0

我几乎完成了我的项目,只有一件事需要改进。

我的应用程序是一个音乐测验,它检索有关作者、歌曲标题、previewUrl ecc 的所有信息。使用适当的搜索 API 从 iTunes Store 下载。

当用户选择要玩的类型时,我必须告诉用户等待 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 异常,因为我开始播放音乐流但列表尚未填充。

你能建议我解决这种情况吗?

谢谢!

4

3 回答 3

3

删除.get()它会阻塞 UI 直到任务完成。

启动任何依赖于AsycTaskin 的任务,例如(播放视频)

@Override
protected void onPostExecute(Void result)
{
    super.onPostExecute(result);

    pDialog.dismiss();
      //You can start music stream here
}
于 2012-12-03T19:07:14.530 回答
0

Finally I solved my problem, some advices were good and helped me a lot!

I simply moved the startActivity instruction to onPostExecute of JsonCanzoni AsyncTask, and changed some code to adapt to the new version and it's all right! ;)

于 2012-12-04T16:18:55.570 回答
0

get() 调用被阻塞。从文档:

如有必要,等待计算完成,然后检索其结果。

您应该做的是在开始播放音乐之前异步等待计算完成。

如果您不想在您的类之外公开异步任务,您可以在您的 JSonCanzoni 类中设置一个回调,以便在异步任务的 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() 实现是您需要开始播放的地方。

于 2012-12-03T19:08:05.463 回答