我差不多完成了我的项目,只有一件事需要改进。
我的应用是一个音乐测验,可以检索有关作者,歌曲标题,previewUrl ecc的所有信息。来自Itunes商店使用适当的搜索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();
}
}
}
问题:使用.get()方法使应用程序等待AsyncTask的整个计算,但它也阻止了UI线程!因此,用户将保持黑屏5秒或更长时间,这不是一件好事!
如果我不使用.get()方法,我会收到一个IndexOutOfBounds异常,因为我开始播放音乐流但列表尚未填充。
你可以建议我为这种情况做一个工作吗?
谢谢!
答案 0 :(得分:3)
删除.get()
它会阻止用户界面,直到完成任务。
启动任务,例如(播放视频),这取决于
中的AsycTask
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pDialog.dismiss();
//You can start music stream here
}
答案 1 :(得分:0)
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()实现是你需要开始播放的地方。
答案 2 :(得分:0)
最后我解决了我的问题,一些建议很好并且帮助了我很多!
我只是将startActivity指令移动到JsonCanzoni AsyncTask的onPostExecute,并更改了一些代码以适应新版本,它没问题! ;)