![](/img/trans.png)
[英]How to make a Main Thread waiting for the AsyncTask android, without blocking the UI
[英]Android Asynctask: wait for entire computation without blocking UI thread
我的項目幾乎完成了,剩下的只有一件事需要改進。
我的應用程序是一個音樂測驗,它檢索有關作者,歌曲標題,previewUrl ecc的所有信息。 使用相應的Search API從Itunes商店中獲取。
當用戶選擇要播放的流派時,我必須告訴用戶等待4到5秒鍾,因為計算將填充包含所有信息的列表。
我調用Asynctask來檢索這些信息,如下所示:
JsonCanzoni recuperoCanzoni = new JsonCanzoni(arrayGenere,Canzone.this);
try {
recuperoCanzoni.execute().get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
執行這些操作的類(擴展了Asynctask)如下:
class JsonCanzoni extends AsyncTask<Void, Void, Void>
{
List<String> canzoni = new ArrayList<String>(5);
ProgressDialog pDialog;
int[] arrayGenere;
Context context;
public JsonCanzoni(int[] arrayGenere,Context context)
{
this.arrayGenere = arrayGenere;
this.context = context;
}
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pDialog.dismiss();
}
@Override
protected void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Preparazione round...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected Void doInBackground(Void... params)
{
try
{
int randomLookupId = 0;
JSONObject obj;
JSONArray jsonArray;
for(int i = 0; i < 10; i++)
{
canzoni = new ArrayList<String>();
Log.d("GENERE", arrayGenere.toString());
obj = getJSONObject(scegliClassifica(arrayGenere));
jsonArray = obj.getJSONArray("resultIds");
Log.d("dimensione JsonArray", String.valueOf(jsonArray.length()));
try
{
randomLookupId = new Random().nextInt(jsonArray.length()-1);
}
catch(IllegalArgumentException errore)
{
new AlertDialog.Builder(context)
.setTitle("Connessione non attiva!")
.setMessage("Connessione di rete debole, uscita dal programma!");
}
Log.d("randomLookupID", String.valueOf(randomLookupId));
JSONObject finalObj = getJSONObject("http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
Log.d("URL","http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
while(finalObj.getJSONArray("results").length() == 0)
{
Log.d("Array VUOTO!!","Non è possibile!!!!");
randomLookupId = new Random().nextInt(jsonArray.length()-1);
Log.d("randomID rigenerato", String.valueOf(randomLookupId));
finalObj = getJSONObject("http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
Log.d("URL Rigenerato","http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
}
JSONArray finalJsonArray = finalObj.getJSONArray("results");
JSONObject returnObj = finalJsonArray.getJSONObject(0);
Log.d("returnObj.length",String.valueOf(returnObj.length()));
canzoni.add(returnObj.getString("previewUrl"));
canzoni.add(returnObj.getString("artistName"));
canzoni.add(returnObj.getString("trackName"));
canzoni.add(returnObj.getString("artistViewUrl"));
canzoni.add(returnObj.getString("artworkUrl100"));
// GTTapp app=(GTTapp) ((Activity)context).getApplication();
// app.dieciCanzoni;
Canzone.dieciCanzoni.add(i, new ArrayList<String>(canzoni));
}
}
catch (JSONException ignored)
{
ignored.getCause();
}
catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private String scegliClassifica(int[] arrayGenere)
{
int randomArrayPosition = new Random().nextInt(arrayGenere.length);
return "http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/charts?cc=us&g="+arrayGenere[randomArrayPosition]+"&name=Songs&limit=200";
}
JSONObject getJSONObject(String url) throws IOException, MalformedURLException, JSONException
{
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
InputStream in = conn.getInputStream();
try
{
StringBuilder sb = new StringBuilder();
BufferedReader r = new BufferedReader(new InputStreamReader(new DoneHandlerInputStream(in)));
for (String line = r.readLine(); line != null; line = r.readLine())
{
sb.append(line);
}
return new JSONObject(sb.toString());
}
finally
{
in.close();
}
}
}
問題:使用.get()方法使應用程序等待AsyncTask的整個計算,但是它也會阻塞UI線程! 因此,用戶將在黑屏上停留5秒鍾或更長時間,這不是一件好事!
如果我不使用.get()方法,則會收到IndexOutOfBounds異常,因為我開始播放音樂流,但列表尚未填寫。
您能建議我解決這種情況嗎?
謝謝!
刪除.get()
它將阻塞用戶界面,直到任務完成。
啟動任何依賴於AsycTask
任務(如播放視頻)
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pDialog.dismiss();
//You can start music stream here
}
get()調用被阻止。 從文檔:
必要時等待計算完成,然后檢索其結果。
您應該做的是在開始播放音樂之前異步等待計算完成。
如果不想在類外公開asynctask,則可以在JSonCanzoni類中設置一個回調,以在asynctask的onPostExecute方法中調用。
就像是
public interface CanzoniDownloadedInterface {
public void onCanzoniDownloaded();
}
public JsonCanzoni(int[] arrayGenere, CanzoniDownloadedInterface callback, Context context){
this.arrayGenere = arrayGenere;
this.context = context;
this.callback = callback;
}
並在您的onPostExecute()中:
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
this.callback.onCanzoniDownloaded();
pDialog.dismiss();
}
如果讓您的活動實現該接口,則可以將其傳遞給您的班級。
您需要開始播放onCanzoniDownloaded()實現。
終於我解決了我的問題,一些建議很好,對我有很大幫助!
我只是將startActivity指令移至JsonCanzoni AsyncTask的onPostExecute,並更改了一些代碼以適應新版本,沒關系! ;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.