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 внутри петли и, возможно, сон внутри de runOnUiThread звонок. Однако это не предпочтительный вид решения, так как вы используете слишком много процессора, чтобы просто искать изменение значения. Спящий подход к нему немного уродлив, но решает проблему процессора. Это будет что-то типа:

    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();
}