Android从零开始搭建MVVM架构(5)—— LifeCycle详解

2024-06-24 05:18

本文主要是介绍Android从零开始搭建MVVM架构(5)—— LifeCycle详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.Lifecycle简介
为什么要使用lifecycle?
activity 和fragment 是有声明周期的,有时候,我们的很多操作需要写在声明周期的方法中,比如,下载,文件操作等,这样很多情况下回导致,我们在activity中的声明周期方法中写越来越多的代码,activity或者fragment 越来越臃肿,代码维护越来越困难。 使用lifecycle就可以很好的解决这类问题。
lifecycle代码简洁,我们可以通过实现LifecycleObserver 接口,来监听声明周期,然后我们在activity和fragment中去注册监听。

2.几个重要的类和接口

1.Lifecycle
Lifecycle是一个持有组件生命周期状态(如Activity或Fragment)的信息的类,并允许其他对象观察此状态。
2.Event :从框架和Lifecycle类派发的生命周期事件。这些事件映射到活动和片段中的回调事件。
3.State :由Lifecycle对象跟踪的组件的当前状态。
4.LifecycleOwner (重要)Lifecycle持有者
实现该接口的类持有生命周期(Lifecycle对象),该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。
5.LifecycleObserver(重要)Lifecycle观察者
实现该接口的类,通过注解的方式,可以通过被LifecycleOwner类的addObserver(LifecycleObserver o)方法注册,被注册后,LifecycleObserver便可以观察到LifecycleOwner的生命周期事件。

3.LifeCycle中两个重要的接口LifeCycleOwner和LifecycleObserver 的使(1)LifecycleOwner(生命周期持有者接口)
LifecycleOwner就是一个接口,谁继承了它,就持有了lifecycle对象。然后就可以调用getLifecycle()方法获取继承了抽象类Lifecycle的LifecycleRegistry,然后调用 addObserver(@NonNull LifecycleObserver observer) 方法来注册监听。
这样,该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。

(2)LifecycleObserver(生命周期观察者接口)
LifecycleObserver 是一个观察者接口,实现了它,可以通过注解或者继承的方式,来管理声明周期的监听。只要在持有lifecycle的类中注册了它,当声明周期发生变化时,它就能收到,进行我们自定义的操作。

两种实现方式:

1)实现DefultLifecyceObserver接口,然后重写里面生命周期方法;
2)直接实现LifecycleObserver接口,然后通过注解的方式来接收生命周期的变化;

Lifecycle.java文档中是建议使用第一种方式,因为文档中说明了,随着Java8成为主流,注解的方式会被弃用。DefaultLifecycleObserver是需要另外声明的java8 比如下面

GenericLifecycleObserver,FullLifecycleObserver,DefaultLifecycleObserver 这三个接口都是直接或者间接继承的LifecycleObserver

 // 如果使用的是java 8要显示声明如下的
def lifecycle_version = "1.1.1"
implementation "android.arch.lifecycle:common-java8:$lifecycle_version"

3.开始使用Lifecycle
我们写个测试代码,首先,我们要测试一下,到底LifecycleObserver到底能不能监听到声明周期的变化。并且实验下上图中的声明周期状态
先写两个简单的Activity,FirstActivity 和SecondActivity, 单纯的一个跳转。

public class FirstActivity extends AppCompatActivity {private Button firstBtn;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.first_activity_layout);initView();initListener();}private void initView() {firstBtn = findViewById(R.id.first_btn);}private void initListener() {firstBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(FirstActivity.this, SecondActivity.class);startActivity(intent);}});}
}

接下来,我们要做的是要写一个需要拥有声明周期的类,正常我们自定义控件啊,或者做其他逻辑的类,是没有声明周期的,现在有了LifecycleObserver,我们可以让一个普通的类拥有感知声明周期变化的能力。比如,现在自定义一个,MyObserver类。

public class MyObserver implements DefaultLifecycleObserver{private static final String TAG = "MyListener";@Overridepublic void onCreate(@NonNull LifecycleOwner owner) {Log.d(TAG,"onCreate()");Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());}@Overridepublic void onStart(@NonNull LifecycleOwner owner) {Log.d(TAG,"onStart()");Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());}@Overridepublic void onResume(@NonNull LifecycleOwner owner) {Log.d(TAG,"onResume()");Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());}@Overridepublic void onPause(@NonNull LifecycleOwner owner) {Log.d(TAG,"onPause()");Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());}@Overridepublic void onStop(@NonNull LifecycleOwner owner) {Log.d(TAG,"onStop()");Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());}@Overridepublic void onDestroy(@NonNull LifecycleOwner owner) {Log.d(TAG,"onDestroy() ");Log.d(TAG,"当前生命周期状态="+lifecycle.getCurrentState().name());}}

我们采取的是,直接继承DefaultLifecycleObserver接口,来实现它所有的方法。我们在里面做了log,来查看,是否这个类,收到了activity声明周期的变化。
然后,要做的就是注册监听
在Activity 的OnCreate方法中,调用getLifecycle();

public class FirstActivity extends AppCompatActivity {private Button firstBtn;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.first_activity_layout);initView();initListener();//添加了这一行代码getLifecycle().addObserver(new MyObserver());}private void initView() {firstBtn = findViewById(R.id.first_btn);}private void initListener() {firstBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(FirstActivity.this, SecondActivity.class);startActivity(intent);}});}
}

