2017-09-28 4 views
1

je dois être en mesure de MANAGER certaines demandes avec OKHTTP, en utilisant le Google Places AutoComplete pour recevoir quelques prédictions en tapant l'adresse. Le Problème est Chaque fois que j'insère un CHAR il fera une nouvelle demande mais en même temps j'ai besoin d'annuler le précédent! Ex: New York City = 13 demandes en même temps! Donc j'utilise une seule instance de Call en essayant d'annuler tout ce qui a été demandé mais sans succès. C'est ce que j'ai fait!Comment annuler la demande à l'aide OKHTTP

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 = client.newCall(request); 


       call.enqueue(new Callback() { 
        public void onResponse(Call call, final Response response) throws IOException { 
         final String result = response.body().string(); 
         runOnUiThread(new Runnable() { 
          @Override 
          public void run() { 
           Log.d("Response",result); 
           PlacePredictions place = null; 
           try { 
            place = LoganSquare.parse(result,PlacePredictions.class); 
           } catch (IOException e) { 
            e.printStackTrace(); 
           } 
           if(autoCompleteAdapter == null){ 
            autoCompleteAdapter = new AutoCompleteAdapter(CustomPlaces.this); 
            recyclerView.setAdapter(autoCompleteAdapter); 
            autoCompleteAdapter.Add(place.getPlaces()); 
           }else { 
            autoCompleteAdapter.Clear(); 
            autoCompleteAdapter.Add(place.getPlaces()); 
            autoCompleteAdapter.notifyDataSetChanged(); 
           } 
          } 
         }); 
        } 
        public void onFailure(Call call, IOException e) { 
         //fail(); 
        } 
       }); 
      }else { 
       if(autoCompleteAdapter != null){ 
        autoCompleteAdapter.Clear(); 
       } 
      } 
     } 

Je vérifie si l'objet call est nul et annuler la demande, mais garde encore à venir!

+0

Pourquoi créez-vous une requête pour chaque lettre tapée par l'utilisateur? Ajouter un délai d'attente (1 seconde par exemple) et envoyer une requête uniquement si l'utilisateur n'a rien tapé pendant 1 seconde. Je peux fournir un exemple de code. – babay

+0

Ce serait génial si vous fournissez, merci! –

Répondre

2

Qu'en est-ce qui suit:

  //Set tags for your requests when you build them: 
      Request request = new Request.Builder(). 
      url(url).tag("requestKey").build(); 

      //When you want to cancel: 
      //A) go through the queued calls and cancel if the tag matches: 
      for (Call call : mHttpClient.dispatcher().queuedCalls()) { 
       if (call.request().tag().equals("requestKey")) 
        call.cancel(); 
      } 

      //B) go through the running calls and cancel if the tag matches: 
      for (Call call : mHttpClient.dispatcher().runningCalls()) { 
       if (call.request().tag().equals("requestKey")) 
        call.cancel(); 
      } 
+0

Très bien, je vais laisser le code tel qu'il est, j'ai juste besoin d'ajouter un tag avec ma demande et les deux "for" à droite? donc à chaque fois que j'ajoute un nouveau char je fais le pour et ça empêchera que la réponse revienne? –

+0

Vous devez d'abord annuler, demander après (de sorte que vous n'annulez pas le nouveau) :-) Refactor cancelPending dans une méthode. – TomerBu

+0

Je vais essayer! Merci! –

1

Délai de demande au serveur et afficher uniquement si l'entrée n'a pas changé pour le délai d'attente (1000 ms, réglez pour une meilleure sensation). Vous pouvez ajouter une méthode d'annulation à GetHintsRequest

... 
    Address.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void afterTextChanged(Editable s) { 
      if (s.length() < 3) { 
       if (autoCompleteAdapter != null) { 
        autoCompleteAdapter.Clear(); 
       } 
       return; 
      } 

      GetHintsRequest request = new GetHintsRequest(s.toString(), new GetHintsRequest.GetHintsCallback() { 
       @Override 
       public boolean isRequestNotChanged(String oldRequest) { 
        return Address.getText().toString().equals(oldRequest); 
       } 

       @Override 
       public void onGotHints(String request, PlacePredictions predictions) { 
        if (autoCompleteAdapter == null) { 
         autoCompleteAdapter = new AutoCompleteAdapter(CustomPlaces.this); 
         recyclerView.setAdapter(autoCompleteAdapter); 
         autoCompleteAdapter.Add(place.getPlaces()); 
        } else { 
         autoCompleteAdapter.Clear(); 
         autoCompleteAdapter.Add(place.getPlaces()); 
         autoCompleteAdapter.notifyDataSetChanged(); 
        } 
       } 
      }); 
      request.postCheck(); 
     } 
    }); 
... 

public class GetHintsRequest { 
    private static final long TIMEOUT_MS = 1000; // timeout 
    private final String requestText; 
    private final GetHintsCallback callback; 
    // android.os.Handler, can be used to post and delayed post to main thread. activity.runOnUiThread uses it 
    private final Handler handler = new Handler(Looper.getMainLooper()); 

    public GetHintsRequest(String requestText, GetHintsCallback callback) { 
     this.requestText = requestText; 
     this.callback = callback; 
    } 

    public void postCheck() { 
     handler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       if (callback.isRequestNotChanged(requestText)){ 
        execute(); 
       } 
      } 
     }, TIMEOUT_MS); 
    } 


    public void execute() { 
     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 = client.newCall(request); 

     call.enqueue(new Callback() { 
      public void onResponse(Call call, final Response response) throws IOException { 
       final String result = response.body().string(); 
       handler.post(new Runnable() { 
        @Override 
        public void run() { 
         Log.d("Response", result); 
         PlacePredictions place = null; 
         if (callback.isRequestNotChanged(requestText)) { 
          try { 
           place = LoganSquare.parse(result, PlacePredictions.class); 
          } catch (IOException e) { 
           e.printStackTrace(); 
           return; 
          } 
          callback.onGotHints(requestText, place); 
         } 
        } 
       }); 
      } 

      public void onFailure(Call call, IOException e) { 
       //fail(); 
      } 
     }); 
    } 

    public interface GetHintsCallback { 
     boolean isRequestNotChanged(String oldRequest); 

     void onGotHints(String request, PlacePredictions predictions); 
    } 

} 
+0

Merci! j'essaierai. Le plus gros problème pour moi est d'annuler la demande chaque fois que je mets quelque chose. –