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

问题描述 投票:0回答:4

首先,我知道如何创建Handler。

我正在做一个项目,我正在使用

Handler
postDelayed
。有时应用程序崩溃是因为 activity 被销毁并且处理程序中的任务在 activity destroy 之后执行。

我正在寻找 Handler 的替代方案,它可以在延迟后执行,并且它可以是生命周期感知的,这样应用程序就不会崩溃。

我知道如何取消 Handler(删除 Handler 或取消活动的 onDestroy/onStop 方法中的处理程序),这是相同的link。但我不是在寻找这些解决方案。如果可以的话,任何替代方案都会是更好的解决方案。

提前致谢!

android kotlin android-lifecycle android-handler
4个回答
4
投票

根据您使用的是 java 还是 Kotlin,您可以为此使用 RxJava 或协程。

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 解决方案

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

如您所见,Kotlin + 协程解决方案需要的手动工作少得多,而且更难出错,所以如果您在 Kotlin 项目上,我认为您应该使用那个。其他选择可能是使用 Guava

ListenableFuture
s 但我还没有使用过这些。


1
投票

如果您使用

Handler
来执行带有
postDelayed()
的延迟操作,当您的 Activity 或 Fragment 被销毁后执行操作时,您可能会遇到麻烦。

对此有一个简单的解决方案。将您的处理程序绑定到生命周期。

创建生命周期观察者

首先让我们创建一个

LifecycleObserver
获取一个
Handler
实例。 在
Lifecycle.Event.ON_DESTROY
的情况下,它将删除该
Handler
.

中的所有回调和消息
class LifecycleObververHandler(private val handler: Handler) : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    internal fun onDestroy() {
        handler.removeCallbacksAndMessages(null)
    }
}

将 LifecycleObserver 添加到 LifecycleOwner

接下来我们必须将

LifecycleObververHandler
添加到
LifecycleOwner
。我们还想轻松地创建这些生命周期观察处理程序。所以让我们创建一个
LifecycleHandlerFactory
.

该工厂是使用 lambda

handlerFactory
创建的,它为您提供了一个
Handler
的实例(默认为带有主 Looper 的
Handler
)。它有一个函数
create
需要一个
LifecycleOwner
.

在该函数中,它检查

Lifecycle
的状态是否不是
DESTROYED
。它调用
handlerFactory
来获取
Handler
的实例。然后它创建一个
LifecycleObserverHandler
,它接受处理程序,并将该
Observer
添加到
LifecycleOwner
。最后
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
    }
}

注入生命周期感知处理程序

当您使用 DependendencyInjection Framework 或像 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) }
}

最后,您可以在片段(或活动)中注入生命周期处理程序。

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

1
投票

如果您熟悉并且可以使用

coroutines
,您可以替换
Handlers
以实现相同的功能

将以下依赖项与协程结合使用,您可以让协程了解生命周期

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

然后在活动中

lifeCycleScope.launchWhenStarted{
     delay(1000)

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

关于使用协程的更多信息:深入研究协程 + Android


0
投票

launchWhenResumed () 现在已弃用,现在看来解决方案如下:

    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.RESUMED) {
            delay(2000)
            yourFunction()
        }
    }

您可以使用以下小帮手:

fun LifecycleOwner.delayed(
    timeMillis: Long,
    state: Lifecycle.State = Lifecycle.State.RESUMED,
    block: () -> Unit
) {
    lifecycleScope.launch {
        repeatOnLifecycle(state) {
            delay(timeMillis)
            block()
        }
    }
}

喜欢:

delayed(2000) { yourFunction() }
© www.soinside.com 2019 - 2024. All rights reserved.