2017-07-10 7 views
0

私はAndroidライブラリプロジェクトでネットワークのメインスレッドの例外を回避するためにAsyncTaskを使用しています。今、私の変数に返される値を取得し、次のコード行を実行するまで待機します。私はCountDownLatchを使ってこれを行った。Android:AsyncTask onPostExecuteに到達しない

私のリクエストを実行し、AsyncTaskを呼び出す方法は以下の通りです。返す値を返す前にCountDownLatchを使用して応答を待ちます。

public MyObject getMyObject(){ 

    final String url = "http://[myip]:8080/retrieve"; 

    try{ 
     Response response = executeRequest(url); 
     final MyObject myObject = om.readValue(response.body().string(), 
       new TypeReference<MyObject>() { 
       }); 
     return myObject; 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return null; 

} 



private Response executeRequest(String url){ 

    try { 
     //Simplified please just ignore this.. 
     GenericAsyncParams genericAsyncParams = createParams(......); 

     final CountDownLatch countDownLatch = new CountDownLatch(1); 
     ResponseListener responseListener = new ResponseListener(countDownLatch); 
     MyAsyncTask myAsyncTask = new AsyncTask(responseListener); 
     myAsyncTask.execute(genericAsyncParams); 
     countDownLatch.await(); 

     //get the response from the listener class. 
     Response response = responseListener.getResponse(); 
     return response; 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    return null; 
    } 

私はAsyncTaskのonPostExecuteにはsetResponseを呼んで、私はまた、asyncTask.execute(引数)に.get()が例外を引き起こす可能性があることを承知していますので、私は、発信者からの値を更新するリスナーを使用しました。

public class ResponseListener { 

    private static final String TAG = ResponseListener.class.getName(); 

    private Response response; 
    private CountDownLatch countDownLatch; 

    public ResponseListener(CountDownLatch countDownLatch) { 
     this.response = null; 
     this.countDownLatch = countDownLatch; 
    } 

    public void setResponse(Response response){ 
     this.response = response; 
     Log.e(TAG, "Executing countdown.."); 
     countDownLatch.countDown(); 
    } 

    public Response getResponse() { 
     return response; 
    } 

    public CountDownLatch getCountDownLatch() { 
     return countDownLatch; 
    } 
} 

は今、これは私のAsyncTask 。注:のRequestProcessorはokHttpのラッパークラスです。

public class MyAsynctask extends AsyncTask<GenericAsyncParams, Void, Response>{ 


    private static final String TAG = MyAsyncTask.class.getName(); 

    private ResponseListener listener; 

    public MyAsynctask(ResponseListener listener) { 
     this.listener = listener; 
    } 

    @Override 
    protected Response doInBackground(GenericAsyncParams... genericAsyncParamses) { 
     Response response = null; 
     GenericAsyncParams genericAsyncParams = genericAsyncParamses[0]; 
     String url = genericAsyncParams.getUrl(); 
     String method = genericAsyncParams.getMethod(); 
     RequestProcessor requestProcessor = genericAsyncParams.getRequestProcessor(); 

     try { 
      Request.Builder builder; 
      if(method.equalsIgnoreCase("POST")){ 
       builder = new Request.Builder() 
         .post(genericAsyncParams.getRequestBody()) 
         .url(url) 
         .headers(headers); 
      } else { 
       builder = new Request.Builder() 
         .headers(headers) 
         .get() 
         .url(url); 
      } 
      final Request request = builder.build(); 
      response = requestProcessor.client().newCall(request).execute(); 
      Log.d(TAG, "returning okHttp response.."); 
      return response; 
     } catch (Exception e){ 
      Log.e(TAG, String.format("ERROR.. %s", ExceptionUtils.getMessage(e))); 
     } 

     return response; 
    } 


    @Override 
    protected void onPostExecute(Response response) { 
     if(listener != null){ 
      Log.d(TAG, "Updating response : onPostExecute.."); 
      listener.setResponse(response); 
     } else { 
      super.onPostExecute(response); 
     } 
    } 

} 

私のログの最後の行は

07-10 23: 47:07.008 28409-28530/com.aaron.android.android.lib D/com.aaron.android.android.lib.api.tasks.MyAsyncTask: returning okHttp response.. 
+0

どのクラスに 'executeRequest()'が含まれていますか? –

+0

プロジェクト全体で使用されるUtilクラス内の共通コードです。 – Aaron

+0

あなたのコードにそのことを示して、それがどのように呼び出されたかの例を示してください。 –

答えて

5

NetworkOnMainExceptionメインUIスレッドをブロックしないように私たちを思い出させています。ただし、応答を待つためにCountDownLatchを使用してブロックしています。メインスレッドでonPostExecute()が実行されているため、実行をブロックしています。ネットワーク接続が完了するのを待つ間、メインスレッドをブロックすることはできません。代わりに、UIが適切に応答できるように、executeRequest()を返すようにしてください。

+0

これは今私にとって意味があると思うので、私のコードをリファクタリングする必要があります。なぜなら、現在のところ、Asyncの唯一の部分はApplication Projectに公開するインターフェイスだからです。ネットワークコールなどの他のコンポーネントは非同期ではなく、APIに返される必要があるデータを収集するために使用するサービス(Androidサービスではなく、サービスのみ)の各戻り値を待ちます(私のライブラリは私が作成した)。とにかく、これは非常に大きな助けと私はリファクタリングがたくさんあります。ありがとう@コード弟子! – Aaron

関連する問題