2

アプリ フローが Android 標準とは異なるアプリがあります。

  • 標準: アクティビティ A のボタンを押して、データをロードし、アクティビティ B のビューを構築している間に、このアクティビティのロードを表示してから、次のアクティビティを表示します。 (アクティビティ A で AsyncTask を呼び出し、データの送信が完了したらアクティビティ B を呼び出します)

  • 必要なもの: アクティビティ A のボタンを押し、アクティビティ B に移動し、読み込みを表示しながら、読み込みの背後にあるアクティビティ B のビューを更新します。 (アクティビティ A から B に移動し、読み込み中に AsyncTask を呼び出します。AsyncTask が終了すると、読み込みが前面にある間にビューが更新され、ビューの更新プロセスが表示されます)

問題: これにより、読み込み中のアイコンが停止し、(操作に時間がかかるため) 応答しないダイアログが表示され、UI スレッドを使用して構築中のビューを変更することがあります。

同じ問題に関するいくつかの質問を読みました: Android: UI を動的に更新する方法は?

しかし、誰も一般的な答えを提供していません。

「それは推奨される動作ではありません」と答えた場合、同意します...ただし、これらは要件であるため、助けていただければ幸いです:-D

4

4 に答える 4

4

私は最初にプロジェクトで1年前にこれを行いました。アイコンを使用しようとしたため、これとまったく同じ問題が発生しました。更新するものが多すぎてアイコンが時々フリーズしたためHandlerAsyncTask. これは実際には、セットアップ前のアクティビティで非常に一般的なパターンです。

手順は次のとおりです。

  1. ローディング ダイアログを作成し、Handlerオブジェクトにポストします。このようなものを使用できます(Toast明らかに、の代わりに読み込みダイアログ)。
  2. AsyncTask計算を開始します。
  3. 計算の各部分の準備が整ったら、publishProgress. UI のどの部分を構築する必要があるかを正確に伝えるために、コードにフラグを付けます。ローディングダイアログが表示されて回転している間、UI がビルドされていることがわかります。
  4. すべてが完了したら、 でダイアログを閉じますonPostExecute

以下は、あなたが説明したことを正確に行うサンプルコードです。

private void settingsAndPlaceTaskStart() {

    // loading dialog
    startLoading();

    new AsyncTask<Context, Integer, Void>() {
        @Override
        protected Void doInBackground(Context... context) {

            // check and prepare settings integrity
            Settings st = new Settings(context[0], false);
            st.checkPreferencesIntegrity();

            // set text for each view / paired object
            // this will take a long time
            do {
                // ... removed for clarity
                int code = ...;
                publishProgress(mObjects.getViewByCode(code));    
                while (mObjects.getNext());
            return null;
        }

        @Override
        protected void onPostExecute(Void void) {
            // finish stuff
        }

        @Override
        protected void onProgressUpdate(Integer... message) {
            prepareView(message[0]);
        }

    }.execute(getActivity());
}

ここでは、進行状況がダイアログで回転している間、ローディングがスタッターに悩まされることはありません。ダイアログは、onPostExecute. タスクの終了後、ダイアログを閉じる必要があります。

于 2012-03-04T14:30:39.153 に答える
2

A. Androidマーケットアプリを見てください(「プレイ」でどのように機能するかわかりません)-アプリをクリックすると、サイクルバーのみの空のアクティビティが表示され、完全なダウンロード後に他のデータが表示されます. 同じ動作をしたいですか?はいの場合 - 以下が機能します。

B アクティビティのレイアウト:

<RelativeLayout>
    <common_layout_of_your_view_that_covers_all_space />
    <layout_for_progress />
</RelativeLayout>

layout_for_progress は任意のレイアウトにすることができ、透明にしたい場合は、特別な背景を配置します。

バックグラウンド データの読み込みのためにスレッドを開始するだけでなく、B をアクティビティします。

onCreate(...) {
    //call super
    //set content view

    new Thread(new Runnable() {
        public void run() {
            while(!downloadComplete) {
                //ask some portion of data
                ActivityB.this.runOnUIThread(new Runnable(){
                    public void run() {
                        //update your main view
                    }
                });
            }
            findViewById(R.id.layout_for_progress).setVisibility(View.GONE);
        }
    }).start();
}
于 2012-03-07T13:42:34.063 に答える
2

この権利があることを確認させてください。アクティビティ A が最初で、B が 2 番目です。2 つのことをトリガーする A のボタンが必要です: 非同期データの読み込みと、アクティビティ スタックでの B のプッシュです。これで問題ありません。

What I Need」では、「バックグラウンドでビューを更新する」という動詞句を使用しています。これは不可能です。メイン UI スレッドでのみビューを更新できます。また、onPause()(B のプッシュによってトリガーされて) A が呼び出されると、A は処理できないと考える必要があります。あなたができることは、バックグラウンドでデータをロードすることです.Bはそのことを行い、次にAはonResume()そのUIを適切に更新できます.

私が間違っていて、B が表示されている間に A にいくつかの UI 作業を行わせた場合は問題ありませんが、チャンクとしての処理に時間がかかりすぎる場合は、それをより小さなものに分割する必要があると思いますB のユーザー エクスペリエンスを中断しないように、チャンクを分割して少しずつスケジュールを設定します。

アップデート

特にYがまだonCreate()d. アクティビティ間でレイアウト リソースを共有できるかどうかはわかりませんが、可能かもしれません。

あなたが上に投稿したリンクはそれに到達します - Handlerクラスの使用に関する答えはあなたのソリューションの一部だと思います。また、 LooperDesigning for Responsivenessについてもお読みください。つまり、メイン スレッドに Handler を実装して、100 ~ 200 ミリ秒の小さなチャンクで UI を更新できるようにし ( Responsivenessで提案されているように)、高い粒度でその Handler にメッセージを送信する必要があると思います。バックグラウンド スレッドで少量のデータを処理します。たとえば、 を更新している場合ListView、一度に 1 行ずつインフレートできる必要があります。に画像を追加する場合も同様ですGridView。また、事前に検討してください-リソースをロードしますが、表示はしません。これにより、時間が短いときに膨張に費やす時間を減らすことができます。

現時点での私の考えではこれだけですが、数週間以内に似たようなことをしなければならなくなると思うので、これをお気に入りとしてマークしています。あなたに合ったものを投稿してください。幸運を!

于 2012-03-04T13:11:40.297 に答える
1

onCreate で asyncTask を開始し、すべての計算を実行させることができます。同時に、読み込みバーを表示できます。次に、 onPostExecute で、収集した情報でビューを更新し、進行状況バーを閉じることができます

于 2012-02-29T19:21:26.700 に答える