Android Как обновить значение ProgressBar?
моя деятельность имеет ProgressBar. Когда начнется действие, я проверю значение get из другого места и обновлю его до ProgressBar. Вот мой код:
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar_detail);
final TextView progressText = (TextView) findViewById(R.id.progressText_detail);
final ImageView btnCancel = (ImageView) findViewById(R.id.imgCancel_detail);
progressBar.setVisibility(View.VISIBLE);
progressText.setVisibility(View.VISIBLE);
btnCancel.setVisibility(View.VISIBLE);
Thread t = new Thread() {
public void run() {
((Activity) ctx).runOnUiThread(new Runnable() {
public void run() {
int oldProgress = 0;
while (progressBar.getProgress() < 100) {
int value = Downloader.progress.get(gameId+ "");
if (value != oldProgress) {
oldProgress = value;
progressBar.setProgress(value);
progressText.setText(value + " %");
}
}
}
});
}
};
t.start();
значение ProgressBar я получаю от int value = Downloader.progress.get(gameId)
и это правильно. Но когда я запускаю этот код, действие не отвечает и ничего не показывает (но приложение не сбой). Похоже, что поток для обновления ProgressBar работает и блокирует поток пользовательского интерфейса, поэтому макет активности не отображается.
что не так с моим кодом? Каков правильный способ обновления ProgressBar в этой ситуации?
4 ответов
работает while (progressBar.getProgress() < 100)
в потоке пользовательского интерфейса (вы используете runOnUiThread
) поэтому поток пользовательского интерфейса будет заблокирован (и ничего не окрашен) до завершения этого цикла.
вы можете:
-
поставить
runOnUiThread
внутри петли и, возможно, сон внутри derunOnUiThread
звонок. Однако это не предпочтительный вид решения, так как вы используете слишком много процессора, чтобы просто искать изменение значения. Спящий подход к нему немного уродлив, но решает проблему процессора. Это будет что-то типа:Thread t = new Thread() { public void run() { int oldProgress = 0; while (progressBar.getProgress() < 100) { ((Activity) ctx).runOnUiThread(new Runnable() { public void run() { int value = Downloader.progress.get(gameId+ ""); if (value != oldProgress) { oldProgress = value; progressBar.setProgress(value); progressText.setText(value + " %"); } } } Thread.sleep(500); } }); }
};
обновите индикатор выполнения таким образом, чтобы вы только вызывали (в потоке пользовательского интерфейса) код обновления при изменении прогресса. Это предпочтительный способ.
попробовать с:
int currentPosition=0;
int total=mediaPlayer.getDuration();
while(mediaPlayer!=null && currentPosition<total){
try{
if(progressEnable){
Thread.sleep(1000);
currentPosition=mediaPlayer.getCurrentPosition();
long pos=1000L * currentPosition/total;
Log.d("thread pos", pos+"");
progressSeekBar.setProgress((int) pos);
}
}
catch (Exception e) {
}
}
объявить progressEnable глобально:
private boolean progressEnable=true;
обычно я использую этот код:
private int mProgressStatus;
private Handler mHandler = new Handler();
public void startProgress(View view) {
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.horizontal_progress);
mProgressStatus = 0;
progressBar.setProgress(mProgressStatus);
//progressBar.setVisibility(View.VISIBLE);
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... params) {
while (mProgressStatus < 100) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
mProgressStatus += 15;
mHandler.post(new Runnable() {
public void run() {
progressBar.setProgress(mProgressStatus);
}
});
}
return null;
}
}.execute();
}
надеюсь, что это помогает
вы можете автоматически продвигать индикатор выполнения с помощью RXJava.
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (autoProgress) {
autoProgressSubscriber = Observable.interval(0, 1000/60, TimeUnit.MILLISECONDS) //~60fps
.map(index -> calculateAutoProgress())
.subscribe(progress -> {
if (progressBar != null) {
progressBar.setProgress(progress);
}
});
}
}
@Override
protected void onDetachedFromWindow() {
if (autoProgress) {
autoProgressSubscriber.unsubscribe();
}
super.onDetachedFromWindow();
}