Jetpack:你如何管理Activity和Fragment的生命周期?

栏目: Android · 发布时间: 5年前

内容简介:为什么需要我们管理Activity和Fragment的生命周期?这些不是Framework自动帮我们搞定的么?(手动黑人问号)刚看到这样的标题我也是很懵逼,不就是onCreate->onSart()->onResume()->onPause()->onStop()->onDestory()么?难道还有什么高深的地方么?在讲Data Bing Library的文章中,大多数同学反馈在实际开发中没什么必要。因为没深爱过,没法名正言顺为其正名。恰好周末逛到如果你对Data Binding Library有独特的见

为什么需要我们管理Activity和Fragment的生命周期?这些不是Framework自动帮我们搞定的么?(手动黑人问号)刚看到这样的标题我也是很懵逼,不就是onCreate->onSart()->onResume()->onPause()->onStop()->onDestory()么?难道还有什么高深的地方么?

题外话

在讲Data Bing Library的文章中,大多数同学反馈在实际开发中没什么必要。因为没深爱过,没法名正言顺为其正名。恰好周末逛到 郭霖公众号 一篇讲Data Bing 在RecyclerView的实践,讲的挺好,大家有空移步前去阅读。引用《卖油翁的故事》道理->熟能生巧,爱得够深,就能擦出火花。

如果你对Data Binding Library有独特的见解或看法,可以前往 Data Binding Library(数据绑定库) 讨论

Abount Lifecycle-Aware Components

该组件能在像Activity、Fragment等等具有生命周期的组件发生状态改变时,以轻量级的和易维护的代码作出响应动作。

吃个栗子就懂意思了:

//为了考虑大多数同学学习过Java,就贴 Java 的代码
//定义个监听类,用来在Activity生命周期发生变化时,对定位服务资源作相关处理
class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // connect to system location service
    }

    void stop() {
        // disconnect from system location service
    }
}
//在Activity中回调监听类相关方法
class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    @Override
    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // update UI
        });
    }
    
    @Override
    public void onStart() {
        super.onStart();
        myLocationListener.start();
        // manage other components that need to respond
        // to the activity lifecycle
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
        // manage other components that need to respond
        // to the activity lifecycle
    }
}
复制代码

毕竟拿人手短,吃人嘴软,吃了人家的栗子就得给人家分析。

这个栗子还是挺简单的,只是简单调用了MyLocationListener对象的两个回调方法,但是在实际开发中,大多数情况下会在Activity的onCreate()、onStart()等等生命周期中做大量的业务逻辑处理和UI更新,而且如果不止一个监听类需要被回调的话,就意味着要在Activity中管理多个其他组件的生命周期或者回调。那代码的维护性和可读性就非常差。(另外,在发生某种竞态条件的情况下,可能会导致Activity的onStop()方法在onStart()方法前就发生了)

为了解决这种痛点,在包 android.arch.lifecycle 中提供类和接口来独立的管理Activity和Fragment组件的生命周期。

Lifecycle

生命周期是一个类包含组件的生命周期状态的信息(例如Activity和Fragment),并允许其他对象观察到这个状态。 Lifecycle 对象以两种主要的枚举类型跟踪它关联组件的生命周期状态:

  • Event Framework和Lifecycle类分发生命周期事件(Lifecycle Event),并映射到Activity或者Fragment的回调事件。
  • State Lifecycle对象跟踪组件的当前状态。
Jetpack:你如何管理Activity和Fragment的生命周期?
方框中的 INITALZIEDDESTROYED 等等表示组件的状态,而箭头上的 ON_CREATEON_START 等等则表示事件。假如Framework或者Lifecycle类分发 ON_CREATE

事件,表示关联的组件的状态从初始化到onCreate状态,对应调用组件的onCreate()方法。

通过在类的方法上添加注解来监听组件的生命周期。然后将该类以观察者形式添加到具有生命周期的类中。

//MyObserver作为一个观察者来监听有生命周期的类
public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}
//myLifecycleOwner是一个实现了LifecycleOwner 接口的类,继续看下文
myLifecycleOwner.getLifecycle().addObserver(new MyObserver());
复制代码

LifecycleOwner

LifecycleOwner,是只有一个 getLifecycle() 方法的接口,实现该接口的类表示具有生命周期。如果想管理整个应用的生命周期,用 ProcessLifecycleOwner 代替 LifecycleOwner 。LifecycleOwner接口将所有具有生命周期的类的生命周期所有权抽象出来,以方便可以在其生命周期进行读写。实现了LifecycleObserver接口的类可以注册到实现了 LifecycleOwner 的类,以观察对应组件的生命周期。例如上文的:

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());
复制代码