api26以后,Activity中可以直接 getLifecycle().addObserver(new MyObserver()); 这样,就已经注册了声明周期观察者的监听。运行查看log
启动FirstActivity后,MyObserver类已经监听到了Activity的声明周期方法
并且,和图中表示一致,各个声明周期方法对应相应的节点。一定要清楚,后面会用到。比如,onResume()方法执行后,Activity处于RESUME状态,我们可以通过判断这个状态来做一些事情

通过这个简单的小例子,我们看到了我们的类,只要实现了 LifecycleObserver接口,然后,在Activity 或者Fragment中 通过getLifecycle().addObserver()方法,把这个类的对象传入,就可以实现声明周期的感应监听。

当然,我们可以再初始化这个类的时候,把Lifecycle对象传入,那我们自定义的类就可以自己去管理声明周期,而不依赖activity或者fragment。 这样,activity在使用此类的时候就不必关系声明周期的问题,因为,在这个类里面我们已经处理了。比如: 给MyObserver类添加一个构造方法,传入一个Lifecycle对象。

要注意的是:
生命周期状态为RESUMED时表示,当前activity 是在前台,并且可交互也就onResume()执行后

生命周期状态为STARTED时,表示当前activity处于可见但是不可交互,也就是onStart()方法刚执行完或者onPause()方法刚执行完的状态

生命周期状态为CREATED,表示onCreate()方法刚刚执行完或者onStop()方法刚刚执行完,也就是当前activity不在前台,但是也没有处于销毁状态。

生命周期状态为DESTORYED,表示当前Activity还不存在,没有被创建或者已经销毁,我们通常考虑比较多的就是,onDestory()方法执行后,当前Activity已经销毁。

所以,如果我们要保证在Activity或者Fragment的有效生命周期内进行的操作,必须判断,当前lifecycle的状态是否至少是CREATED状态,避免Activity或者fragment销毁了以后,回调或者网络请求才回来,此时做一些操作会导致异常。

添加以下代码,就是我们把lifecycle对象传给观察者,让它自己去判断回调后的代码,保证至少是CREATED状态。

 private Lifecycle lifecycle;public MyObserver(Lifecycle lifecycle) {this.lifecycle = lifecycle;}
//然后再相应的回调方法中使用下面代码判断,保证数据回调回来,当前activity是存在的if (lifecycle.getCurrentState().isAtLeast(CREATED)) {//这里只是示例,不一定是CREATED}

这里用到了Lifecycle类的方法,下面我们看一下Lifecycle的源码

public abstract class Lifecycle {@MainThread  //添加将在LifecycleOwner更改状态时通知的LifecycleObserver。public abstract void addObserver(@NonNull LifecycleObserver observer);@MainThread //从观察者列表中删除给定的观察者。public abstract void removeObserver(@NonNull LifecycleObserver observer);@MainThread //返回生命周期的当前状态。public abstract State getCurrentState();@SuppressWarnings("WeakerAccess")public enum Event {ON_CREATE,//用于onCreate事件的常量LifecycleOwner。ON_START,ON_RESUME,ON_PAUSE,ON_STOP,ON_DESTROY,ON_ANY //一个Event可以用来匹配所有事件的常数。 }@SuppressWarnings("WeakerAccess")public enum State {DESTROYED,INITIALIZED, //LifecycleOwner的初始化状态。 CREATED, STARTED,RESUMED;//比较此状态是否大于或等于给定值state。public boolean isAtLeast(@NonNull State state) {return compareTo(state) >= 0;}}
}/*** Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on* {@link OnLifecycleEvent} annotated methods.* <p>* @see Lifecycle Lifecycle - for samples and usage patterns.*/
@SuppressWarnings("WeakerAccess")
public interface LifecycleObserver {}

最后借用下官网的-生命周期感知组件的最佳实战

1.尽可能保持您的UI控制器(活动和片段)尽可能精简。他们不应该试图获取他们自己的数据;相反,使用ViewModel来做到这一点,并观察一个LiveData对象来反映更改回视图。
2.尝试编写数据驱动的用户界面,其中您的用户界面控制器的职责是在数据更改时更新视图,或将用户操作通知给ViewModel。
3.把你的数据逻辑放在ViewModel类中。ViewModel应作为您的UI控制器和其他应用程序之间的连接器。但要小心,ViewModel不负责提取数据(例如,来自网络)。相反,ViewModel应调用相应的组件来获取数据,然后将结果提供给UI控制器。
4.使用dataBinding在视图和UI控制器之间保持干净的界面。这使您可以使您的视图更具说明性,并最大限度地减少需要在活动和片段中编写的更新代码。

这篇关于Android从零开始搭建MVVM架构(5)—— LifeCycle详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089267

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

MyBatis常用XML语法详解

《MyBatis常用XML语法详解》文章介绍了MyBatis常用XML语法,包括结果映射、查询语句、插入语句、更新语句、删除语句、动态SQL标签以及ehcache.xml文件的使用,感兴趣的朋友跟随小... 目录1、定义结果映射2、查询语句3、插入语句4、更新语句5、删除语句6、动态 SQL 标签7、ehc

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

vite搭建vue3项目的搭建步骤

《vite搭建vue3项目的搭建步骤》本文主要介绍了vite搭建vue3项目的搭建步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1.确保Nodejs环境2.使用vite-cli工具3.进入项目安装依赖1.确保Nodejs环境

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D