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);
    }
});

在我的 Activity 的构造函数上:

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

我的后台工作非常繁重(包括本地调用),但我创建了一个新的 Runnable 来完成这项工作。

问题是:使用progressBar,后台线程完成工作的时间增加了大约每秒300ms。当我运行 traceview 时,我可以看到每次我的 ProgressBar 刷新时,它都会停止后台线程来更新视图。

我尝试了两种方法:

  1. 将后台线程的优先级设置为 MAX_PRIORITY。
  2. 创建刷新率为 300 毫秒(默认为 50 毫秒)的自定义动画。

将这两者结合起来,我的一项操作的时间从 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;
        }

    };
};

这确实改进了我的应用程序,我不再需要将线程优先级设置为 Max,这是我的目标之一。

但我仍然想将我的动画恢复为 Android 的默认设置(每 50 毫秒刷新一次 ProgressBar)。当我这样做时,我在基准操作中损失了 1 秒。

我的基准:

同一操作的平均时间:

  1. 没有处理程序和android的默认进度条:5.1s
  2. 带handler和android的默认进度条:4.6s(线程优先到MAX的结果相同)
  3. 处理程序和自定义动画每 300 毫秒刷新一次: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 回答