IT이야기

Android에서 지연된 후 메소드를 호출하는 방법

cyworld 2022. 4. 28. 20:39
반응형

Android에서 지연된 후 메소드를 호출하는 방법

나는 지정된 지연 후에 다음 방법으로 전화할 수 있기를 원한다.객관적인 c에서는 다음과 같은 것이 있었다.

[self performSelector:@selector(DoSomething) withObject:nil afterDelay:5];

자바를 가진 안드로이드에 이 방법과 동등한 것이 있는가?예를 들어 나는 5초 후에 메소드를 호출할 수 있어야 해.

public void DoSomething()
{
     //do something here
}

코틀린

Handler(Looper.getMainLooper()).postDelayed({
    //Do something after 100ms
}, 100)

자바

final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something after 100ms
    }
}, 100);

나는 내 경우에 다른 어떤 대답도 사용할 수 없었다.나는 대신 네이티브 자바 타이머를 사용했다.

new Timer().schedule(new TimerTask() {          
    @Override
    public void run() {
        // this code will be executed after 2 seconds       
    }
}, 2000);

참고: 이 대답은 질문이 Android를 컨텍스트로 지정하지 않았을 때 제공되었다.Android UI 스레드 관련 답변은 여기를 참조하십시오.


Mac OS API가 현재 스레드를 계속 실행하도록 하고 비동기식으로 태스크를 실행하도록 예약하는 것처럼 보인다.자바에서는 에 의해 등가함수가 제공된다.java.util.concurrent꾸러미 안드로이드가 어떤 제한을 가할지 모르겠다.

private static final ScheduledExecutorService worker = 
  Executors.newSingleThreadScheduledExecutor();

void someMethod() {
  ⋮
  Runnable task = new Runnable() {
    public void run() {
      /* Do something… */
    }
  };
  worker.schedule(task, 5, TimeUnit.SECONDS);
  ⋮
}

5초 후에 UI 스레드에서 무언가를 실행하는 경우:

new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something here
    }
}, 5000);

Kotlin&Java여러 가지 방법

1. 사용Handler

Handler().postDelayed({
    TODO("Do something")
    }, 2000)

2. TimerTask 사용

Timer().schedule(object : TimerTask() {
    override fun run() {
        TODO("Do something")
    }
}, 2000)

아니면 심지어 더 짧다.

Timer().schedule(timerTask {
    TODO("Do something")
}, 2000)

아니면 가장 짧을 것이다.

Timer().schedule(2000) {
    TODO("Do something")
}

. 3.. 사용Executors

Executors.newSingleThreadScheduledExecutor().schedule({
    TODO("Do something")
}, 2, TimeUnit.SECONDS)

자바에서

1. 사용Handler

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something
    }
}, 2000);

2. 사용Timer

new Timer().schedule(new TimerTask() {          
    @Override
    public void run() {
        // Do something
    }
}, 2000);

. 3.. 사용ScheduledExecutorService

private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();

Runnable runnable = new Runnable() {
  public void run() {
      // Do something
  }
  };
worker.schedule(runnable, 2, TimeUnit.SECONDS);

UIThread 내의 처리기를 사용할 수 있음:

runOnUiThread(new Runnable() {
                
    @Override
    public void run() {
        new Handler().postDelayed(new Runnable() {
           @Override
           public void run() {
               //add your code here
          }
        }, 1000);           
    }
});

모든 훌륭한 답변에 감사하며, 나는 내 필요에 가장 적합한 해결책을 찾았다.

Handler myHandler = new DoSomething();
Message m = new Message();
m.obj = c;//passing a parameter here
myHandler.sendMessageDelayed(m, 1000);

class DoSomething extends Handler {
    @Override
    public void handleMessage(Message msg) {
      MyObject o = (MyObject) msg.obj;
      //do something here
    }
}

다음 데모를 참조하십시오.

import java.util.Timer;
import java.util.TimerTask;

class Test {
     public static void main( String [] args ) {
          int delay = 5000;// in ms 

          Timer timer = new Timer();

          timer.schedule( new TimerTask(){
             public void run() { 
                 System.out.println("Wait, what..:");
              }
           }, delay);

           System.out.println("Would it run?");
     }
}

