草庐IT

Jetpack Compose过渡 - 监听Acitvity生命周期

白熊小北极 2023-03-28 原文

事情是这样的

本人学习Compose有两周多了,目前已经着手重构项目上的UI,因为项目体积庞大,要把所有Activity段时间内替换成只有一个Compose的方式肯定不现实,目前就从替换xml布局开始。说实话,用了这么久的View,感觉有些坑挺多,View从反射到绘制需要的时间还是挺长的,经常会遇到因为绘制延迟导致的各式各样的问题,遂决定逐步迁移到Compose上面来。

使用场景

搜索全网,各式各样Compose相关的文章很多,也很详细,根据现有的资料,很难查到关于Activity声明周期监听的文章,因为大多数人都是使用单个Activity + Navigation 的形式。举个例子,在某些场景下,当用户进入新的Activity时,需要默认去请求页面所需的数据,如果在Compose中直接调用,肯定是不行的,根据Compose刷新机制,接口会被疯狂的调用,显然是不合理的,这里我就自己归纳出了一个方法作为过渡。

观察者

自制生命周期观察者,其中 DefaultLifecycleObserver 来自 androidx.lifecycle.DefaultLifecycleObserver

class ComposeLifecycleObserver : DefaultLifecycleObserver {

    private var create: (() -> Unit)? = null

    private var start: (() -> Unit)? = null

    private var resume: (() -> Unit)? = null

    private var pause: (() -> Unit)? = null

    private var stop: (() -> Unit)? = null

    private var destroy: (() -> Unit)? = null
    
    fun onLifeCreate(scope: () -> Unit) {
        this.create = scope
    }
    
    fun onLifeStart(scope: () -> Unit) {
        this.start = scope
    }
    
    fun onLifeResume(scope: () -> Unit) {
        resume = scope
    }
    
    fun onLifePause(scope: () -> Unit) {
        this.pause = scope
    }
    
    fun onLifeStop(scope: () -> Unit) {
        this.stop = scope
    }
    
    fun onLifeDestroy(scope: () -> Unit) {
        this.destroy = scope
    }

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        create?.invoke()
    }

    override fun onStart(owner: LifecycleOwner) {
        super.onStart(owner)
        start?.invoke()
    }

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        resume?.invoke()
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        pause?.invoke()
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
        stop?.invoke()
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        destroy?.invoke()
    }
}

方法

Composable 中监听组合状态,一旦组合被释放,就移除声明周期观察

@Composable
fun rememberLifecycle(): ComposeLifecycleObserver {
    val observer = ComposeLifecycleObserver()
    val owner = LocalLifecycleOwner.current

    DisposableEffect(key1 = "lifecycle", effect = {
        owner.lifecycle.addObserver(observer)
        onDispose {
            owner.lifecycle.removeObserver(observer)
        }
    })

    val ctx = LocalContext.current
    return remember(ctx) { observer }
}

使用

在不同的声明周期里做要做的事情即可

@Composable
fun TestScreen(){
    val life = rememberLifecycle()
    life.onLifeCreate { TODO() }
    life.onLifeStart { TODO() }
    life.onLifeResume { TODO() }
    life.onLifePause { TODO() }
    life.onLifeStop { TODO() }
    life.onLifeDestroy { TODO() }
}

最后

非科班跨行程序员,如有错误欢迎批评。