这样做带来的好处是什么? 通过这种观察者模式,可以将平常根据Activity或Fragment生命周期状态的逻辑分离到单独类中进行处理,以便更好的逻辑开发、功能迭代和后期维护。

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}
复制代码

讲到这里基本就已经知道如何使用Lifecycle-Aware Components管理Activity或Fragment的生命周期了。如果LifecycleObserver需要监听其他Activity或Fragment的生命周期,只需要重新初始化并注册到新的Activity或Fragment即可。资源的设置和清除回收不需要我们担心。

Custom LifecycleOwner

在Support Library 26.1.0和更高版本,Activity和Fragment已经默认实现了LifecycleOwner。如果要实现定制的LifecycleOwner,需要新建 LifecycleRegistry 对象,并将相关事件传递给它。

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}
复制代码

最好实践

  • 保持UI(Activity或Fragment)精简。不要在Activity或Fragment中取获取应用数据,采用ViewModel或者Livedata。也就是为什么有MVP、MVVM模式。
  • 尝试写数据驱动类型UI。在数据发生变化的时候通过UI控制器更新UI或者通知用户进行操作。
  • 把数据的处理逻辑放到 ViewModel 类中。 ViewModel 作为UI界面与数据的桥梁,处理数据与UI界面交互的逻辑。注意不是获取数据的逻辑,例如获取网络数据或者数据库数据。
  • 使用数据绑定库(Data Binding Library)在UI界面和UI控制器之间进行维护。这样有利于减少在Activity或Fragment中更新UI的代码。在Java中可以使用 Butter Knife 库。
  • 如果UI界面很复杂,可以建立一个主持(Presenter)类去处理视图。MVP模式?
  • 使用Kotlin协同机制管理耗时任务。

使用lifecycle-aware components的场景

lifecycle-aware组件在不同情况能让我们更方便的管理Acitivity和Fragment的生命周期。那在什么情景下适合使用该组件呢?

  • 粗细粒度的切换。例如在定位中,如果当前界面可见,那么定位精度应该更细,定位请求更频繁,以提高响应性。当切换到后台时,请求定位的频率就要放缓,以降低功耗
  • 开始和停止视频缓冲。这个是高手,在应用加载的时候尽早缓冲视频,减少用户等待时间在应用退出是结束缓冲。
  • 开始和停止网络连接。根据App状态自动切换连接的状态。
  • 开始和停止绘制图片。应用在后台时不会绘制,返回前台继续绘制。

存在的一些问题

当Fragment或AppCompatActivity在调用onSaveInstanceState()方法保存状态后,它们的视图在 ON_START 事件被调用之前是不会改变的,在这期间UI被更改会引起不一致的问题,这就是为什么FragmentManager在状态保存后运行FragmentTransaction会抛出异常。

因此如果AppCompatActivity的onStop()方法在调用onSaveInstanceState()方法之后,就会造成一个缺口:UI状态改变是不允许,但生命周期还没有改为 CREATED 的状态。为此,Lifecycle类通过将状态标记为 CREATED ,但直到调用onStop()方法前,不分发该事件,此时去检测当前的状态也可获得真实的值。但是还存在以下两个问题:

  • 在Android 6.0和更低版本,系统调用onSaveInstanceState()方法,但它不一定调用onStop()方法。这样就会造成事件无法分发,潜在的导致观察者以为lifecycle处于活动状态,尽管此时它处于停止状态。
  • 任何想要在LiveData暴露类似行为的类必须实现Lifecycle 版本 beta 2 和更低版本提供的方法。

总结

本文是对官网知识的理解或翻译,建议再进一步阅读原文,毕竟原文才是原汁原味,知识点也多。

Google Android Developer 官网

从第一次看官网懵懵懂懂,到开始了解,又掌握一个知识点。不仅光讲Lifecycle-Aware Components的知识点,还讲到平常开发应用的 最佳实践 ,这些对实际开发都有很强指导作用。

坚持初心,写优质好文章

开文有益, 点赞 支持好文

本文是Jetpack系列文章第二篇

第一篇: Jetpack:你还在findViewById么?


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

火球

火球

张传波 / 2012-2 / 39.80元

《火球:UML大战需求分析》融合UML、非UML、需求分析及需求管理等各方面的知识,帮助读者解决UML业界问题、需求分析及需求管理问题。全书主要介绍UML的基本语法、面向对象的分析方法、应用UML进行需求分析的最佳实践及软件需求管理的最佳实践四个方面的内容。 《火球:UML大战需求分析》各章以问题为引子,通过案例、练习、思考和分析等,由浅入深地逐步介绍UML综合应用的知识。《火球:UML大战......一起来看看 《火球》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具