처리기를 사용해야 하지만 다른 스레드에 빠져 있는 경우runonuithreadUI 스레드에서 처리기를 실행하십시오.이렇게 하면 전화를 걸기 위해 던져진 예외로부터 당신을 구할 수 있다.Looper.Prepare()

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //Do something after 1 second
            }
        }, 1000);
    }
});

꽤 지저분해 보이지만, 이것이 방법 중 하나이다.

나는 사용하는 것을 더 좋아한다.View.postDelayed()메서드, 아래의 단순 코드:

mView.postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do something after 1000 ms
    }
}, 1000);

가장 짧은 해결책은 다음과 같다.

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //Do something after 100ms
    }
}, 100);

Android Studio 3.0 이상을 사용하는 경우 람다 식을 사용할 수 있다.방법callMyMethod()2시간 에에:

new Handler().postDelayed(() -> callMyMethod(), 2000);

지연된 실행 가능을 취소해야 하는 경우 다음을 사용하십시오.

Handler handler = new Handler();
handler.postDelayed(() -> callMyMethod(), 2000);

// When you need to cancel all your posted runnables just use:
handler.removeCallbacksAndMessages(null);

안전 강화 - Kotlin Coroutine 사용

대부분의 답변은 Handroid Lifecycle을 사용하지만 나는 Android Lifecycle extend로 활동, 단편, 보기 모델 지연을 위한 다른 솔루션을 제공한다.이렇게 하면 라이프사이클이 파괴되기 시작할 때 자동으로 취소됨 - 메모리 누수 또는충돌 방지

활동 또는 조각에서:

lifecycleScope.launch { 
  delay(DELAY_MS)
  doSomething()
}

ViewModel에서:

viewModelScope.lanch {
  delay(DELAY_MS)
  doSomething()
}

일시 중단 함수: (Kotlin Coroutine)

suspend fun doSomethingAfter(){
    delay(DELAY_MS)
    doSomething()
}

라이프사이클에 오류가 발생하는 경우스코프를 찾을 수 없음! - 이 종속성을 앱 그라들 파일로 가져오기:

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0"
final Handler handler = new Handler(); 
Timer t = new Timer(); 
t.schedule(new TimerTask() { 
    public void run() { 
        handler.post(new Runnable() { 
            public void run() { 
                //DO SOME ACTIONS HERE , THIS ACTIONS WILL WILL EXECUTE AFTER 5 SECONDS...
            }
        }); 
    } 
}, 5000); 

타이머를 추천한다. 타이머를 사용하면 아주 특정한 간격으로 호출할 수 있는 방법을 계획할 수 있다.이렇게 하면 UI가 차단되지 않으며 메서드가 실행되는 동안 앱의 재전송 상태를 유지할 수 있다.

다른 옵션은 wait(); 메서드인데, 이렇게 하면 지정된 시간 동안 현재 스레드가 차단된다.이렇게 하면 UI 스레드에서 UI 응답이 중지된다.

그래서 이 고양이 가죽을 벗기는 방법은 매우 많기 때문에 여기서 고려해야 할 몇 가지가 있다.이미 모든 답변이 선택과 선택으로 주어졌지만.단지 "주요 선택 단순 답변" 때문에 잘못된 방향으로 가는 사람을 피하기 위해 적절한 코딩 가이드라인을 통해 이 문제를 재검토하는 것이 중요하다고 생각한다.

먼저 이 실에서 전반적으로 선택된 정답인 간단한 Post Delayed 답변에 대해 토론해 봅시다.

고려해야 할 몇 가지 사항.사후지연 후에는 기억의 유출, 죽은 물체, 사라진 라이프 사이클 등을 만날 수 있다.그래서 그것을 적절하게 다루는 것 또한 중요하다.두 가지 방법으로 이것을 할 수 있다.

현대 발전을 위해 코틀린에서 공급할 것이다.

다음은 콜백에 UI 스레드를 사용하고 콜백을 칠 때 활동이 아직 활성화되어 있는지 확인하는 간단한 예입니다.

  Handler(Looper.getMainLooper()).postDelayed({
            if(activity != null && activity?.isFinishing == false){
                txtNewInfo.visibility = View.GONE
            }
        }, NEW_INFO_SHOW_TIMEOUT_MS)

