2016-03-21 14 views
1

Kullanıcı, metin görünümünde kullanıcı türü olarak harici bir sunucudan önerileri dolduran bir konum önerme etkinliği gerçekleştiriyorum. Metin görünümündeki metin her değiştiğinde önerileri almak için AsyncTask kullanıyorum. Yeni bir harf yazıldığında, zaten var olan görevi iptal ederiz ve yeni bir tane yürütürüz. Çoğu zaman doInBackground, execute sonra çağrılır, ancak diğer zamanlarda birkaç saniye alabilir. (DoInBackground başladığında, performans gayet iyi.)android autocomplete AsyncTask Gecikmesi

Seti dinleyici:

İşte
private void init() { 
    // respond to any text change 
    textView.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void onTextChanged(final CharSequence s, int start, int b, int c) { 
      showSuggestions(s.toString()); 
     } 
    }); 
} 

önceki bir yeni bir görev başlangıç ​​ve iptal:

private void showSuggestions(String query) { 
    // suggestionsTask is an instance variable of the activity 
    if (suggestionsTask != null) { 
     suggestionsTask.cancel(true); 
    } 

    suggestionsTask = new AsyncTask<String, Void, List<Suggestion>>() { 
     @Override 
     protected void onPostExecute(List<Suggestion> resultList) { 
      // set suggestions with adapter - CHANGES STATE 
     } 

     @Override 
     protected List<Suggestion> doInBackground(String... query) { 
      // one local db call for recent searches - DOES NOT CHANGE STATE 
      // one network call to external server - DOES NOT CHANGE STATE 
      // return results 
     } 
    }; 

    suggestionsTask.execute(query); 
} 

daha iyi bir iş parçacığı mekanizması var mı bunun için kullan? Execute ve doInBackground arasında neden gecikme olduğunu biliyor musunuz? AsyncTask reference itibaren

+2

Görevler serileştirilmiş olabilir ve önceki bir görevi iptal etme zamanını alabilir. –

+0

Bu kulağa çok benziyor. Bunu nasıl aşacağına dair bir fikrin var mı? – lf215

cevap

1

:

bir görev (boolean) iptal çağırarak herhangi bir zamanda iptal edilebilir. Bu yöntemin çağrılması, doğrulanabilmesinin isCancelled() öğesine yapılan sonraki çağrılara neden olacaktır. Bu yöntemi çağırdıktan sonra, onPostExecute (Object) yerine onCancelled (Object), doInBackground (Object []) geri döndükten sonra çağrılır. hep mümkünse ([] Nesne) doInBackground gelen periyodik) isCancelled (dönüş değerini kontrol etmelidir bir görev mümkün olduğunca çabuk iptal emin olmak için (örneğin bir döngü içine.)

Yani doInBackground(), doInBackground içinde periyodik olarak ayarlanmış olup olmadığını elle kontrol etmediğiniz sürece doInBackground() adımını iptal etmiyorsunuz. Çoğu Android sürümünde, tüm AsyncTasks tek bir iş parçacığını paylaşır, böylece bir sonraki başlamaya başlamadan önce bitirmesi gerekir. Bu nedenle gecikmenizin nedeni budur, ancak isCancelled() için nerede kontrol edileceğine dair bir öneri bulmak için doInBackground() kodunuzdan yeterli bilgi (yani kodu göndermediniz) yok.

ise nedense, ayrıca ama görünüyor ki yapmaya çalıştığımız şey ile aynı belgeler anlaşılacağı gibi THREAD_POOL_EXECUTOR ile executeOnExecutor(java.util.concurrent.Executor, Object[]) kullanarak, AsyncTasks paralel olarak yürütmek yapma deneyebilirsiniz mümkün değildir önceki görevi iptal edebilmek için Bu, şu anda sahip olduğunuzdan daha kötü olabilecek bazı sinir bozucu iş parçacıklarına neden olabilir.

+0

"... Aynı belgelerdeki gibi THREAD_POOL_EXECUTOR, ancak bunu yapmaya çalıştığınız şey, bazı sinir bozucu iş parçacıklarına neden olabilir gibi görünüyor". Her yeni yürütmeden önce iptal edersem ve bu nedenle yalnızca en son görev PostExecute üzerinde çalışırsa nasıl iş parçacığı sorunları olabilir? Benim sonrası bu içermez ama değiştirilir yalnızca genel devlet OnPostExecute olduğunu ima etmeye çalıştı: akla gelen – lf215

+0

Peki sadece basit örneği "adaptörüyle önerileri ayarla" Farklı iş parçacıklarının üzerinde birden AsyncTasks yürütmek durumunda olduğu İlk başladığın ilk işin biteceğini garanti edemezsin. Böylece daha yavaş ama doğru bir çözümden daha hızlı ama yanlış olana kadar gidebilirdiniz. Elbette iş parçacığı havuzu yürütücüsünü kullanmaya devam edebilirsiniz, ancak hazırlanmakta zorlanan ve daha fazla sinir bozucu olan, sürekli olarak başarısız olan sorunları açar. Öntanımlı yürütücüye bağlı kalmak ve aslında bir önceki görevini doInBackground() içindeki bir döngü ile iptal ettiğinizden emin olmak çok daha kolay olurdu. – ajpolt

+0

Genel durumda size katılıyorum, ama soruya dahil ettiğim kod göz önüne alındığında, değerlendirmenizin burada çok ihtiyatlı/yanlış olduğunu düşünüyorum. "Farklı iş parçacıklarında birden çok AsyncTasks çalıştırırsanız, ilk başladığınızın birincisi olacağını garanti edemezsiniz. İlkini bitiren ilk şey umurumda değil - sadece sonuncusu en son bağdaştırıcıyı değiştirir. THREAD_POOL_EXECUTOR kullanırsam çözümümün yanlış olabileceği ihtimaline açığım ancak yorumlarınızdaki kanıtı göremiyorum. Lütfen daha önceki sorumu ele alalım: "Nasıl olabilir ... onPostExecute?" – lf215