还有其他类似的SO问题,但没有一个真正有用。
我只想实现一个进度条,按钮点击,从0开始,逐渐移动并停在一个点(从sharedPreferences读取)。
然而事情正在发挥作用,但进度条没有逐步更新,而是直接显示在终点。
我在这里粘贴的简化代码:
public class MainActivity extends ActionBarActivity {
int primaryProgress = 0;
int finalPrimaryProgress = 60;
ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
progressBar.setMax(100);
progressBar.setProgress(0);
}
public void click(View view) {
while (primaryProgress < finalPrimaryProgress)
{
progressBar.setProgress(primaryProgress+=1);
Thread.sleep(100); //This is inside Try-catch in actual code.
}
}
}
我知道问题出在线程上,但我对线程不太友好,所以无法理解这个问题。
答案 0 :(得分:1)
我假设你的&#34;点击&#34;方法正在UI线程上发生(否则,当您尝试在后台线程上更改视图时,您可能会遇到异常)。
想想你在这里做了什么 - 当你点击一个按钮时,你开始循环。在循环的每次迭代中,您更改进度条的值,然后使(主)线程休眠100毫秒,然后重复。
问题是,您永远不会让运行时对您所做的更改做出反应。一旦更改了视图的值(例如,更改TextView的文本),Android运行时需要有时间对您的更改做出反应,调整视图的大小,位置然后重绘。在您再次更改值之前,您的代码基本上阻止了任何事情发生,因为您告诉主线程要休眠,然后您立即再次更改该值。
这里的预期结果是,一旦你停止更改其值而不让运行时实际上对它做任何事情,就会看到在最终状态下绘制的进度条。
作为当前点击方法的替代方法,请尝试使用postDelayed执行某些操作。这将允许运行时在每次迭代之间执行完整的度量 - 布局 - 绘制循环:
private void increaseProgressBar()
{
if (progressBar.getProgress() < progressBar.getMax())
progressBar.postDelayed(new Runnable() {
@Override
public void run() {
progressBar.setProgress(progressBar.getProgress() + 1); // increase the value of the progress bar.
increaseProgressBar(); // call the function again, but after a delay.
}
}, 100);
}
public void click(View v)
{
increaseProgressBar();
}
注意:请记住,目前,多次单击该按钮会导致行为不稳定,因为您基本上会向此序列添加额外的可运行,从而导致进度条增长得更快。你可以用一个简单的旗帜轻松地防范这种情况。