하지만, 활동이 사라졌으면 콜백을 칠 이유가 없기 때문에, 더 좋은 방법은 콜백을 계속 참고하고 이렇게 콜백을 제거하는 것이다.

    private fun showFacebookStylePlus1NewsFeedOnPushReceived(){
        A35Log.v(TAG, "showFacebookStylePlus1NewsFeedOnPushReceived")
        if(activity != null && activity?.isFinishing == false){
            txtNewInfo.visibility = View.VISIBLE
            mHandler.postDelayed({
                if(activity != null && activity?.isFinishing == false){
                    txtNewInfo.visibility = View.GONE
                }
            }, NEW_INFO_SHOW_TIMEOUT_MS)
        }
    }

그리고 콜백에 닿지 않도록 당연히 onPause의 정리를 처리하십시오.

    override fun onPause() {
        super.onPause()
        mHandler.removeCallbacks(null)
    }

이제 뻔한 것을 다뤘으니, 현대식 코루틴과 코틀린 :)과 함께 더 깨끗한 옵션에 대해 이야기해 보자.만약 네가 아직 이것을 사용하지 않는다면, 너는 정말 놓치고 있는 거야.

   fun doActionAfterDelay() 
        launch(UI) {
            delay(MS_TO_DELAY)           
            actionToTake()
        }
    }

또는 해당 방법으로 UI를 항상 실행하려면 다음을 수행하십시오.

  fun doActionAfterDelay() = launch(UI){ 
      delay(MS_TO_DELAY)           
      actionToTake()
  }

물론 PostDelayed와 마찬가지로 당신은 당신이 취소 처리를 확실히 해야 당신이 지연 통화 후에 활동 점검을 할 수 있거나 다른 경로와 마찬가지로 일시 정지 상태에서 그것을 취소할 수 있다.

var mDelayedJob: Job? = null
fun doActionAfterDelay() 
   mDelayedJob = launch(UI) {
            try {
               delay(MS_TO_DELAY)           
               actionToTake()
            }catch(ex: JobCancellationException){
                showFancyToast("Delayed Job canceled", true, FancyToast.ERROR, "Delayed Job canceled: ${ex.message}")
            }
        }
   }
}

//청소

override fun onPause() {
   super.onPause()
   if(mDelayedJob != null && mDelayedJob!!.isActive) {
      A35Log.v(mClassTag, "canceling delayed job")
      mDelayedJob?.cancel() //this should throw CancelationException in coroutine, you can catch and handle appropriately
   }
}

실행(UI)을 메서드 서명에 넣으면 코드의 호출 라인에서 작업을 할당할 수 있다.

그래서 이 이야기의 교훈은 지연된 행동을 안전하게 하고, 콜백을 제거하거나, 직업을 취소하고, 물론 콜백 완료 시 아이템을 만질 수 있는 적절한 수명주기를 가지고 있는지 확인하는 것이다.코루틴은 취소 가능한 조치도 제공한다.

또한 일반적으로 코루틴과 함께 발생할 수 있는 다양한 예외를 처리해야 한다는 점도 유의할 필요가 있다.예를 들어, 취소, 예외, 시간 초과, 사용자가 무엇을 사용하기로 결정했든지.코루틴의 활용을 시작하기로 결정했을 때 보다 발전된 예가 여기에 있다.

   mLoadJob = launch(UI){
            try {
                //Applies timeout
                withTimeout(4000) {
                    //Moves to background thread
                    withContext(DefaultDispatcher) {
                        mDeviceModelList.addArrayList(SSDBHelper.getAllDevices())
                    }
                }

                //Continues after async with context above
                showFancyToast("Loading complete", true, FancyToast.SUCCESS)
            }catch(ex: JobCancellationException){
                showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
            }catch (ex: TimeoutCancellationException) {
                showFancyToast("Timed out saving, please try again or press back", true, FancyToast.ERROR, "Timed out saving to database: ${ex.message}")
            }catch(ex: Exception){
                showFancyToast("Error saving to database, please try again or press back", true, FancyToast.ERROR, "Error saving to database: ${ex.message}")
            }
        }

단순 줄 핸들 포스트 지연의 경우 다음과 같이 할 수 있다.

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // Do someting
    }
}, 3000);

이게 도움이 됐으면 좋겠는데

가장 간단한 솔루션에 사용할 수 있는 기능:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        //Write your code here
    }
}, 5000); //Timer is in ms here.

그렇지 않으면 아래는 또 다른 깨끗하고 유용한 솔루션이 될 수 있다.

new Handler().postDelayed(() -> 
{/*Do something here*/}, 
5000); //time in ms

