![](/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.