2017-09-28 58 views
2

我看了線程OkHttpClient cannot cancel Call by tag但它不適用於我。我有一個EditTextTextWatcher使用Google PlacesAutocomplete獲取Places地址,因此每個輸入的字符都是一個新的請求,但是我輸入的每個字符都需要取消先前的請求,所以我沒有收到它的返回,cu'z重要的是最後的地址輸入,我這樣做:如何用OkHttp取消請求Android

更新!

Address.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
      if(Address.getText().toString().length() > 3){ 
       _Address = Address.getText().toString(); 
       if(call != null){ 
        call.cancel(); 
       } 

       Request request = new Request.Builder() 
         .url(getPlaceAutoCompleteUrl(_Address)) 
         .addHeader("content-type", "application/json") 
         .addHeader("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.0.3; en-us; google_sdk Build/MR1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30") 
         .build(); 
       Call call = new OkHttpClient().newCall(request); 
       call.enqueue(new Callback() { 
        @Override 
        public void onFailure(Call call, IOException e) { 

        } 
        @Override 
        public void onResponse(Call call, Response response) throws IOException { 
         Log.d("Response",response.body().string()); 
         PlacePredictions place = LoganSquare.parse(response.body().string(),PlacePredictions.class); 
         if(autoCompleteAdapter == null){ 
          autoCompleteAdapter = new AutoCompleteAdapter(CustomPlaces.this); 
          recyclerView.setAdapter(autoCompleteAdapter); 
          autoCompleteAdapter.Add(place.getPlaces()); 
         }else { 
          autoCompleteAdapter.Clear(); 
          autoCompleteAdapter.Add(place.getPlaces()); 
          autoCompleteAdapter.notifyDataSetChanged(); 
         } 
        } 
       }); 
       //call.cancel(); 
      } 

例外:

E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher 
              Process: com.app, PID: 2660 
              java.lang.IllegalStateException: closed 
               at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:398) 
               at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:392) 
               at okhttp3.internal.Util.bomAwareCharset(Util.java:449) 
               at okhttp3.ResponseBody.string(ResponseBody.java:174) 
               at com.ustork.CustomPlaces$2$1.onResponse(CustomPlaces.java:89) 
               at okhttp3.RealCall$AsyncCall.execute(RealCall.java:153) 
               at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) 
               at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
               at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
               at java.lang.Thread.run(Thread.java:818) 

回答

3

如何是關於嘗試其他方法來您的問題?你可以像這樣用OkHttp不使用asyncTask

Call call = new OkHttpClient().newCall(your request); 
    call.enqueue(new Callback() { // call off UI thread. 
     @Override 
     public void onFailure(Call call, IOException e) { 
      // this is where your call is cancelled: call.isCanceled() 
     } 

     @Override 
     public void onResponse(Call call, Response response) throws IOException { 

     } 
    }); 
    call.cancel(); // this is the proper way to cancel an async call. 

更新

你應該注意到the response body is a one-shot value that may be consumed only once,你應該不叫response.body().string()兩次。只需製作一個本地變量:responseString = response.body().string()並僅使用它。

+0

因此,我可以檢查調用對象是否爲空,然後調用'call.cancel();'每個新的請求?在那種情況下,我會提前?謝謝! –

+0

我試圖用這種方式,但我得到一個致命的異常,我會更新我的代碼! –