1

次のコードの実行中は、途中でも実行を停止できるようにしたいと思います。たとえば、私が持っている場合、このスレッド/クラスboolean x = true;にコマンドの王様を送りたいと思います。stop(ReadJSONFeedMainTask);で発生している可能性があるものも含めて、すべてをキャンセルしたいと思いonPostExecute()ます。これどうやってするの?

これが私のコードです:

private void doStuff() {
    new ReadJSONFeedMainTask().execute(urlString);
}

private class ReadJSONFeedMainTask extends AsyncTask<String, Void, String> {
    protected String doInBackground(String... urls) {
        return Helper.readJSONFeed(urls[0]);
    }

    protected void onPostExecute(String result) {

        try {      
            dictItems = new ArrayList<HashMap<?, ?>>();
            JSONArray jsonArray = new JSONArray(result);
            Log.i("JSON", "Number of items in feed: " + jsonArray.length());

            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);

                HashMap<String, String> map = new HashMap<String, String>();

                Iterator<?> it = jsonObject.keys();
                while (it.hasNext())
                {
                      // do a bunch of time consuming stuff
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }  
    }
}
4

4 に答える 4

2

タスクをキャンセルするには、asyncTaskVariable.cancel()を実行します。すでにonPostExecuteにある場合は、それを終了する必要があります。UIスレッドを使用しているため、強制終了できません。最善の方法は、(もちろん別のスレッドから)終了するように指示する変数を設定し、その変数を定期的にチェックして、設定されている場合は返すようにすることです。

于 2012-11-15T19:31:37.910 に答える
2

xが真の場合はスキップしてください

 while (it.hasNext() && x == false) // where x is your skip boolean
 {
      // do a bunch of time consuming stuff
 }

終了したい他の方法でも同様のことを行います。

異常な動作を引き起こす可能性があるため、フローの途中で終了するよりもはるかに安全です。

于 2012-11-15T19:32:19.657 に答える
2

あなたは電話する必要があります

asyncTaskVariable.cancel( true );

これにより、非同期タスクが強制的に停止されます。

しかし、それはすぐには止まらないことを知っておく必要があります。

スレッドがIO入力を待機している場合、スレッドは「ブロックされたio状態」になります。その後、停止しません。このヘルパーメソッドで何が発生するかを制御できない場合は、何も変更できません。ただし、所有している場合は、入力ストリームをループして、毎回(バッファーを使用して)バイト数ずつ読み取ることができます。これにより、スリーアドを停止する機会が与えられます。そのために次のようなことをします

int readBytes = 0;
while( readBytes != -1 && !Thread.interrupted ) {
   readBytes = bufferedReader.read( buffer );
   if( readBytes >0 ) { 
      stringBuilder.append( buffer, 0, readBytes ); 
   }
}

フラグを使用するinterruptedと、非同期タスクがキャンセルされたときにスレッドを停止できます。

AsyncTaskネットワーク操作にを使用しないことを検討する必要があります。それらは短命の仕事のために設計されました。

AsyncTaskは、スレッドとハンドラーの周りのヘルパークラスになるように設計されており、一般的なスレッドフレームワークを構成しません。AsyncTasksは、理想的には短い操作(最大で数秒)に使用する必要があります。スレッドを長期間実行し続ける必要がある場合は、java.util.concurrentpacakgeによって提供されるさまざまなAPIを使用することを強くお勧めします。 Executor、ThreadPoolExecutorおよびFutureTask。

別の方法は、 RoboSpiceライブラリのようにAndroidサービスを使用することです。

于 2012-11-15T19:48:14.073 に答える
1

そのためには、クラスへの参照を保持する必要があります。例えば...

private ReadJSONFeedMainTask foo;

private void doStuff() {
    foo = new ReadJSONFeedMainTask();
    foo.execute(urlString);
}

その後、割り込みイベントが発生したときに、電話をかけることができます

foo.cancel(true);

trueパラメータは、即時割り込みを示します。

編集 私は、実行後の長時間実行タスクの配置に気づきませんでした。gabeが正しく述べたように、cancel()でさえそこでは役に立ちません。上記のようにコードへの参照を保持することに加えて、コードをリファクタリングして、実行時間の長いタスクをdoInBackgroundメソッドに配置し、すぐにキャンセルできるようにする必要があります。

于 2012-11-15T19:34:42.500 に答える