Android 以延时重复任务?
我的代码中有一个变量,表示它是“status” 我想根据这个变量值在应用程序中显示一些文本。这必须在特定的时间延迟内完成 就像Android 以延时重复任务?,android,android-thread,Android,Android Thread,我的代码中有一个变量,表示它是“status” 我想根据这个变量值在应用程序中显示一些文本。这必须在特定的时间延迟内完成 就像 检查状态变量值 显示一些文本 等待10秒钟 检查状态变量值 显示一些文本 等待15秒 等等。时间延迟可能会发生变化,并且在显示文本后设置 我尝试了Thread.sleep(延时),但失败了。是否有更好的方法来完成此任务?为此,您应该使用处理程序的postDelayed函数。它将在主UI线程上以指定的延迟运行代码,因此您将能够更新UI控件 private int mI
- 检查状态变量值
- 显示一些文本
- 等待10秒钟
- 检查状态变量值
- 显示一些文本
- 等待15秒
我尝试了
Thread.sleep(延时)
,但失败了。是否有更好的方法来完成此任务?为此,您应该使用处理程序的postDelayed
函数。它将在主UI线程上以指定的延迟运行代码,因此您将能够更新UI控件
private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;
@Override
protected void onCreate(Bundle bundle) {
// your code here
mHandler = new Handler();
startRepeatingTask();
}
@Override
public void onDestroy() {
super.onDestroy();
stopRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
@Override
public void run() {
try {
updateStatus(); //this function can change value of mInterval.
} finally {
// 100% guarantee that this always happens, even if
// your update method throws an exception
mHandler.postDelayed(mStatusChecker, mInterval);
}
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
对于任何感兴趣的人,这里有一个我使用inazaruk的代码创建的类,它创建了所需的一切(我称之为UIUpdater,因为我使用它定期更新UI,但您可以随意调用它):
然后,您可以在类中创建UIUpdater对象,并像这样使用它:
...
mUIUpdater = new UIUpdater(new Runnable() {
@Override
public void run() {
// do stuff ...
}
});
// Start updates
mUIUpdater.startUpdates();
// Stop updates
mUIUpdater.stopUpdates();
...
如果您想将其用作活动更新程序,请将开始调用放在onResume()方法中,将停止调用放在onPause()中,以便根据活动可见性启动和停止更新。我认为新的热点是使用。像这样:
private final ScheduledThreadPoolExecutor executor_ =
new ScheduledThreadPoolExecutor(1);
this.executor_.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
update();
}
}, 0L, kPeriod, kTimeUnit);
试试下面的例子吧
在onCreate()方法中使用[Handler],该方法使用postDelayed()方法,将Runnable添加到消息队列中,并在给定示例中为0的指定时间后运行
请参阅此代码:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
android.os.Handler customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable()
{
public void run()
{
//write here whaterver you want to repeat
customHandler.postDelayed(this, 1000);
}
};
定时器是完成工作的另一种方式,但如果您正在使用UI,请确保添加runOnUiThread
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<CheckBox
android:id="@+id/singleshot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Single Shot"/>
xml是
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
安排一个倒计时,直到将来某个时间,并定期通知沿途的时间间隔。在文本字段中显示30秒倒计时的示例:
您可以使用处理程序发布可运行代码。这里很好地介绍了这项技术:定时器工作正常。在这里,我使用定时器搜索1.5s后的文本并更新UI。希望有帮助
class MyActivity {
private ScheduledThreadPoolExecutor mDialogDaemon;
private void initDebugButtons() {
Button btnSpawnDialogs = (Button)findViewById(R.id.btn_spawn_dialogs);
btnSpawnDialogs.setVisibility(View.VISIBLE);
btnSpawnDialogs.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
spawnDialogs();
}
});
}
private void spawnDialogs() {
if (mDialogDaemon != null) {
mDialogDaemon.shutdown();
mDialogDaemon = null;
}
mDialogDaemon = new ScheduledThreadPoolExecutor(1);
// This process will execute immediately, then execute every 3 seconds.
mDialogDaemon.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
// Do something worthwhile
}
});
}
}, 0L, 3000L, TimeUnit.MILLISECONDS);
}
}
基于以上关于的帖子,我想出了一个适合我需要的实用程序(希望每3秒触发一个方法):
在我的例子中,如果其中一个条件为真,我必须执行一个进程:如果前一个进程已经完成,或者如果已经过了5秒。因此,我做了以下工作,并且做得很好:
//----------------------SCHEDULER-------------------------
private final ScheduledThreadPoolExecutor executor_ =
new ScheduledThreadPoolExecutor(1);
ScheduledFuture<?> schedulerFuture;
public void startScheduler() {
schedulerFuture= executor_.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
//DO YOUR THINGS
pageIndexSwitcher.setVisibility(View.GONE);
}
}, 0L, 5*MILLI_SEC, TimeUnit.MILLISECONDS);
}
public void stopScheduler() {
pageIndexSwitcher.setVisibility(View.VISIBLE);
schedulerFuture.cancel(false);
startScheduler();
}
私有可运行mStatusChecker;
私人经理人;
阶级{
方法(){
mStatusChecker=new Runnable(){
整数倍=0;
@凌驾
公开募捐{
如果(次数<5){
if(process1.isRead()){
executeProcess2();
}否则{
时代++;
mHandler.postDelayed(mStatusChecker,1000);
}
}否则{
executeProcess2();
}
}
};
mHandler=新处理程序();
startRepeatingTask();
}
void startRepeatingTask(){
mStatusChecker.run();
}
void stopRepeatingTask(){
mHandler.removeCallbacks(mStatusChecker);
}
}
如果读取了process1,它将执行process2。如果不是,则递增变量时间,并使处理程序在一秒钟后执行。它保持一个循环,直到读取process1或times为5。当时间为5时,表示经过了5秒,每秒执行process1.isRead()的if子句。有3种方法:
使用ScheduledThreadPoolExecutor
有点过分,因为你不需要一个线程池
//----------------------TIMER TASK-------------------------
private Timer carousalTimer;
private void startTimer() {
carousalTimer = new Timer(); // At this line a new Thread will be created
carousalTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//DO YOUR THINGS
pageIndexSwitcher.setVisibility(INVISIBLE);
}
}, 0, 5 * MILLI_SEC); // delay
}
void stopTimer() {
carousalTimer.cancel();
}
使用Handler和Runnable
现代安卓风格
//----------------------HANDLER-------------------------
private Handler taskHandler = new android.os.Handler();
private Runnable repeatativeTaskRunnable = new Runnable() {
public void run() {
//DO YOUR THINGS
}
};
void startHandler() {
taskHandler.postDelayed(repeatativeTaskRunnable, 5 * MILLI_SEC);
}
void stopHandler() {
taskHandler.removeCallbacks(repeatativeTaskRunnable);
}
/**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
*/
private static class NonLeakyHandler extends Handler {
private final WeakReference<FlashActivity> mActivity;
public NonLeakyHandler(FlashActivity activity) {
mActivity = new WeakReference<FlashActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
FlashActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
}
具有活动/上下文的非泄漏处理程序
在活动/片段类中声明一个内部处理程序类
private Runnable repeatativeTaskRunnable = new Runnable() {
public void run() {
new Handler(getMainLooper()).post(new Runnable() {
@Override
public void run() {
//DO YOUR THINGS
}
};
//Task Handler
private Handler taskHandler = new NonLeakyHandler(FlashActivity.this);
初始化活动/片段中的处理程序对象(此处FlashActivity是我的活动类)
在固定时间间隔后重复任务
taskHandler.postDelayed(RepeativeTaskRunnable,DELAY_MILLIS)
停止重复任务
taskHandler.removeCallbacks(RepeativeTaskRunnable)
更新:在科特林:
对于使用Kotlin的人来说,将无法工作,IDE将要求初始化变量,因此我们将在Runnable
中使用postDelayed
,而不是在Runnable
中使用它
- 初始化
可运行的,如下所示:
private fun runDelayedHandler(timeToWait : Long) {
if (!keepRunning) {
//Stop your handler
handler.removeCallbacksAndMessages(null)
//Do something here, this acts like onHandlerStop
}
else {
//Keep it running
handler.postDelayed(myRunnable, timeToWait)
}
}
- 按如下方式初始化
runDelayedHandler
方法:
private var repeatableJob: Job? = null
- 如您所见,这种方法将使您能够控制任务的生命周期,跟踪
不断修剪,并在应用程序的生命周期内更改它,这将为您完成任务
使用kotlin及其协同程序非常简单,首先在类中声明作业(在viewModel中更好),如下所示:
repeatableJob = viewModelScope.launch {
while (isActive) {
delay(5_000)
loadAlbums(iImageAPI, titleHeader, true)
}
}
repeatableJob?.start()
然后,当您要创建并启动它时,请执行以下操作:
repeatableJob?.cancel()
如果你想完成它:
PS:viewModelScope
仅在视图模型中可用,您可以使用其他协同程序作用域,例如withContext(Dispatchers.IO)
更多信息:谢谢inazaruk,它成功运行了。发现2 v小的打字错误(顶部的“Handler”不是“Handle”,底部的“removeCallbacks”不是removecallback).但无论如何,代码正是我想要的。试着想想我能做些什么来报答你的恩惠。至少你赢得了我的尊重。向Aubrey Bourke致以亲切的问候。很好的程序,工作非常好。但是startRepeatingTask()必须从onCreate方法/UI线程调用(我花了一些时间才意识到这一点!),也许这一点可以
//update interval for widget
override val UPDATE_INTERVAL = 1000L
//Handler to repeat update
private val updateWidgetHandler = Handler()
//runnable to update widget
private var updateWidgetRunnable: Runnable = Runnable {
run {
//Update UI
updateWidget()
// Re-run it after the update interval
updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
}
}
// SATART updating in foreground
override fun onResume() {
super.onResume()
updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
}
// REMOVE callback if app in background
override fun onPause() {
super.onPause()
updateWidgetHandler.removeCallbacks(updateWidgetRunnable);
}
private var myRunnable = Runnable {
//Do some work
//Magic happens here ↓
runDelayedHandler(1000) }
private fun runDelayedHandler(timeToWait : Long) {
if (!keepRunning) {
//Stop your handler
handler.removeCallbacksAndMessages(null)
//Do something here, this acts like onHandlerStop
}
else {
//Keep it running
handler.postDelayed(myRunnable, timeToWait)
}
}
private var repeatableJob: Job? = null
repeatableJob = viewModelScope.launch {
while (isActive) {
delay(5_000)
loadAlbums(iImageAPI, titleHeader, true)
}
}
repeatableJob?.start()
repeatableJob?.cancel()