0

プロジェクトはほぼ終了しましたが、改善すべき点が 1 つだけ残っています。

私のアプリは、作者、曲のタイトル、previewUrl ecc に関するすべての情報を取得する音楽クイズです。Apposite Search 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 Exception が発生します。これは、音楽ストリームの再生を開始しましたが、リストがまだいっぱいになっていないためです。

この状況の回避策を教えてもらえますか?

ありがとうございました!

4

3 に答える 3

3

削除.get()すると、タスクが完了するまで UI がブロックされます。

に依存する(ビデオの再生)などのタスクを開始しAsycTaskます

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

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

最後に私は問題を解決しました。いくつかのアドバイスは素晴らしく、私を大いに助けてくれました!

startActivity 命令を JsonCanzoni AsyncTask の onPostExecute に移動し、一部のコードを新しいバージョンに合わせて変更しただけで問題ありません。;)

于 2012-12-04T16:18:55.570 に答える
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() 実装は、プレイを開始する必要がある場所です。

于 2012-12-03T19:08:05.463 に答える