【问题标题】:AsyncTask does not run on next Activity invocationAsyncTask 不会在下一次 Activity 调用时运行
【发布时间】:2012-01-23 04:25:46
【问题描述】:

在我的初始屏幕活动中,我运行了一些冗长的初始化。所以我创建了一个后台异步任务并执行它来完成繁重的工作。然后主 Activity (UI) 线程显示初始屏幕图像并从 onCreate() 方法返回,这会导致屏幕更新。当异步任务完成时,它会调用启动屏幕活动上的一个方法,该方法会调用主活动并自行终止。

这在应用程序第一次运行时非常有效。如果我终止应用程序然后重新启动它,则会创建一个全新的 Async 任务,并且在调用 execute 方法时会调用 onPreExecute() 方法,但在第二次运行时不会调用 doInBackground() 方法。

如果我使用任务管理器强行杀死应用程序,那么它可以正常工作。当应用程序完成(显示设备主屏幕)但尚未被操作系统回收时,就会出现此问题。

我创建了一个全新的 Async Task 对象,并在调用 execute() 方法之前检查它是否未被取消。就好像异步任务记住了前一个实例并且无法启动新的异步任务,因为它认为它已经执行了一次。

为什么全新的Async Task在调用execute时没有调用doInBackground()方法?

异步任务代码:

public class AsynchTaskInitializeApplication extends AsyncTask<Void, Integer, Boolean> {

    private ActivitySplashScreen theActivity;

    public AsynchTaskInitializeApplication() {
            Log.d("App", "AsynchTaskInitializeApplication constructor called\n");
    }

    public void setTheActivity(ActivitySplashScreen theActivity) {
            Log.d("App", "AsynchTaskInitializeApplication::setTheActivity() called\n");
            this.theActivity = theActivity;
    }

    @Override
    protected Boolean doInBackground(Void... arg0) {
            boolean result = false;

            Log.d("App", "AsynchTaskInitializeApplication::doInBackground() called\n");

            try {
                    // Initialization code goes here
                    result = true;
            } catch (Exception e) {
                    // Something went wrong - we failed.
                    // Return false result.
                    e.printStackTrace();
            }

            return result;
    }

    @Override
    protected void onPreExecute() {
            super.onPreExecute();
            Log.d("App", "AsynchTaskInitializeApplication::onPreExecute() called\n");
    }

    @Override
    protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);

            if (this.theActivity != null) {
                    this.theActivity.initializationComplete(result);
            }
    }
}

创建/调用代码:

    // Start the asynchronous task that starts the data store and does
    // any other heavy hitting initialization.
    this.mBackgroundInitialization = null;
    this.mBackgroundInitialization = new AsynchTaskInitializeApplication();
    this.mBackgroundInitialization.setTheActivity(this);
    Log.d("App", "ActivitySplashScreen::onCreate() start the background initialization\n");
    if (this.mBackgroundInitialization.isCancelled()) {
            Log.d("App", "ActivitySplashScreen::onCreate() background initialization task already cancelled\n");
    }       
    this.mBackgroundInitialization.execute();
    Log.d("App", "ActivitySplashScreen::onCreate() background initialization should have started\n");

后台任务完成时调用的代码:

    public void initializationComplete(boolean readyToGo) {
    Log.d("App", "Initialization is complete " + readyToGo + "\n");
    // Attempt to forcibly stop the background task.
    // A second attempt to run the app does not cause it to execute. 
    if (!this.mBackgroundInitialization.isCancelled()) {
            this.mBackgroundInitialization.cancel(true);
    }
    this.mBackgroundInitialization = null;

    // Display the home screen
    Intent homeScreenIntent = new Intent(context, ActivityHomeScreen.class);
    try {   
           startActivity(homeScreenIntent);

           // And quit this activity so that when the home screen activity
           // finishes then the application finishes
           this.finish();
    } catch(ActivityNotFoundException e) {
            errorMessage = "Cannot find activity for intent: " + homeScreenIntent.toString();
    } catch(Exception e) {
            errorMessage = "Unknown exception when launching intent: " + homeScreenIntent.toString();
    }
    Log.e("App", errorMessage);
    this.finish();
    }

第一次运行成功案例的logcat输出,注意doInBackground()方法宣告自己,初始化完成:

01-22 23:59:30.133 10195 10195 D App: AsynchTaskInitializeApplication constructor called
01-22 23:59:30.133 10195 10195 D App: AsynchTaskInitializeApplication::setTheActivity() called
01-22 23:59:30.133 10195 10195 D App: ActivitySplashScreen::onCreate() start the background initialization
01-22 23:59:30.133 10195 10195 D App: AsynchTaskInitializeApplication::onPreExecute() called
01-22 23:59:30.133 10195 10195 D App: ActivitySplashScreen::onCreate() background initialization should have started
01-22 23:59:30.157 10195 10207 D App: AsynchTaskInitializeApplication::doInBackground() called
01-22 23:59:30.477 10195 10195 D App: Initialization is complete true

doInBackground() 未运行的第二次运行的 logcat 输出:

01-23 00:02:45.868 10195 10195 D App: AsynchTaskInitializeApplication constructor called
01-23 00:02:45.868 10195 10195 D App: AsynchTaskInitializeApplication::setTheActivity() called
01-23 00:02:45.868 10195 10195 D App: ActivitySplashScreen::onCreate() start the background initialization
01-23 00:02:45.868 10195 10195 D App: AsynchTaskInitializeApplication::onPreExecute() called
01-23 00:02:45.868 10195 10195 D App: ActivitySplashScreen::onCreate() background initialization should have started

【问题讨论】:

    标签: android android-asynctask


    【解决方案1】:

    我认为您的答案不仅仅在于使用 onCreate() 方法。如果你熟悉 Activity 生命周期:http://developer.android.com/reference/android/app/Activity.html

    您知道,当您的应用进入不同的状态时,您可以调用不同的方法来处理新的状态。在这种情况下,您要确保就像您第一次运行应用程序时一样,似乎导致问题的 AsyncTask 已被销毁。使用:

        myAsyncTask.cancel();
    

    您的应用尝试结束任务的适当位置。

    http://developer.android.com/reference/android/os/AsyncTask.html

    【讨论】:

    • Flynn 在我添加示例代码之前添加了这条评论。代码路径中有一个明确的取消导致我出现问题。 onPause() 中也有一个,以防在初始化完成之前暂停应用程序之前发生。
    【解决方案2】:

    我建议记录异步任务的状态。

    【讨论】:

    • 好主意。不知道你能得到那个(我必须阅读文档,我必须阅读文档)。我会看看它说什么。
    • 你可以使用 getStatus() 方法返回 AsyncTask.Status 枚举。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 1970-01-01
    相关资源
    最近更新 更多