有关Jetpack Compose过渡 - 监听Acitvity生命周期的更多相关文章

  1. ruby-on-rails - Rails 是否支持监听 UDP 套接字的简洁方式? - 2

    在Rails中,什么是集成更新模型某些元素的UDP监听过程的最佳方式(特别是它将向其中一个表添加行)。简单的答案似乎是在同一个进程中使用UDP套接字对象启动一个线程,但我什至不清楚我应该在哪里做适合Rails方式的事情。有没有一种巧妙的方法来开始收听UDP?具体来说,我希望能够编写一个UDPController并在每个数据报消息上调用一个特定的方法。理想情况下,我希望避免在UDP上使用HTTP(因为它会浪费一些在这种情况下非常宝贵的空间),但我完全控制消息格式,因此我可以为Rails提供它需要的任何信息。 最佳答案 Rails是一个

  2. ruby - 在 Ruby 中查找周期和范围集差异的有效方法 - 2

    我在Ruby中有很多时间范围:period=Time.parse('8:00am')..Time.parse('8:00pm')incidents=[Time.parse('7:00am')..Time.parse('9:00am'),Time.parse('1:00pm')..Time.parse('3:00pm'),Time.parse('1:30pm')..Time.parse('3:30pm'),Time.parse('7:00pm')..Time.parse('9:00pm'),]我正试图在这段时间内获得一系列无事件block。对于以上内容:[Time.parse('9:00

  3. ruby-on-rails - 有没有一种简单的方法可以在 Passenger 的请求周期之外运行垃圾收集? - 2

    unicorn有OobGC可用于在一定数量的请求后运行GC.start的机架中间件。PhusionPassenger中有类似的东西吗? 最佳答案 PhusionPassenger4正式引入了带外垃圾回收机制。它比Unicorn更灵活,允许任意工作,而不仅仅是垃圾收集。http://blog.phusion.nl/2013/01/22/phusion-passenger-4-technology-preview-out-of-band-work/ 关于ruby-on-rails-有没有一种

  4. ruby-on-rails - 有没有办法阻止 Rails 的内置服务器默认监听 0.0.0.0? - 2

    我在不受信任的网络(咖啡店、邻居的开放式wifi、DEFCON)上进行了大量的Web开发,当随机的、肯定有错误的软件(比如我正在开发的Rails应用程序)在0.0上绑定(bind)一个端口时,我会感到紧张.0.0并开始接受所有来者的请求。我知道我可以使用-b选项指定绑定(bind)到服务器的地址,但我想全局更改默认值,以便它始终以这种方式运行,除非我另有说明。当然我也可以运行某种会阻止连接的防火墙,但最好不要一开始就监听。是否有“.railsrc”文件或类似文件——至少是每个项目的设置文件,但最好是一些全局设置文件——我可以使用它来强制服务器默认仅绑定(bind)到127.0.0.1?

  5. ruby-on-rails - rails 周期性任务 - 2

    我有一个ruby​​onrails应用程序,我试图在其中找到每隔几秒运行一些代码的方法。我发现了很多使用cron或类似cron的实现的信息和想法,但这些只是准确到分钟,并且/或需要外部工具。我想每15秒左右启动一次任务,并且我希望它完全独立于应用程序中(如果应用程序停止,任务也停止,并且没有外部设置)。这用于缓存数据的后台生成。每隔几秒,任务就会收集一些数据,然后将其存储在缓存中,供所有客户端请求使用。该任务非常慢,因此需要在后台运行并且不阻塞客户端请求。我是ruby​​的新手,但有很强的perl背景,我解决这个问题的方法是创建一个间隔计时器和处理程序,它fork、运行代码,然后在完成

  6. ruby-on-rails - Rails 应用程序的生命周期 - 2

    我正在尝试了解Rails应用程序的生命周期。application_controller.rb什么时候运行?是每次更改时只执行一次,还是每次请求时都执行一次?我想了解以下文件:config/environments/*.rb(开发、生产或测试,取决于当前模式)boot.rb环境.rb路线.rb我问这个的原因之一是,我想知道放在哪里比较好初始化代码自定义配置数据编辑:@Gdeglin的回答很好,但我实际上很想知道这些文件中的每一个何时运行。 最佳答案 应用程序Controller.rbApplicationController是所有C

  7. ruby - 在 Sinatra(Ruby) 中,我应该如何创建在应用程序生命周期中只赋值一次的全局变量? - 2

    在Sinatra中,我无法创建在应用程序生命周期中仅分配一次值的全局变量。我错过了什么吗?我的简化代码如下所示:require'rubygems'ifRUBY_VERSION这导致nil2在终端和,2在浏览器中。如果我尝试将@a=1放入initialize方法中,我会在WebApp.run!中遇到错误线。我觉得我错过了一些东西,因为如果我不能有全局变量,那么我如何在应用程序实例化期间加载大数据?beforedo似乎每次有来自客户端的请求时都会被调用。 最佳答案 classWebApp请注意,如果您使用Shotgun或其他在每次请求时

  8. ruby-on-rails - AASM:来自任何州的过渡? - 2

    我正在使用AASM.是否可以从任何状态转换?例如:aasm_event:publishdotransitions:to=>:publish,:from=>ANY_STATEend我知道可以将状态数组传递给:from,但这不是我想要的。我试过完全省略:from,但没有用。 最佳答案 aasm现在支持不指定任何from的转换,这将允许从任何状态转换。aasm_event:publishdotransitionsto::publish#fromANYend(吹牛的权利:我添加此功能是因为我需要它)

  9. javascript - 窗口上的事件监听器不会删除 - 2

    这个问题在这里已经有了答案:JavaScript:removeeventlistener(10个答案)关闭7年前。我需要删除在窗口上设置的事件监听器,但它不起作用,监听器一直在滚动时触发。我试过设置有和没有lodashthrottle的听众,但它没有任何区别。这是我的代码:setupListener(){window.addEventListener('resize',_.throttle(this.handler.bind(this),750));window.addEventListener('scroll',_.throttle(this.handler.bind(this),7

  10. javascript - 是否使用 ".click()"异步触发事件监听器? - 2

    我有以下代码(我的HTML中有一个):(function(){'usestrict';document.getElementById(7).addEventListener("click",function(){console.log('clicked');})console.log('before');document.getElementById(7).click();console.log('after')}());当它在Firefox41控制台中运行时,我会预料到之前之后点击因为代码会同步运行,然后在完成脚本后响应事件队列中的点击事件。相反,我得到了之前点击在之后这表明事件正在

随机推荐