2

そのため、Android アプリケーションで基本的に OData が行われていることに対して、これらの長時間実行されるサーバー呼び出しがあります。呼び出しのコンシューマーは.execute().get()、ネットワーク スレッドからの応答を待機するために使用します (適切な方法は、すべてを非同期でコールバック ベースにすることですが、アプリはこのデータがなければ機能しません。そのように働くことは何の利益ももたらさないようです)。

そのため、以下のコード サンプルに示すようにとProgressDialogを組み合わせて使用​​すると、実行中に進行状況ダイアログを表示するために使用できる多くのスニペットをオンラインで見つけました。私は提供されたサンプルを正確に使用していますが、何が起こるかというと、呼び出しが開始され、ネットワーク トランザクションを待ってから、進行状況ダイアログがすぐに点滅して非表示になります。トランザクションを数秒間待機することができ、実際に で待機していることはわかっていますが、ダイアログは最後までポップアップしないため、効果的に役に立たなくなります。onPreExecute()onPostExecute()AsyncTaskdoInBackground()

以下のコードでは、DoEvents()ビットは基本的に非常に短いスリープです。私はそれの有無にかかわらず試してみましたが、違いはないようですが、試してみる価値があるようです.

class GetFromServerTask extends AsyncTask<String, Void, String>
    {
        private Context context;
        private ProgressDialog dialog;

        public GetFromServerTask(Context ctx) {
            context = ctx;
            dialog = new ProgressDialog(ctx);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog.setMessage("Loading...");
            dialog.show();
            DoEvents();
        }

        @Override
        protected String doInBackground(String... parms) {
            if(InOfflineMode)
                return "notdeserializable";

            String url = parms[0]; 
            HttpURLConnection urlConnection = null;
            try {
                URL typedUrl = new URL(url);
                urlConnection = (HttpURLConnection) typedUrl.openConnection();

                //Add Authorization token
                if(InDebugMode) {
                    urlConnection.addRequestProperty("AuthToken", AuthToken);
                } else {
                    urlConnection.addRequestProperty("Authorization", "Bearer " + AuthToken);
                }
                urlConnection.addRequestProperty("Accept", "application/json");

                DoEvents();
                InputStream in = new BufferedInputStream(urlConnection.getInputStream());
                byte[] contents = new byte[in.available()];

                int bytesRead = 0;
                String strContents = ""; 
                while((bytesRead = in.read(contents)) != -1){ 
                    strContents += new String(contents, 0, bytesRead);
                    DoEvents();
                }

                if(strContents.startsWith("<HTML>"))
                    return "Error: Received unexpected HTML when connecting to service.  Make sure you are not connected to a WIFI that requires authentication.";

                return strContents;
            } catch(UnknownHostException hex) {
                return "Error: Could not find server address.  Make sure you are connected to the internet.  If you just changed connections (ie: turning WIFI on or off) it make take a minute to refresh";
            }
            catch(Exception ex) {
                String msg = "Error: " + ex.getClass().getName() + ": " + ex.getMessage();
                Log.e("TE", msg);
                return msg;
            } finally {
                if(urlConnection != null)
                    urlConnection.disconnect();
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if(dialog != null && dialog.isShowing())
                dialog.dismiss();
            DoEvents();
        }
    }

SO の他の場所で提案されているわずかに異なるバージョン (以下に示す) も試してみましたが、まったく同じ結果が得られました。

protected void onPreExecute() {
    dialog=ProgressDialog.show(context, "", "Loading...", true, false);
    super.onPreExecute();
}

以下に示すようProgressDialogに、すべてをまとめてタスクの「外側」に表示することも試みました。AsyncTaskこの場合、それは表示されません。

ProgressDialog dialog = ProgressDialog.show(ServerAccessLayer.m_context, "", "Loading...", true, false);
String retVal = new GetFromServerTask(ServerAccessLayer.m_context).execute(url).get();
dialog.dismiss();

return retVal; 
4

2 に答える 2

3

わかりました、あなたの問題はあなた.get()です。 .getブロッキングコールです。これは、イベント ループ ( 、、、イベント ハンドラ、、、onCreateなどを呼び出す Android フレームワーク内のコード) が戻るまで戻らないことを意味します。イベント ループに戻らないと、描画コードに入ることができず、進行状況ダイアログも表示されません。ダイアログを表示したい場合は、タスクを実際に非同期で使用するようにアプリを再構築する必要があります。余談ですが、UI スレッドでそのように呼び出すと、アプリ全体がフリーズして壊れたように見えます。そのため、そもそも UI スレッドでネットワーク IO を実行しないように人々に強制しました。onPauseonPostExecuteonPreExecute.get()

于 2013-06-03T21:41:03.243 に答える
1

@Gabe-Sechan が言うように、これ.get()が UI がフリーズし、ProgressDialog が希望どおりに表示されない理由です。一方で、彼が次のように言うとき、私は彼に同意しません。

ダイアログを表示したい場合は、タスクを実際に非同期で使用するようにアプリを再構築する必要があります。

単純に削除して.get()ダイアログを に表示し、onPreExecute()で閉じると、onPostExecute(String result)探しているものが得られます: タスクの実行中に表示される ProgressDialog です。

アップデート:

Android の AsyncTask クラスのメソッドを使用する感覚/有用性に基づいて質問を開始しました。get()

于 2013-06-03T22:31:43.360 に答える