私のアクティビティにはProgressBarがあります。アクティビティを開始するときに、別の場所から取得した値を確認し、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を更新し、UIスレッドをブロックして、アクティビティレイアウトが表示されないようにするスレッドのようです。
私のコードの何が問題になっていますか?この状況でProgressBarを更新する正しい方法は何ですか?
UIスレッドでwhile (progressBar.getProgress() < 100)
を実行しているため(runOnUiThread
を使用)、このループが終了するまでUIスレッドはブロックされます(ペイントされません)。
あなたはできる:
runOnUiThread
をループ内に配置し、おそらくde runOnUiThread
呼び出し内でスリープ状態にします。ただし、値の変更を探すだけではCPUを使いすぎているため、これは推奨される種類のソリューションではありません。睡眠は少し醜いアプローチですが、CPUの問題を解決します。次のようになります::
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);
}
});
}
};
進行状況が変更されたときにのみ更新コードを呼び出すように、イベント方式で進行状況バーを更新します(UIスレッドで)。これが推奨される方法です。
試してみてください:
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();
}