简体   繁体   English

如何在 Android 中创建生命周期感知处理程序?

[英]How to create Life Cycle Aware Handler in Android?

First of all, I know how to create Handler.首先,我知道如何创建Handler。

I am working on a project where I am using Handler with postDelayed .我正在一个项目中使用HandlerpostDelayed There are some times when app got crashed because activity was destroyed and the task inside the handler executes after activity destroy .有时应用程序崩溃是因为Activity 被破坏并且处理程序中的任务在 Activity destroy 之后执行

I am looking for an alternative of Handler which can execute after a delay and it could be Lifecycle Aware so that the app won't get crash.我正在寻找 Handler 的替代方案,它可以在延迟后执行,它可以是生命周期感知的,这样应用程序就不会崩溃。

I know how to cancel Handler (removing Handler or cancelling handler inside onDestroy/onStop methods of activity), here is the link for the same.我知道如何取消处理程序(在活动的 onDestroy/onStop 方法中删除处理程序或取消处理程序),这是相同的链接 But I am not looking for these solutions.但我不是在寻找这些解决方案。 Any alternative would be a better solution if one can have.如果可以的话,任何替代方案都会是更好的解决方案。

Thanks in advance!提前致谢!

if you are familiar and ok with using coroutines , you can replace Handlers to achieve the same functionality如果您熟悉并且可以使用coroutines ,您可以替换Handlers以实现相同的功能

using below dependency with coroutines you can make coroutines lifecycle aware将以下依赖项与协程一起使用,您可以使协程具有生命周期意识

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"

then in Activity然后在活动中

lifeCycleScope.launchWhenStarted{
     delay(1000)

     //do your work after delay, runs on main thread 
     //by default, will be cancelled if life cycle is inactive
}

More about using coroutines: Deep Dive into Coroutines + Android更多关于使用协程: Deep Dive into Coroutines + Android

Depending on if you're using java or Kotlin, you can use RxJava or coroutines for this.根据您使用的是 java 还是 Kotlin,您可以为此使用 RxJava 或协程。

RxJava solution RxJava 解决方案

// this should be a member variable
private final CompositeDisposable disposables = new CompositeDisposable();

// this is how you launch the task that needs delay
Disposable d = Single.timer(2, TimeUnit.SECONDS)
    .subscribeOn(Schedulers.io())
    .observeOn(schedulers.ui())
    .subscribe(ignored -> {
        // you can manipulate the ui here
     });
        
// make sure to call disposables.clear() in onDestroyView
disposables.add(d);

Kotlin solution Kotlin 解决方案

viewLifecycleOwner.lifecycleScope.launchWhenResumed {
   withContext(Dispatchers.IO) {
       delay(2000)
   }
   // you can manipulate the ui here
}

As you can see the Kotlin + coroutines solution requires much less manual work, and it's harder to get wrong, so if you're on a Kotlin project I think you should use that one.如您所见,Kotlin + 协程解决方案需要的手动工作要少得多,而且更难出错,所以如果您在 Kotlin 项目中,我认为您应该使用那个。 Other alternative may be to use Guava ListenableFuture s but I haven't work with those yet.其他选择可能是使用 Guava ListenableFuture ,但我还没有使用这些。

If you are using a Handler to execute delayed actions with postDelayed() you can run into troubles when the execution of the action happens after your Activity or Fragment has been destroyed.如果您使用Handler使用postDelayed()执行延迟操作,则当您的 Activity 或 Fragment 被销毁后执行该操作时,您可能会遇到麻烦。

There is a simple solution to this.有一个简单的解决方案。 Bind your Handler to the lifecycle.将您的处理程序绑定到生命周期。

Create a LifecycleObserver创建 LifecycleObserver

First lets create a LifecycleObserver that gets a Handler instance.首先让我们创建一个获取Handler实例的LifecycleObserver In the event of Lifecycle.Event.ON_DESTROY it will remove all callbacks and messages from that Handler .Lifecycle.Event.ON_DESTROY事件中,它将从该Handler中删除所有回调和消息。

class LifecycleObververHandler(private val handler: Handler) : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    internal fun onDestroy() {
        handler.removeCallbacksAndMessages(null)
    }
}

Add the LifecycleObserver to the LifecycleOwner将 LifecycleObserver 添加到 LifecycleOwner

Next we have to add the LifecycleObververHandler to a LifecycleOwner .接下来,我们必须将LifecycleObververHandler添加到LifecycleOwner We also wanna create these lifecycle observed handlers easily.我们还想轻松地创建这些生命周期观察处理程序。 So lets create a LifecycleHandlerFactory .所以让我们创建一个LifecycleHandlerFactory

That factory gets created with a lambda handlerFactory that gives you an instance of a Handler (default is a Handler with a main Looper).该工厂是使用 lambda handlerFactory创建的,它为您提供了一个Handler的实例(默认是一个带有主 Looper 的Handler )。 It has one function create that expects a LifecycleOwner .它有一个需要LifecycleOwner的 function create

Within that function it checks that the state of the Lifecycle is not DESTROYED .在该 function 中,它检查LifecycleDESTROYED是否未销毁。 It calls the handlerFactory to get an instance of Handler .它调用handlerFactory来获取Handler的实例。 Then it creates a LifecycleObserverHandler , which takes the handler, and adds that Observer to the LifecycleOwner .然后它创建一个LifecycleObserverHandler ,它接受处理程序,并将该Observer添加到LifecycleOwner Finally the Handler gets returned.最后返回Handler程序。

class LifecycleHandlerFactory(private val handlerFactory: (() -> Handler) = { Handler(Looper.getMainLooper()) }) {

    fun create(owner: LifecycleOwner): Handler {
        check(owner.lifecycle.currentState != Lifecycle.State.DESTROYED) {
            "Cannot create a Handler for a destroyed life-cycle"
        }
        val handler = handlerFactory.invoke()
        val observer = LifecycleObververHandler(handler)
        owner.lifecycle.addObserver(observer)
        return handler
    }
}

Inject the lifecycle aware Handler注入生命周期感知处理程序

When you are using a DependendencyInjection Framework or a service locater like Koin you can inject the lifecycle aware Handler .当您使用 DependendencyInjection 框架或像Koin这样的服务定位器时,您可以注入生命周期感知Handler

module {
  // a single instance of LifecycleHandlerFactory
  // it gets a lambda that every time its being called returnes a new Handler with a main looper.
  single { LifecycleHandlerFactory() }
  
  // uses the LifecycleHandlerFactory to create a new handler with a LifecycleOwner as parameter.
  factory<Handler> { (lifecycleOwner: LifecycleOwner) -> get<LifecycleHandlerFactory>().create(lifecycleOwner) }
}

Finally you can inject a lifecycle handler in your Fragment (or Activity).最后,您可以在 Fragment(或 Activity)中注入生命周期处理程序。

// injects a new handler with a LifecycleOwner as a parameter
private val handler: Handler by inject { parametersOf(viewLifecycleOwner) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM