34

我有一个应用程序需要在启动时进行密集的数据库操作。该应用程序保存手机上联系人的本地副本,并在启动时与 android 联系人数据库同步。

如果用户启动应用程序,则会启动一个在后台执行数据库同步的异步任务。如果用户关闭应用程序,操作会继续运行,这很好。但是,如果用户再次打开应用程序,则会启动异步任务并产生错误。

无论如何检查任务是否已经从应用程序的不同实例运行?

4

4 回答 4

97

用于getStatus()获取您的AsyncTask. 如果状态为,AsyncTask.Status.RUNNING则您的任务正在运行。

编辑:您应该重新考虑您的实施并将AsyncTask可能的保留在ServiceIntentService从网络上获取您的数据。

于 2012-09-02T14:55:39.363 回答
35

是的,伙计们,这些是一些例子。

LoadMusicInBackground lmib = new LoadMusicInBackground();

if(lmib.getStatus() == AsyncTask.Status.PENDING){
    // My AsyncTask has not started yet
}

if(lmib.getStatus() == AsyncTask.Status.RUNNING){
    // My AsyncTask is currently doing work in doInBackground()
}

if(lmib.getStatus() == AsyncTask.Status.FINISHED){
    // My AsyncTask is done and onPostExecute was called
}
于 2014-07-10T07:22:04.577 回答
7

我已经设法用某种单例模式处理了这个问题。希望能帮助到你。

// fill the places database from a JSON object
public class myAsyncTask extends AsyncTask<Void,Integer,Integer> {

    Activity mContext = null;
    static AsyncTask<Void,Integer,Integer> myAsyncTaskInstance = null; 

    // Private Constructor: can't be called from outside this class
    private myAsyncTask(Activity iContext) {
        mContext = iContext; 
    }

    public static AsyncTask<Void, Integer, Integer> getInstance(Activity iContext) {
        // if the current async task is already running, return null: no new async task 
        // shall be created if an instance is already running
        if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.RUNNING) {
            // it can be running but cancelled, in that case, return a new instance
            if (myAsyncTaskInstance.isCancelled()) {
                myAsyncTaskInstance = new myAsyncTask(iContext);
            } else {
                // display a toast to say "try later"
                Toast.makeText(iContext, "A task is already running, try later", Toast.LENGTH_SHORT).show();    

                return null;
            }
        }

        //if the current async task is pending, it can be executed return this instance
        if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.PENDING) {
            return myAsyncTaskInstance;
        }

        //if the current async task is finished, it can't be executed another time, so return a new instance
        if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.FINISHED) {
            myAsyncTaskInstance = new myAsyncTask(iContext);
        }


        // if the current async task is null, create a new instance
        if (myAsyncTaskInstance == null) {
            myAsyncTaskInstance = new myAsyncTask(iContext);
        }
        // return the current instance
        return myAsyncTaskInstance;
    }

    @Override
    protected Integer doInBackground(Void... iUnUsed) {
        // ...
    }
}
于 2013-05-05T13:24:31.653 回答
3

我认为您应该检查Applicationin的概念Androidhttp://developer.android.com/reference/android/app/Application.html

事实上,没有这样的事情

应用程序的不同实例

. 对你所有的Application人来说总是一样的Activities/Services. 这意味着你已经离开Activity并再次打开它,2种情况是可能的:

  1. 系统已经杀死了您的应用程序。在这种情况下AsyncTask已经死了,可以安全地开始一个新的
  2. Application还活着,所以可能AsyncTask还在运行。

在第二种情况下,我建议使用一些静态变量,指向这个AsyncTask或它的状态。如果您的应用在第二次打开时仍然存在 - 所有静态引用仍然有效,因此您可以成功操作。

PS:顺便说一下,在当前方法中,请注意您的应用程序可以随时被系统终止。所以AsyncTask可以随时被打断。它不适合您 - 请检查IntentServices- 组件,专为后台操作目的而设计。http://developer.android.com/reference/android/app/IntentService.html

祝你好运!

于 2012-09-02T14:58:36.957 回答