Indeterminate ProgressBar使我的后台线程变得非常慢

时间:2013-03-20 14:42:01

标签: android multithreading performance progress-bar

我有一个背景繁重的应用程序。为了保持我的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,后台线程完成工作的时间增长大约每秒300毫秒。当我运行traceview时,我可以看到每次我的ProgressBar刷新时,它都会停止后台线程来更新视图。

我尝试了两种方法:

  1. 将后台线程的优先级设置为MAX_PRIORITY。
  2. 创建刷新率为300毫秒的自定义动画(默认值为50毫秒)。
  3. 有了这两个组合,我的一个操作的时间从5900ms到4700ms但是,刷新率较低,进度条不顺畅,我担心将后台线程优先级设置为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;
            }
    
        };
    };
    

    这确实改善了我的应用程序,我不再需要将Thread Priority设置为Max,这是我的目标之一。

    但是我仍然希望将我的动画恢复到Android的默认值(每50ms刷新一次ProgressBar)。当我这样做时,我的基准操作中会丢失1秒。

    我的基准:

    同一操作的平均时间:

    1. 没有处理程序和android的默认进度条:5.1s
    2. 使用handler和android的默认进度条:4.6s(与线程优先级相同的结果)
    3. 每300毫秒刷新处理程序和自定义动画:3.5秒
    4. 使用处理程序和自定义动画每150ms刷新一次:3.8s
    5. 有什么想法吗?

2 个答案:

答案 0 :(得分:1)

尝试在活动中启用中间进度条,例如onClickListener。将其关闭也是如此。

所需的额外时间可能是分配和启动新线程的时间。这就是您使用控制进度条的新Runnable()所做的事情。

不要从它自己的线程控制进度条。

答案 1 :(得分: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();
        }

    }
}