Activity 线程完成后不停止

Activity not stopping when finished froim thread

我有一个 Splashscreen,其中我是 运行 动画。以下是我关于从 初始屏幕 移动到 MainActivity.

的逻辑

启动画面的最短可见时间 = minTime

启动画面的最长可见时间 = maxTime

API 被调用,它会在一段时间内得到响应 - apiTime

1. 显示 启动画面 至少 minTime.

2. 呼叫 API。如果 API 的响应在不到 maxtime 的时间内收到, 立即移动到下一个屏幕,否则,移动到下一个屏幕 maxtime

以下是我的代码:

public class SplashActivity extends AppCompatActivity {

private ImageView container;
private AnimationDrawable animationDrawable;
int apiTime = 2000, minTime = 1000, maxTime = 5000;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    container = findViewById(R.id.iv_icons);
    container.setBackgroundResource(R.drawable.splash_animation);

    animationDrawable = (AnimationDrawable) container.getBackground();
}

@Override
protected void onResume() {
    super.onResume();
    animationDrawable.start();
    final long start = System.currentTimeMillis();

    //calling api in thread simultaneously. As soon as response is received, move to next screen.
    //Thread.sleep is just dummy for api response time
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(apiTime);
                //if apiTime is less than minTime, then we wait till minTime
                long time = minTime - (System.currentTimeMillis() - start);
                if (time > 0) {
                    Thread.sleep(time);
                }
                moveToNextScreen();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    t1.start();

    hardMoveToNextScreen();
}

private void moveToNextScreen() {
    Intent i = new Intent(SplashActivity.this, MainActivity.class);
    startActivity(i);
    finish();
}

private void hardMoveToNextScreen () {
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            moveToNextScreen();
        }
    }, maxTime);
}

}

现在,根据我使用的时间值,线程 t1 在方法 hardMoveToNextScreen() 调用相同方法之前调用方法 moveToNextScreen()。所以,一旦 activity 完成,我应该移动到 MainActivity.

我面临的问题是 MainActivity 打开了两次。一次来自线程,然后来自 hardMoveToNextScreen() 方法。但是,这不应该发生,因为我已经在调用 finish(),这意味着一旦我移动到 MainActivity,就不应该再调用 SplashActivity 中的任何方法。

我做错了什么?

您正在调用 moveToNextScreen() 两次。第一次在线程中,第二次在 hardMoveToNextScreen() 中。

如果删除 hardMoveToNextScreen();在 t1.start() 之后;它应该适合你。

或者更好的选择是删除 Thread 并使用带有处理程序的 hardMoveToNextScreen() 方法。

更新的答案:

如果要保持双重逻辑声明全局变量:

private boolean activityFinished = false;

然后将 moveToNextScreen() 方法更改为:

private void moveToNextScreen() {
    if( !activityFinished ) {
        Intent i = new Intent( SplashActivity.this, MainActivity.class );
        startActivity( i );
        finish();
        activityFinished = true;
    }
}

所以首先我会告诉你发生这种情况的原因,然后我会继续解决这个问题。

原因:

即使在调用 onDestroy() 方法后,activity 实例仍保留在内存中。现在这并不意味着 activity 实例将永远保留在那里。它根据系统的内存要求由 Android OS 销毁。 这在这个答案中有很好的描述- What is Activity.finish() method doing exactly? 在这一个里—— Activity instance remains in the memory after onDestroy() (此外,Whosebug 上有很多描述完全相同的事情的答案。只需搜索即可)。

解决方案:

使用 returns 布尔值 isDestroyed() 方法检查是否调用了 activity 的 onDestroy() 方法。您可以在此处找到它的文档 - https://developer.android.com/reference/android/app/Activity.html#isDestroyed%28%29

所以 moveToNextScreen() 方法现在应该看起来像这样 -

private void moveToNextScreen() {
    if (!isDestroyed()) {
        Intent i = new Intent(SplashActivity.this, MainActivity.class);
        startActivity(i);
        finish();
    }
}