1

バックグラウンドでの作業が多いアプリがあります。UIを存続させる(そしてANRを回避する)ために、バックグラウンドが機能する前に表示し、終了すると非表示にする不確定なProgressBarがあります。

これは、私のアクティビティのxmlでプログレスバーが宣言される方法です。

<ProgressBar
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:indeterminate="true"
    android:visibility="gone" />

バックグラウンド操作の前後で可視性を切り替えます。

this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Activity.this.progress.setVisibility(View.VISIBLE);
    }
});

this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Activity.this.progress.setVisibility(View.GONE);
    }
});

私のアクティビティのコンストラクターについて:

this.progress = (ProgressBar) findViewById(R.my_activity.progress_id);

私のバックグラウンド作業は非常に重いです(ネイティブコールを含む)が、その仕事をするために新しいRunnableを作成します。

問題は次のとおりです。progressBarを使用すると、作業をバックグラウンドで終了するまでの時間が1秒あたり約300ミリ秒長くなります。traceviewを実行すると、ProgressBarが更新されるたびに、バックグラウンドスレッドが停止してビューが更新されることがわかります。

私は2つのアプローチを試しました:

  1. バックグラウンドスレッドの優先度をMAX_PRIORITYに設定します。
  2. リフレッシュレートが300ms(デフォルトは50ms)のカスタムアニメーションを作成します。

これら2つを組み合わせると、1つの操作の時間は5900ミリ秒から4700ミリ秒になりますが、リフレッシュレートが低いと、プログレスバーがスムーズにならず、バックグラウンドスレッドの優先度をMAXに設定するのは安全ではありません。

他にできることはありますか?


編集:

AsyncTaskは、現在リファクタリングすることは本当に不可能です。

Chuck Norrisのソリューションで更新されたコード:

Activity.this.getHandler().sendEmptyMessage(
            MyMessages.SHOW_PROGRESS_BAR);


Activity.this.getHandler().sendEmptyMessage(
            MyMessages.HIDE_PROGRESS_BAR);

private Handler handler = new Handler() {
    @Override
    public void handleMessage(android.os.Message msg) {

        switch (msg.what) {
        case MyMessages.SHOW_PROGRESS_BAR:
            Activity.this.progress.setVisibility(View.VISIBLE);
            break;
        case MyMessages.HIDE_PROGRESS_BAR:
            Activity.this.progress.setVisibility(View.GONE);
            break;
        default:
            break;
        }

    };
};

これによりアプリケーションが本当に改善され、スレッドの優先度を最大に設定する必要がなくなりました。これが私の目標の1つでした。

ただし、アニメーションをAndroidのデフォルトに戻したい(50ミリ秒ごとにProgressBarを更新する)。そうすると、ベンチマーク操作で1を失います。

私のベンチマーク:

同じ操作の平均時間:

  1. ハンドラーとAndroidのデフォルトのプログレスバーなし:5.1秒
  2. ハンドラーとAndroidのデフォルトのプログレスバーを使用した場合:4.6秒(MAXに対するスレッドの優先度と同じ結果)
  3. 300msごとに更新されるハンドラーとカスタムアニメーション:3.5秒
  4. 150ミリ秒ごとに更新されるハンドラーとカスタムアニメーション:3.8秒

何か案が?

4

2 に答える 2

1

のように、アクティビティで中間プログレスバーをオンにしてみてくださいonClickListener。オフにする場合も同じようにします。

余分な時間がかかるのは、新しいスレッドを割り当てて開始するための時間である可能性があります。これが、プログレスバーを制御する新しいRunnable()で行っていることです。

独自のスレッドからプログレスバーを制御しないでください。

于 2013-03-20T14:53:56.953 に答える
1

したがって、AsyncTaskは、説明した種類のジョブを実行するための受け入れられたメカニズムです

public class MyActivity extends Activity {
    ProgressBar mProgressBar = (ProgressBar) findViewById(R.my_activity.progress_id);
    DoTheWorkClass myInstanceOfClassThatDoesTheWork = new Object();

    class MyAsyncTask extends AsyncTask<Void, Void, Integer> {


        @Override
        protected void onPreExecute() {
            mProgressBar.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onPostExecute(Integer result) {
            mProgressBar.setVisibility(View.GONE);
        }

        @Override
        protected Integer doInBackground(Void... params) {
            return myInstanceOfClassThatDoesTheWork.doTheWork();
        }

    }
}
于 2013-03-20T15:05:22.927 に答える