시간 지연이 있는 작업을 반복하시겠습니까?
코드에 "상태"라는 변수가 있습니다.
이 변수 값에 따라 응용 프로그램에 일부 텍스트를 표시합니다.이 작업은 특정 시간 지연으로 수행해야 합니다.
같습니다,
상태 변수 값 확인
일부 텍스트 표시
10초간 기다립니다.
상태 변수 값 확인
일부 텍스트 표시
15초간 기다립니다.
등등.시간 지연은 다양할 수 있으며 텍스트가 표시되면 설정됩니다.
난 시도했다.Thread.sleep(time delay)
실패했습니다.이 일을 끝낼 더 좋은 방법은 없습니까?
사용해야 합니다.Handler
의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의 코드를 사용하여 만든 클래스가 있습니다(주기적으로 UI를 업데이트하는 데 사용하기 때문에 UIUpdater라고 불렀지만 원하는 이름으로 불러도 됩니다).
import android.os.Handler;
/**
* A class used to perform periodical updates,
* specified inside a runnable object. An update interval
* may be specified (otherwise, the class will perform the
* update every 2 seconds).
*
* @author Carlos Simões
*/
public class UIUpdater {
// Create a Handler that uses the Main Looper to run in
private Handler mHandler = new Handler(Looper.getMainLooper());
private Runnable mStatusChecker;
private int UPDATE_INTERVAL = 2000;
/**
* Creates an UIUpdater object, that can be used to
* perform UIUpdates on a specified time interval.
*
* @param uiUpdater A runnable containing the update routine.
*/
public UIUpdater(final Runnable uiUpdater) {
mStatusChecker = new Runnable() {
@Override
public void run() {
// Run the passed runnable
uiUpdater.run();
// Re-run it after the update interval
mHandler.postDelayed(this, UPDATE_INTERVAL);
}
};
}
/**
* The same as the default constructor, but specifying the
* intended update interval.
*
* @param uiUpdater A runnable containing the update routine.
* @param interval The interval over which the routine
* should run (milliseconds).
*/
public UIUpdater(Runnable uiUpdater, int interval){
UPDATE_INTERVAL = interval;
this(uiUpdater);
}
/**
* Starts the periodical update routine (mStatusChecker
* adds the callback to the handler).
*/
public synchronized void startUpdates(){
mStatusChecker.run();
}
/**
* Stops the periodical update routine from running,
* by removing the callback.
*/
public synchronized void stopUpdates(){
mHandler.removeCallbacks(mStatusChecker);
}
}
그런 다음 클래스 내에 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);
세 가지 방법이 있습니다.
예약 사용스레드 풀 실행자
스레드 풀이 필요 없기 때문에 약간의 과잉 살상.
//----------------------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();
}
타이머 작업 사용
오래된 안드로이드 스타일
//----------------------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-------------------------
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
}
};
활동/Fragment에서 처리기 개체 초기화(여기서 FlashActivity는 내 활동 클래스)
//Task Handler
private Handler taskHandler = new NonLeakyHandler(FlashActivity.this);
고정 시간 간격 후 태스크를 반복하려면 다음과 같이 하십시오.
taskHandler.postDelayed(반복 작업실행 가능, DELETY_)MILIS);
작업의 반복을 중지하려면 다음과 같이 하십시오.
taskHandler .remove콜백(반복적인 TaskRunnable);
업데이트: 코틀린에서:
//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);
}
타이머는 정상적으로 작동합니다.여기서 나는 타이머를 사용하여 1.5초 후 텍스트를 검색하고 UI를 업데이트합니다.도움이 되길 바랍니다.
private Timer _timer = new Timer();
_timer.schedule(new TimerTask() {
@Override
public void run() {
// use runOnUiThread(Runnable action)
runOnUiThread(new Runnable() {
@Override
public void run() {
search();
}
});
}
}, timeInterval);
코틀린과 코루틴을 사용하는 것은 매우 쉽습니다. 먼저 다음과 같이 클래스에서 작업을 선언합니다(당신이 보기에 더 나은 모델).
private var repeatableJob: Job? = null
그런 다음 만들고 시작하려면 다음을 수행합니다.
repeatableJob = viewModelScope.launch {
while (isActive) {
delay(5_000)
loadAlbums(iImageAPI, titleHeader, true)
}
}
repeatableJob?.start()
그리고 당신이 그것을 끝내고 싶다면:
repeatableJob?.cancel()
PS:viewModelScope
뷰 할 수 , 뷰 모 사 수 에 며 과 다 음 같 다 은 른 있 할 니 습 수 용 다 사 를 델 위 범 서 만 으 있 용 할 ▁as ▁cor 니 ▁is▁such▁sc다있ine, 등의 다른 Coroutine 스코프를 할 수 .withContext(Dispatchers.IO)
추가 정보: 여기
타이머는 당신의 일을 하는 또 다른 방법이지만 조용히 하세요.runOnUiThread
UI로 작업하는 경우.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;
public class MainActivity extends Activity {
CheckBox optSingleShot;
Button btnStart, btnCancel;
TextView textCounter;
Timer timer;
MyTimerTask myTimerTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
optSingleShot = (CheckBox)findViewById(R.id.singleshot);
btnStart = (Button)findViewById(R.id.start);
btnCancel = (Button)findViewById(R.id.cancel);
textCounter = (TextView)findViewById(R.id.counter);
btnStart.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
if(timer != null){
timer.cancel();
}
//re-schedule timer here
//otherwise, IllegalStateException of
//"TimerTask is scheduled already"
//will be thrown
timer = new Timer();
myTimerTask = new MyTimerTask();
if(optSingleShot.isChecked()){
//singleshot delay 1000 ms
timer.schedule(myTimerTask, 1000);
}else{
//delay 1000ms, repeat in 5000ms
timer.schedule(myTimerTask, 1000, 5000);
}
}});
btnCancel.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if (timer!=null){
timer.cancel();
timer = null;
}
}
});
}
class MyTimerTask extends TimerTask {
@Override
public void run() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat =
new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
final String strDate = simpleDateFormat.format(calendar.getTime());
runOnUiThread(new Runnable(){
@Override
public void run() {
textCounter.setText(strDate);
}});
}
}
}
그리고 xml은...
<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"/>
CountDownTimer를 사용하는 다른 방법
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
이후 시간까지 카운트다운을 예약하고 중간 간격으로 정기적으로 알림을 보냅니다.텍스트 필드에 30초 카운트다운 표시 예:
그것이 작동하는 예를 따라 해보세요!!!
[Handler]는 메시지 큐에 Runnable을 추가하도록 하는 postDelayed() 메서드를 사용하는 onCreate() 메서드에서 [Handler]를 사용합니다. 이 메서드는 지정된 시간이 경과한 후 실행됩니다(예: 0). 1
다음 코드 참조:
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);
}
};
처리기를 사용하여 실행 가능한 코드를 게시할 수 있습니다.이 기술은 여기에 매우 잘 설명되어 있습니다. https://guides.codepath.com/android/Repeating-Periodic-Tasks
예정된 일정과 관련된 위 게시물을 기반으로 합니다.ThreadPoolExecuter, 저는 제 요구에 맞는 유틸리티를 생각해 냈습니다(매 3초마다 메소드를 실행하고 싶었습니다).
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);
}
}
이 경우 이전 프로세스가 완료되었거나 이미 5초가 경과한 경우 다음 조건 중 하나가 충족되면 프로세스를 실행해야 했습니다.그래서 저는 다음을 수행했고 꽤 잘 일했습니다.
private Runnable mStatusChecker;
private Handler mHandler;
class {
method() {
mStatusChecker = new Runnable() {
int times = 0;
@Override
public void run() {
if (times < 5) {
if (process1.isRead()) {
executeProcess2();
} else {
times++;
mHandler.postDelayed(mStatusChecker, 1000);
}
} else {
executeProcess2();
}
}
};
mHandler = new Handler();
startRepeatingTask();
}
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
}
process1이 읽히면 process2를 실행합니다.그렇지 않으면 변수 시간이 증가하고 1초 후에 처리기가 실행됩니다.프로세스 1이 읽히거나 시간이 5가 될 때까지 루프를 유지합니다.시간이 5일 때는 5초가 지났음을 의미하며 각 초마다 process1.isRead()의 if 절이 실행됩니다.
Kotlin을 사용하는 사람들의 경우 inazaruk의 대답은 작동하지 않을 것이고, IDE는 변수를 초기화하도록 요구할 것입니다. 그래서 대신에postDelayed
에의 에.Runnable
우리는 그것을 다른 방법으로 사용할 것입니다.
기화를 합니다.
Runnable
과 같이: 식으로런이:private var myRunnable = Runnable { //Do some work //Magic happens here ↓ runDelayedHandler(1000) }
기화를 합니다.
runDelayedHandler
과 같습니다.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) } }
보다시피, 이 접근 방식을 통해 작업의 수명을 제어할 수 있으며, 다음을 추적할 수 있습니다.
keepRunning
응용프로그램의 수명 동안 변경하면 작업을 수행할 수 있습니다.
언급URL : https://stackoverflow.com/questions/6242268/repeat-a-task-with-a-time-delay
'programing' 카테고리의 다른 글
Windows용 iPhone Browser 시뮬레이터? (0) | 2023.08.07 |
---|---|
mysqdump 시 사용자를 지정하는 것과 지정하지 않는 것의 차이점은 무엇입니까? (0) | 2023.08.07 |
PHP를 사용하는 Oracle에서 선택된 행 수 계산 (0) | 2023.08.02 |
왼쪽 외부 조인에 대한 SQL 성능이 존재하지 않음 (0) | 2023.08.02 |
"이것.앱inits[i]는 함수가 아닙니다. (0) | 2023.08.02 |