34

起動時に集中的なデータベース操作を行う必要があるアプリがあります。アプリは電話の連絡先のローカルコピーを保持し、起動時にAndroidの連絡先データベースと同期します。

ユーザーがアプリを起動すると、データベースの同期をバックグラウンドで実行する非同期タスクが開始されます。ユーザーがアプリを閉じると、操作は続行されますが、これは問題ありません。ただし、ユーザーがアプリを再度開くと、非同期タスクが開始され、エラーが発生します。

タスクがアプリの別のインスタンスからすでに実行されているかどうかを確認する方法はありますか?

4

4 に答える 4

97

getStatus()のステータスを取得するために使用しますAsyncTask。ステータスがAsyncTask.Status.RUNNINGの場合、タスクは実行中です。

編集:あなたはあなたの実装を再考し、AsyncTaskおそらくウェブからあなたのデータをフェッチするためにServiceまたはに保持する必要があります。IntentService

于 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

Applicationの概念を確認する必要があると思いますAndroidhttp://developer.android.com/reference/android/app/Application.html

実際、そのようなものはありません

アプリの別のインスタンス

。これApplicationは、すべてのユーザーにとって常に同じです。Activities/Services. つまり、を離れActivityて再度開いたということです。2つのケースが考えられます。

  1. システムはすでにアプリケーションを強制終了しました。この場合AsyncTask、すでに死んでいて、新しいものを始めても安全です
  2. Applicationまだ生きていたので、AsyncTaskおそらくまだ実行中です。

AsyncTask2番目のケースでは、これまたはその状態を指すいくつかの静的変数を使用することをお勧めします。2回目に開いたときにアプリがまだ有効であった場合、すべての静的参照は引き続き有効であるため、正常に操作できます。

PS:ちなみに、現在のアプローチでは、アプリケーションはいつでもシステムによって終了される可能性があることに注意してください。したがってAsyncTask、いつでも中断することができます。それはあなたにとって大丈夫ではありません-チェックしてくださいIntentServices-バックグラウンド操作の目的のために特別に設計されたコンポーネント。http://developer.android.com/reference/android/app/IntentService.html

幸運を!

于 2012-09-02T14:58:36.957 に答える