Android 不确定的ProgressBar使我的后台线程非常慢

Android 不确定的ProgressBar使我的后台线程非常慢,android,multithreading,performance,progress-bar,Android,Multithreading,Performance,Progress Bar,我有一个应用程序与沉重的背景工作。为了使我的UI保持活跃(并避免ANR),我有一个不确定的进度条,在后台工作之前显示,在完成后隐藏 我的进度条是如何在我的活动的xml中声明的: <ProgressBar style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:indeterminate="true" android:visibil

我有一个应用程序与沉重的背景工作。为了使我的UI保持活跃(并避免ANR),我有一个不确定的进度条,在后台工作之前显示,在完成后隐藏

我的进度条是如何在我的活动的xml中声明的:

<ProgressBar
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:indeterminate="true"
    android:visibility="gone" />
在我的活动的构造函数上:

this.progress = (ProgressBar) findViewById(R.my_activity.progress_id);
我的后台工作非常繁重(包括本地调用),但我创建了一个新的Runnable来完成这项工作

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

我尝试了两种方法:

  • 将后台线程的优先级设置为最大优先级
  • 创建刷新率为300ms(默认值为50ms)的自定义动画
  • 这两种方法结合在一起,我的一个操作的时间从5900毫秒到4700毫秒,但是刷新率较低,进度条不平滑,而且我担心将后台线程优先级设置为MAX是不安全的

    还有什么我能做的吗


    编辑:

    AsyncTask现在真的不可能重构

    我用Chuck Norris的解决方案更新的代码:

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

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

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

    我的基准:

    相同操作的平均时间:

  • 没有handler和android的默认进度条:5.1s
  • 使用handler和android的默认进度条:4.6s(线程优先级达到最大值的结果相同)
  • 处理器和自定义动画每300毫秒刷新一次:3.5秒
  • 处理程序和自定义动画每150ms刷新一次:3.8s

  • 有什么想法吗?

    试着在活动中打开中间进度条,就像在
    onClickListener中一样。关闭它也要这样做

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

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

    因此,运行您描述的作业类型时,可以接受一种机制

    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();
            }
    
        }
    }
    
    公共类MyActivity扩展活动{
    ProgressBar mProgressBar=(ProgressBar)findViewById(R.my\u activity.progress\u id);
    DoTheWorkClass MyInstanceOffClassthatDotheWork=新对象();
    类MyAsyncTask扩展了AsyncTask{
    @凌驾
    受保护的void onPreExecute(){
    mProgressBar.setVisibility(View.VISIBLE);
    }
    @凌驾
    受保护的void onPostExecute(整数结果){
    mProgressBar.setVisibility(View.GONE);
    }
    @凌驾
    受保护的整数doInBackground(Void…params){
    返回MyInstanceOffClassthatDotheWork.doTheWork();
    }
    }
    }
    
    你不使用AsyncTask来控制整个过程有什么原因吗?因为应用程序的大小和重构所需的工作量。已经安排好了,但是我现在没有时间。但是创建异步任务来控制整个事情这个问题会解决吗?今天我将尝试进行POC是的,我预计在onPreExecute中启动进度条并在PostExecute中停止它不会显示您描述的行为。。。当然值得测试我尝试过使用处理程序而不是一个新的Runnable,它确实运行得更快。不会太多,但平均快400毫秒。
    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;
            }
    
        };
    };
    
    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();
            }
    
        }
    }