Android: 进度条不显示中间状态

Android: Progress bar not showing intermediate states

还有其他类似的 SO 问题,但 none 真的很有帮助。

我只想实现一个进度条,点击按钮时,从 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.
    }
}
}

我知道是Threads的问题,但是我对线程不是太友好所以无法理解这个问题。

我假设您的 "click" 方法发生在 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();
}

注意:请记住,目前,多次单击该按钮会导致不稳定的行为,因为您基本上是在此序列中添加了额外的可运行对象,导致进度条增长得更快.你可以用一个简单的标志很容易地防御这种情况。