【发布时间】: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
【问题讨论】: