我有一个背景繁重的应用程序。为了保持我的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刷新时,它都会停止后台线程来更新视图。
我尝试了两种方法:
有了这两个组合,我的一个操作的时间从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秒。
我的基准:
同一操作的平均时间:
有什么想法吗?
答案 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();
}
}
}