使用 CountDownTimer 更新 ProgressBar
Posted
技术标签:
【中文标题】使用 CountDownTimer 更新 ProgressBar【英文标题】:Update ProgressBar with a CountDownTimer 【发布时间】:2018-12-24 04:33:35 【问题描述】:我正在尝试用AsyncTask
和CountDownTimer
更新ProgressBar
。我没有错误,但ProgressBar
没有更新。
由于MyDownloadTask
扩展AsyncTask
我不需要发布方法或onProgressUpdate()
。我的 ProgressBar 在 doInBackground() 中自动更新。
我认为CountDownTimer
中的代码没有执行,但我调用的是monCountTimer.start();
这是我的 Java 代码:
public class myDownloadTask extends AsyncTask<Integer, Integer, String>
public void setMonCountTimer(CountDownTimer monCountTimer)
this.monCountTimer = monCountTimer;
public void setInc(int inc)
this.inc = inc;
public void setMaProgressBar(ProgressBar maProgressBar)
this.maProgressBar = maProgressBar;
public CountDownTimer getMonCountTimer()
return monCountTimer;
public int getInc()
return inc;
public ProgressBar getMaProgressBar()
return maProgressBar;
protected CountDownTimer monCountTimer;
private int inc = 0;
protected ProgressBar maProgressBar;
public void setMonAct(MainActivity monAct)
this.monAct = monAct;
public MainActivity getMonAct()
return monAct;
private MainActivity monAct;
public myDownloadTask(ProgressBar maBarre, MainActivity monActi)
this.maProgressBar = maBarre;
this.monAct = monActi;
@Override
protected void onPreExecute()
super.onPreExecute();
this.maProgressBar.setProgress(0);
@Override
protected void onProgressUpdate(Integer... integers)
super.onProgressUpdate(integers);
@Override
protected String doInBackground(Integer... integers)
Thread monThread = new Thread(new Runnable()
@Override
public void run()
monCountTimer = new CountDownTimer(6000, 1000)
@Override
public void onTick(long millisUntilFinished)
myDownloadTask.this.inc++;
myDownloadTask.this.getMaProgressBar().setProgress((int) myDownloadTask.this.inc* 100 / (6000 / 1000));
@Override
public void onFinish()
;
monCountTimer.start();
);
return "coucou";
主类:
public class MainActivity extends AppCompatActivity
private ProgressBar maBarre ;
public void setMaBarre(ProgressBar maBarre)
this.maBarre = maBarre;
public void setLaunchAsync(Button launchAsync)
this.launchAsync = launchAsync;
public void setMonHandler(Handler monHandler)
this.monHandler = monHandler;
public void setMonCountTimer(CountDownTimer monCountTimer)
this.monCountTimer = monCountTimer;
public void setMonTask(myDownloadTask monTask)
this.monTask = monTask;
public void setProgressThread(Thread progressThread)
ProgressThread = progressThread;
public void setI(int i)
this.i = i;
public ProgressBar getMaBarre()
return maBarre;
public Button getLaunchAsync()
return launchAsync;
public Handler getMonHandler()
return monHandler;
public CountDownTimer getMonCountTimer()
return monCountTimer;
public String getPROGRESS_BAR_INCREMENT()
return PROGRESS_BAR_INCREMENT;
public static int getMessagePreExecute()
return MESSAGE_PRE_EXECUTE;
public static int getMessageProgressUpdate()
return MESSAGE_PROGRESS_UPDATE;
public static int getMessagePostExecute()
return MESSAGE_POST_EXECUTE;
public myDownloadTask getMonTask()
return monTask;
public Thread getProgressThread()
return ProgressThread;
public int getI()
return i;
private Button launchAsync;
private Handler monHandler ;
private CountDownTimer monCountTimer ;
private final String PROGRESS_BAR_INCREMENT="ProgreesBarIncrementId";
private static final int MESSAGE_PRE_EXECUTE = 1;
private static final int MESSAGE_PROGRESS_UPDATE = 2;
private static final int MESSAGE_POST_EXECUTE = 3;
myDownloadTask monTask;
Thread ProgressThread ;
private int i = 0 ;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
maBarre = (ProgressBar) findViewById(R.id.progressBar);
launchAsync = (Button) findViewById(R.id.button);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
);
this.launchAsync.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
monTask = new myDownloadTask(MainActivity.this.maBarre , MainActivity.this);
monTask.execute();
);
@Override
public boolean onCreateOptionsMenu(Menu menu)
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in androidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings)
return true;
return super.onOptionsItemSelected(item);
@Override
public void onPointerCaptureChanged(boolean hasCapture)
你能帮帮我吗?
【问题讨论】:
嗨。我会尽力提供帮助。最好对可能出现的问题提供更多分析。此外,最好发布 xml 布局。但首先要做的是将问题分成两半。是演示文稿问题吗?还是更新进度条的逻辑有问题?例如,如果将“maBarre.setProgress(50)”添加到 onCreate,进度条会出现在屏幕上吗? 好的。最好使用任何附加信息编辑原始问题。在找到解决方案之前,请勿将其发布在答案中。如果您在答案中发布代码,那么您将被否决,这将降低获得有用响应的可能性,因为较少人看到被否决的问题。你按照我的建议做了吗?尝试在 onCreate 中调用 setProgress(50) 以验证进度是否出现在屏幕上?如果没有出现,则很可能是布局问题。 【参考方案1】:为您的 XML 文件试试这个。我不知道您要实现什么布局,但是当我执行“setProgress(50);”时在 onCreate 中,使用发布的 XML 文件没有出现任何内容。
我创建了这个 XML 布局,现在进度条看起来很好:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_>
<Button
android:id="@+id/button"
android:layout_
android:layout_
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressBar" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_
android:layout_
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="140dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_
android:layout_
android:layout_gravity="bottom|end"
android:layout_margin="10dip"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button"
app:srcCompat="@android:drawable/ic_dialog_email" />
</android.support.constraint.ConstraintLayout>
在onCreate中,添加:
ProgressBar bar = findViewById(R.id.progressBar);
bar.setProgress(50);
测试布局...
还有几个问题:线程已经创建,但是之后必须调用 start()。
monCountTimer.start();
在public void run()中,代码在做:
myDownloadTask.this.getMaProgressBar().setProgress((int)
myDownloadTask.this.inc* 100 / (6000 / 1000));
永远不要从 Android 中的工作线程更新视图。所有视图都必须在“主线程”(也称为“UI 线程”)上更新
解决此问题的快速方法是:
runOnUiThread(new Runnable()
@Override
public void run()
// ...
);
我已经进行了上面的更改,现在它运行良好:
public class MainActivity extends AppCompatActivity
private ProgressBar maBarre ;
public void setMaBarre(ProgressBar maBarre)
this.maBarre = maBarre;
public void setLaunchAsync(Button launchAsync)
this.launchAsync = launchAsync;
public void setMonHandler(Handler monHandler)
this.monHandler = monHandler;
public void setMonCountTimer(CountDownTimer monCountTimer)
this.monCountTimer = monCountTimer;
public void setMonTask(myDownloadTask monTask)
this.monTask = monTask;
public void setProgressThread(Thread progressThread)
ProgressThread = progressThread;
public void setI(int i)
this.i = i;
public ProgressBar getMaBarre()
return maBarre;
public Button getLaunchAsync()
return launchAsync;
public Handler getMonHandler()
return monHandler;
public CountDownTimer getMonCountTimer()
return monCountTimer;
public String getPROGRESS_BAR_INCREMENT()
return PROGRESS_BAR_INCREMENT;
public static int getMessagePreExecute()
return MESSAGE_PRE_EXECUTE;
public static int getMessageProgressUpdate()
return MESSAGE_PROGRESS_UPDATE;
public static int getMessagePostExecute()
return MESSAGE_POST_EXECUTE;
public myDownloadTask getMonTask()
return monTask;
public Thread getProgressThread()
return ProgressThread;
public int getI()
return i;
private Button launchAsync;
private Handler monHandler ;
private CountDownTimer monCountTimer ;
private final String PROGRESS_BAR_INCREMENT="ProgreesBarIncrementId";
private static final int MESSAGE_PRE_EXECUTE = 1;
private static final int MESSAGE_PROGRESS_UPDATE = 2;
private static final int MESSAGE_POST_EXECUTE = 3;
myDownloadTask monTask;
Thread ProgressThread ;
private int i = 0 ;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
maBarre = (ProgressBar) findViewById(R.id.progressBar);
launchAsync = (Button) findViewById(R.id.button);
//etSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
);
this.launchAsync.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
monTask = new myDownloadTask(MainActivity.this.maBarre , MainActivity.this);
monTask.execute();
);
@Override
public boolean onCreateOptionsMenu(Menu menu)
// getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
@Override
public boolean onOptionsItemSelected(MenuItem item)
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
return super.onOptionsItemSelected(item);
@Override
public void onPointerCaptureChanged(boolean hasCapture)
public class myDownloadTask extends AsyncTask<Integer, Integer, String>
public void setMonCountTimer(CountDownTimer monCountTimer)
this.monCountTimer = monCountTimer;
public void setInc(int inc)
this.inc = inc;
public void setMaProgressBar(ProgressBar maProgressBar)
this.maProgressBar = maProgressBar;
public CountDownTimer getMonCountTimer()
return monCountTimer;
public int getInc()
return inc;
public ProgressBar getMaProgressBar()
return maProgressBar;
protected CountDownTimer monCountTimer;
private int inc = 0;
protected ProgressBar maProgressBar;
public void setMonAct(MainActivity monAct)
this.monAct = monAct;
public MainActivity getMonAct()
return monAct;
private MainActivity monAct;
public myDownloadTask(ProgressBar maBarre, MainActivity monActi)
this.maProgressBar = maBarre;
this.monAct = monActi;
@Override
protected void onPreExecute()
super.onPreExecute();
this.maProgressBar.setProgress(0);
@Override
protected void onProgressUpdate(Integer... integers)
super.onProgressUpdate(integers);
@Override
protected String doInBackground(Integer... integers)
Thread monThread = new Thread(new Runnable()
@Override
public void run()
runOnUiThread(new Runnable()
@Override
public void run()
monCountTimer = new CountDownTimer(6000, 1000)
@Override
public void onTick(long millisUntilFinished)
myDownloadTask.this.inc++;
myDownloadTask.this.getMaProgressBar().setProgress((int) myDownloadTask.this.inc * 100 / (6000 / 1000));
@Override
public void onFinish()
;
monCountTimer.start();
);
);
monThread.start();
return "coucou";
需要考虑的几个问题:
这里创建的线程比需要的多,代码可以写得更简单。 doInBackground 已经在一个单独的线程上,因此无需在那里创建另一个线程。另外,我相信 CountDownTimer 已经在它自己的线程中运行,所以这里的很多代码可能是不必要的。 完成开发后,请消除所有这些警告。软件开发真的是关于纪律和良好的习惯,只有糟糕的开发人员会忽略警告!完成后执行“分析 -> 检查代码”。但是你的进度条更新器现在对我来说很好用。
【讨论】:
好的,非常感谢。我认为我在一年前开发了相同的程序,但奇怪的是我不需要 runOnUi runOnUiThread()。这是我的主要困难【参考方案2】:<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_
android:layout_
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_
android:layout_
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_
android:layout_
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
【讨论】:
请提供一个解释性的解决方案。或者确保您的每个解决方案都与其他解决方案根本不同,并且以哪种方式显而易见。我的印象是您应该在问题中添加信息,而不是这些无法解释的代码转储......【参考方案3】:<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:layout_editor_absoluteY="81dp"
tools:showIn="@layout/activity_main">
<Button
android:id="@+id/button"
android:layout_
android:layout_
android:layout_marginTop="236dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="@+id/progressBar"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="@+id/progressBar"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_
android:layout_
android:layout_marginBottom="336dp"
android:layout_marginEnd="104dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<android.support.constraint.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_
android:layout_
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
【讨论】:
我认为问题与线程有关,没有 AsyncTask,它可以工作,但不合适。我想是的,我忘记了指令 monThread.start()。但是有了这个指令,当我触摸按钮时,我的应用程序不起作用 查看我刚刚发布的答案。 XML 布局没有在模拟器中显示进度条。 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的回答添加解释并说明适用的限制和假设。【参考方案4】:好的,非常感谢!!!!!!:))
我试过了:
@Override
protected String doInBackground(Integer... integers)
Thread monThread = new Thread(new Runnable()
@Override
public void run()
monCountTimer = new CountDownTimer(6000, 1000)
@Override
public void onTick(long millisUntilFinished)
myDownloadTask.this.inc++;
myDownloadTask.this.getMaProgressBar().setProgress((int) myDownloadTask.this.inc* 100 / (6000 / 1000));
@Override
public void onFinish()
;
monCountTimer.start();
monThread.start();
);
return "coucou";
使用此代码,我的应用程序刚刚崩溃。
但是runOnUiThread(new Runnable() ....
可以工作
我们使用 2 个线程 ...;( 它没有优化,3 个带有 monCountTimer ,也许,我们可以删除 monThread
“我相信 CountDownTimer 已经在它自己的线程中运行,所以这里的很多代码可能是不必要的。”
我试过了:
@Override
protected String doInBackground(Integer... integers)
monCountTimer = new CountDownTimer(6000, 1000)
@Override
public void onTick(long millisUntilFinished)
myDownloadTask.this.inc++;
myDownloadTask.this.getMaProgressBar().setProgress((int) myDownloadTask.this.inc * 100 / (6000 / 1000));
@Override
public void onFinish()
;
monCountTimer.start();
它不起作用
【讨论】:
好的,但是请停止发布更多的解决方案...只需对我已经发布的解决方案发表评论就可以了。它在我的环境中运行良好,所以我不知道该告诉你什么。你必须给我更多的东西,而不仅仅是它不起作用。日志中有错误吗?尝试将我的文件剪切并粘贴到您的项目中。我刚刚将您的所有代码合并到 1 个类中以使其更快地工作,但它应该按原样运行...也可以使用我的 XML 文件...G'Luck。 是的,我做到了,我昨天测试了你的代码,但是我们必须创建很多线程,这是我要解释和使用 runOnUiThread() 我不能分开我的两个类,因为myDownloadAsyncTask 类 这似乎不是问题的答案。更像是应该在问题中编辑的附加信息。以上是关于使用 CountDownTimer 更新 ProgressBar的主要内容,如果未能解决你的问题,请参考以下文章