새로 도입된 람다 식을 사용하면 훨씬 깨끗하게 만들 수 있다.

new Handler().postDelayed(() -> {/*your code here*/}, time);

코틀린을 이용하여 우리는 다음과 같은 일을 함으로써 성취할 수 있다.

Handler().postDelayed({
    // do something after 1000ms 
}, 1000)

RxAndroid를 사용하면 스레드와 오류 처리가 훨씬 쉬워진다.지연 후 다음 코드가 실행됨

Observable.timer(delay, TimeUnit.SECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(aLong -> {
            // Execute code here
        }, Throwable::printStackTrace);

나는 이것을 부르는 더 간단한 방법을 만들었다.

public static void CallWithDelay(long miliseconds, final Activity activity, final String methodName)
    {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                try {
                    Method method =  activity.getClass().getMethod(methodName);
                    method.invoke(activity);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }, miliseconds);
    }

이 서비스를 사용하려면 다음 연락처로 전화하십시오..CallWithDelay(5000, this, "DoSomething");

아래는 당신이 받을 때,

자바.의RuntimeException:Looper.prepare()를 호출하지 않은 스레드 내부에 핸들러를 만들 수 없음

final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
    //Do something after 100ms
  }
}, 100);

그것은 사용하기에 매우 쉽다.CountDownTimer자세한 내용은 https://developer.android.com/reference/android/os/CountDownTimer.html를 참조하십시오.

import android.os.CountDownTimer;

// calls onTick every second, finishes after 3 seconds
new CountDownTimer(3000, 1000) { 

   public void onTick(long millisUntilFinished) {
      Log.d("log", millisUntilFinished / 1000);
   }

   public void onFinish() {
      // called after count down is finished
   } 
}.start();

나는 더 깨끗한 것을 좋아한다.다음은 메소드 내에서 사용할 인라인 코드 구현

new Handler().postDelayed(new Runnable() {
  @Override
  public void run() {
    //Do something after 100ms
  }
}, 100);

모든 사람이 새로운 실행 가능 또는 메시지를 게시하기 전에 핸들러를 청소하는 것을 잊은 것 같다.그렇지 않으면 그들은 잠재적으로 축적되어 나쁜 행동을 일으킬 수 있다.

handler.removeMessages(int what);
// Remove any pending posts of messages with code 'what' that are in the message queue.

handler.removeCallbacks(Runnable r)
// Remove any pending posts of Runnable r that are in the message queue.

실행 가능한 UI 요소를 변경할 때 예외가 발생하지 않는다는 또 다른 까다로운 방법이 있다.

public class SimpleDelayAnimation extends Animation implements Animation.AnimationListener {

    Runnable callBack;

    public SimpleDelayAnimation(Runnable runnable, int delayTimeMilli) {
        setDuration(delayTimeMilli);
        callBack = runnable;
        setAnimationListener(this);
    }

    @Override
    public void onAnimationStart(Animation animation) {

    }

    @Override
    public void onAnimationEnd(Animation animation) {
        callBack.run();
    }

    @Override
    public void onAnimationRepeat(Animation animation) {

    }
}

애니메이션을 다음과 같이 부를 수 있다.

view.startAnimation(new SimpleDelayAnimation(delayRunnable, 500));

애니메이션은 어떤 시각에도 붙일 수 있다.

게으르고 게으른 사람들아, 코틀린에 답이 있다.

Handler().postDelayed({
//doSomethingHere()
}, 1000)

안드로이드의 적합한 솔루션:

private static long SLEEP_TIME = 2 // for 2 second
.
.
MyLauncher launcher = new MyLauncher();
            launcher.start();
.
.
private class MyLauncher extends Thread {
        @Override
        /**
         * Sleep for 2 seconds as you can also change SLEEP_TIME 2 to any. 
         */
        public void run() {
            try {
                // Sleeping
                Thread.sleep(SLEEP_TIME * 1000);
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
            //do something you want to do
           //And your code will be executed after 2 second
        }
    }

비슷한 용액이지만 사용하기에 훨씬 깨끗함

이 함수를 강의실 외부로 쓰십시오.

fun delay(duration: Long, `do`: () -> Unit) {

    Handler().postDelayed(`do`, duration)

}

사용량:

delay(5000) {
    //Do your work here
}

참조URL: https://stackoverflow.com/questions/3072173/how-to-call-a-method-after-a-delay-in-android

반응형