我几乎完成了我的项目,只有一件事情还有待改进。Android Asynctask:等待整个计算而不会阻塞UI线程
我的应用程序是一个音乐测验,它可以检索关于作者,歌曲标题,previewUrl ecc的所有信息。从iTunes Store使用适用的搜索API。
当用户选择要使用的流派时,我必须告诉用户等待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();
}
}
}
问题:使用不用彷徨()方法使应用程序等待AsyncTask的整个计算,但它也阻止了UI线程!所以用户将保持5秒或更长时间的黑屏,这不是一件好事!
如果我不使用.get()方法,我会收到一个IndexOutOfBounds异常,因为我开始播放音乐流,但该列表尚未填充。
你能为我提出一个解决这个问题的方法吗?
谢谢!
不要使用get;)只是显示用户一些微调,让他知道他会发生。在收到所有需要的数据后填入你的列表,隐藏微调并开始播放音乐:) – fgeorgiew
如果你不想阻塞线程UI,你不能调用GET。 get() 如果需要等待计算完成,然后检索其结果。 – dougcunha
我注意到在catch(IllegalArgumentException errore){}'你会尝试创建一个AlertDialog。理解这会使您的应用程序崩溃,并尝试从另一个线程访问UI ......您无法/不应该在'doInBackground()'中访问UI。 – Sam