【问题标题】:How to check if Async Task is already running如何检查异步任务是否已在运行
【发布时间】:2012-09-02 14:50:55
【问题描述】:

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

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

是否有办法检查任务是否已经从应用程序的不同实例运行?

【问题讨论】:

  • 产生的错误是什么?我的 AsyncTask 只是挂在 preExecute 上,所以我想知道它是否相关。

标签: android android-asynctask


【解决方案1】:

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

编辑:您应该重新考虑您的实现并将AsyncTask 保存在ServiceIntentService 中以从网络获取您的数据。

【讨论】:

  • 调用 getStatus() 导致空指针异常,但我可以看到异步任务仍在运行..
  • 你是否使用过类似的东西:(yourtask.getStatus() == AsyncTask.Status.RUNNING)
  • 这应该是答案。
  • 不需要带有意图服务的异步任务,因为意图服务已经有工作线程
【解决方案2】:

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

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
}

【讨论】:

  • 感谢您的快速解释
【解决方案3】:

我已经设法用某种单例模式处理了这个问题。 希望对您有所帮助。

// 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) {
        // ...
    }
}

【讨论】:

    【解决方案4】:

    我认为你应该在Android 中检查Application 的概念。 http://developer.android.com/reference/android/app/Application.html

    其实没有

    应用的不同实例

    Application 对于您的所有 Activities/Services. 始终相同 这意味着您已经离开Activity 并再次打开它,可能有两种情况:

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

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

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

    祝你好运!

    【讨论】:

    • 应用程序级别的静态变量似乎是方式。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    相关资源
    最近更新 更多