我正在尝试在按下按钮后立即显示的活动中显示进度条。按下按钮时,将调用以下方法:
private void onStartClick() {
start.setTextColor(getResources().getColor(R.color.button_std_text_on_click));
// Progress bar
progressBar.setVisibility(View.VISIBLE);
progressBar.setMax(100);
// Defines target language
Param.TARGET_LANGUAGE = spinner.getSelectedItem().toString();
// Save language selected to select it directly next time
Pref.savePreference(this, Param.LAST_LANG_KEY, spinner.getSelectedItemPosition());
initAppData(MainActivity.this);
}
但是,下面的代码行似乎是在'progressBar.setVisibility(View.VISIBLE);'行之前执行的完成执行。当 initAppData 快要执行完时,进度条终于显示出来(initAppData 是一个执行时间很长的方法)。
我们如何解释,因为我使用同一个线程来执行这个方法?
我还可以补充一点,当我删除 initAppData 行时,进度条会立即显示。
我试图在另一个线程中执行 initAppData() 以查看 initAppData 是否避免显示进度条,但它没有改变任何东西。
您遇到的问题可能是由于 initAppData() 方法执行时间过长并阻塞了 UI 线程。当 UI 线程被阻塞时,在阻塞操作完成之前无法呈现 UI 更新。这就是为什么直到 initAppData() 几乎完成执行时才显示进度条的原因。
要解决此问题,您应该将长时间运行的操作(在本例中为 initAppData())移至后台线程。这可以使用 Thread 或 AsyncTask 来完成。
这是一个示例,说明如何使用 AsyncTask 在后台运行 initAppData() 并使用进度更新 UI: 1.定义你的异步任务:
private class InitAppDataTask extends AsyncTask<Void, Integer, Void> {
@Override
protected void onPreExecute() {
// This method is called on the UI thread before the background task starts
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(0);
}
@Override
protected Void doInBackground(Void... voids) {
// This method is called on a background thread, so it won't block the UI thread
initAppData(MainActivity.this);
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
// This method is called on the UI thread when you call publishProgress()
progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(Void aVoid) {
// This method is called on the UI thread after the background task completes
progressBar.setVisibility(View.GONE);
}
}
更新你的 onStartClick() 方法来创建一个实例
InitAppDataTask 并执行它:
private void onStartClick() { start.setTextColor(getResources().getColor(R.color.button_std_text_on_click));
// Defines target language
Param.TARGET_LANGUAGE = spinner.getSelectedItem().toString();
// Save language selected to select it directly next time
Pref.savePreference(this, Param.LAST_LANG_KEY, spinner.getSelectedItemPosition());
// Start the InitAppDataTask to run initAppData() in the background
new InitAppDataTask().execute();
}
通过使用 AsyncTask 在后台运行 initAppData(),UI 线程能够立即更新进度条,即使 initAppData() 方法需要很长时间才能执行。每当您从后台线程调用 publishProgress() 时,都会在 UI 线程上调用 onProgressUpdate() 方法,使您可以随着任务的进行更新进度条。 onPostExecute() 方法在后台任务完成后在 UI 线程上调用,允许您隐藏进度条并执行任何必要的 UI 更新。