带你领略Android Jetpack组件的魅力

13,826 阅读13分钟

1、前言

最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面。

Android Architecture组件是Android Jetpack的一部分,它们是一组库,旨在帮助开发者设计健壮、可测试和可维护的应用程序,包含一下组件:

本文是在以上文章完成的基础上,针对每个组件的使用所做的一点思考,个人感觉所有的开发者都应该尽早的熟悉Jetpack组件,相信一定会被它的魅力所吸引,最近也在完成一个使用以上所有组件实现的项目,作为对Jetpack组件的项目实践,后面的文章也会推出,下面按照一个项目的构成来分析一下每个组件对项目开发的帮助

2、Android Jetpack

对于任何一个产品来说,我们开发中都会面对哪些问题?如:产品交互、用户体验、代码结构、数据获取、数据存储、网络优化、任务调度等等,虽然在现在的阶段这些问题已经有了很好的解决和优化,也有很多大神的开源组件方便开发者去使用,Android Jetpack就是Google给出的一个官方的处理方法(当然知识处理其中基本问题),Android Jetpack组件的优势:

  1. 轻松管理应用程序的生命周期
  2. 构建可观察的数据对象,以便在基础数据库更改时通知视图
  3. 存储在应用程序轮换中未销毁的UI相关数据,在界面重建后恢复数据
  4. 轻松的实现SQLite数据库
  5. 系统自动调度后台任务的执行,优化使用性能

Android Jetpack组件推荐的使用项目架构

上面架构组件的功能如下:

  1. Activity和Fragment负责产品与用户的交互
  2. ViewModel作为数据的存储和驱动
  3. Resposity负责调度数据的获取
  4. Room储存本地序列化的数据
  5. Retrofit获取远程数据的数据

按照谷歌推荐的项目架构配合Android Jatpack组件的使用,将会有不一样的开发体验,下面分析每个组件如何帮我们处理这些问题的。

3、Android Jetpack组件介绍

应用程序的开发和产品与用户的交互都是从UI开始的,用户可见的和开发者操作的结果都显示在界面上,所以界面的操作在卡法中占据很重要的地位,也是影响我们开发和使用体验的重要部分,常见的问题如:UI的声明周期处理、数据的显示和刷新、注册监听的释放等, Jetpack架构组件就可以帮我们规范化的解决他们。

  • Lifecycler

Lifecycler是一个生命周期感知组件,执行操作以响应另一个组件(例如活动和片段)的生命周期状态的更改,简单来说它可以监听活动组件声明周期的变化,在每个声明周期执行相应的方法,不同于以往想在生命周期中执行相应的方法需要设置接口,然后在声明周期中回调接口,这样会造成代码的耦合,也会引发声明周期的问题;

Lifecycler的优点

  1. Lifecycler实现了执行的逻辑和活动的分离,代码解耦并且增加了代码的可读性
  2. Lifecycler在活动结束时自定移除监听,避免了生命周期的问题

Lifecycler的实现主要使用两个主要枚举来跟踪其关联组件的生命周期状态

  1. Event:从框架和Lifecycle类派发的生命周期事件。 这些事件映射到活动和片段中的回调事件。
  2. State:由Lifecycle对象跟踪的组件的当前状态。

Lifecycler的原理

Lifecycler为每个活动组件添加了一个没有界面的Fragment,利用Fragment周期会根据活动声明周期变化的特性实现的特性,从而实现生命周期的感知,然后根据注解的Event查找执行相应的方法。

关于Lifecycler的使用和源码请查看一下两篇文章:

  1. Android Jetpack 架构组件之 Lifecycle(使用篇)
  2. Android Jetpack 架构组件之 Lifecycle(源码篇)
  • LiveData

在产品的开发中我们都有必须的操作就是数据的更新,当用户执行某种操作或服务器数据发生改变后,都要重新获取数据再次刷新界面的UI,每改变一次就要重复一次,从代码封装的角度,有没有一种工具可以监听数据状态,在数据变化的时候自动更新UI呢?LiveData就提供了此项更能,从名字中可以看出这个Data时Live的,不是一个死数据,解决了数据展示和刷新的问题

LiveData刷新的使用:

  1. 只需创建LiveData实例后,为可观察的数据添加观察者,在数据改变时会自动回调观察者
//创建观察者对象
val nameObservable = Observer<String> {   // 创建观察者对象
    textView.text = it       // 定义onChange()方法中的操作
}

LiveData的几点注意事项:

  1. 是一个具有声明周期感知特性的可观察的数据保持类,使用LiveData保存数据时,在每次订阅或数据更新时会自动回调设置的观察者从而更新数据,真正的实现了数据驱动的效果
  2. LiveData 认为观察者的生命周期处于STARTED状态或RESUMED状态下,表示观察者处于活动状态,LiveData只通知活跃的观察者去更新数据
  3. LiveData会在活动处于Destroy时释放观察者,所以开发者无需特别处理

LiveData原理:

内部保存了LifecycleOwner和Observer,利用LifecycleOwner感知并处理声明中期的变化,Observer在数据改变时遍历所有观察者并回调方法

LiveData的使用可源码分析请点击:Android Jetpack 架构组件之 LiveData(使用、源码篇)

  • ViewModel

如果你认为上面的方法只是对程序的开发有一点优化的话,那ViewModel的出现确实解决一个简单而又繁琐的问题,大家都知道用户在使用产品的过程中,可能随时会被中断或界面发生重建,如果数据的丢失会造成很差的用户体验,当然现在都知道在onSaveInstanceState()中保存数据,在界面重建时恢复数据,这种虽然可以解决问题,但会造成每个界面都要编写板寸和恢复的代码,而且数据量过大时会影响执行性能,VIewModel的出现就是解决这个问题,它会在活动重建时仍然保存数据,在活动创建完成后从中获取数据

ViewModel的生命周期:

  1. ViewModel对象的范围是在获取ViewModel时传递给ViewModelProvider的Lifecycle生命周期
  2. ViewModel在内存中直到Activity销毁或Fragment被移除
  3. 系统首次调用活动对象的onCreate()方法时,通常会请求ViewModel
  4. 系统可能会在整个活动的整个生命周期中多次调用onCreate(),例如当设备屏幕旋转时
  5. ViewModel从第一次请求ViewModel直到活动完成并销毁时存在

ViewModel的优点:

  1. 数据和界面的分离,使数据驱动界面
  2. 解决了运行中断和界面重建时的数据保存问题
  3. 配合LiveData实时获取最新数据
  4. 实现Activity中Fragment之间的数据交互

ViewModel原理:

将数据保存到ViewModel中,然后为活动中添加一个HolderFragment,HolderFragment中保存了ViewStore的实例,ViewStore中使用Map保存了ViewModel,从而在活动重新创建时获取到原来的ViewModel

注:一般时VIewModel和LiveData组合保存可观察的数据

ViewModel的使用可源码分析请点击:Android Jetpack 架构组件之 ViewModel (源码篇)

  • Paging

RecyclerView是项目中展示数据所必不可少的控件,伴随者列表展示而来的就是下拉加载,目前有很多开源的框架已支持下拉加载,主要分两种:

  1. 当滑动到最后一个Item时,触发加载更多的数据,此时用户会看到加载过程并等待加载完成
  2. 根据显示的position,在未到最后之前就去加载数据并刷新界面,这样用户可以流畅的滑动下去

Paging的实现和上述原理相似,效果与第二种一致,可以更轻松地在应用程序RecycleView中逐步和优雅地加载数据,看下Paging的实现:

上述组成部分的作用:

  1. DataSource:数据的来源,需要设置初始化和加载更多的逻辑以及每次加载变化的Key
  2. PagedList:数据集散中心;根据需要向DataSource索取加载数据,并将得到的数据传递到PagedListAdapter
  3. PagedListAdapter:数据适配器,这里处了起到普通界面加载适配器的作用外,更重要的是根据滑动显示的坐标,起到了确定什么时候要求向PagedList加载数据
  4. DiffUtil.ItemCallback:判断数据是否发生改变以相应界面的更新

Paging的好处

  1. 轻松流畅的实现下拉加载
  2. 使用LiveData<PagedList>实现数据的可观察
  3. 配合Room实现数据库的加载和监听
  4. 支持自定义DataSource

Paging实现的原理:

简单来说就是在PageListAdapter中显示数据,然后根据显示的position确定是否需要加载数据,当触发加载数据时,PagedList调用DataSource中配置的方法加载数据,并将数据传递到Adapter刷新UI

关于Paging组件的使用和源码分析,请点击:Android Jetpack架构组件之 Paging(使用、源码篇)

  • Room

数据库在项目开发中起着至关重要的作用,所有的操作都在修改着数据,而数据的修改驱动UI更新,从而行成了产品的交互;在开发中如果使用Android原生的SQLite数据库,需要编写大量的样板代码,而Room组件可以让你使用几个注解,就可以省略大量的代码,同时支持更强大的数据库访问;

Room提供了三个主要的组件:

  1. @Database:用来注解类,并且注解的类必须是继承自RoomDatabase的抽象类。该类主要作用是创建数据库和创建Dao
  2. @Entity:用来注解实体类,@Database通过entities属性引用被@Entity注解的类,并利用该类的所有字段作为表的列名来创建表。
  3. @Dao:用来注解一个接口或者抽象方法,该类的作用是提供访问数据库的方法。在使用@Database注解的类中必须定一个不带参数的方法,这个方法返回使用@Dao注解的类

Room使用的优点:

  1. 样板代码通过注解自动生成,提高开发效率
  2. 可以返回可观察的数据,在数据库改变时自动更新
  3. 可以配合Paging使用实现下拉加载
  4. 支持Cursor和Observable查询

Room的实现原理:

Room的实现原理其实是很多框架的实现方式,是一种代码注解,在编译时自动生成的方式(Java注解代码生成);如:ButterKnife框架。

关于Room组件的使用和源码分析,请点击:Android Jetpack 架构组件之 Room(使用、源码篇)

  • Navigation

Navigation框架是Jetpack框架中新的组件,也是比较有意思的和创新的框架,它将程序中界面导航像layout文件一样可视化了,在xml中直接可以编辑和修改界面的导航,简化了应用中目标之间导航的实现,如:

在naviagtion.xml文件的design中添加元素并设置导航,下xml中就会自动填充代码:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/navigation"
            app:startDestination="@id/blankFragment">
        <fragment  ....../>
 
        <fragment 
           android:id="@+id/blankFragment" 
           android:name="com.example.administrator.navigation.BlankFragment"
        <action
           android:id="@+id/action_otherFragment_to_blankFragment"// 在导航时调用此ID设置目的
           app:destination="@id/blankFragment" />
        </fragment>
</navigation>

调用添加的action即可跳转界面实现导航

btnFragment.setOnClickListener {
    Navigation.findNavController(btnFragment).navigate(R.id.action_blankFragment_to_secondFragment)
}

Navigation的优点:

  1. 项目界面导航可视化
  2. 简化界面导航的实现过程

关于Navigation的使用,请点击:Android Jetpack 架构组件之Navigation

  • WorkManger

WorkManger是Android Jetpack提供执行后台任务管理的组件,它适用于需要保证系统即使应用程序退出也会运行的任务,可以根据需求设定执行任务的条件,如:插入电源、空闲状态

  1. 如果程序处于执行状态,WorkManager可以在您应用程序进程的新线程中运行您的任务
  2. 如果程序未运行,WorkManager会选择一种合适的方式来安排后台任务 ,可能会使用 JobScheduler,Firebase JobDispatcher或AlarmManager
  3. 所有的操作都有WokManger调度,开发者无需编写其他调度处理

WorkManager的组成:

  1. Worker:指定需要执行的任务,可以继承抽象的Worker类,在实现的方法中编写执行的逻辑
  2. WorkRequest:创建任务请求(执行一项单一任务)
  3. WorkManager:排队和管理工作请求
  4. WorkStatus:包含有关特定任务的信息
  5. Constraints:指定对任务运行时间的限制(任务约束)

WorkManager的基本使用:

  1. 定义Worker的实现类
class TestWorker(context: Context, workerParameters: WorkerParameters) : Worker(context, workerParameters) {

    override fun doWork(): Result {
        Log.e("TestWorker", "执行了 doWork() 操作!")
        return Result.SUCCESS
    }
}
  1. 创建workRequest请求
val workRequest = OneTimeWorkRequest.Builder(TestWorker::class.java).build()
  1. 使用WorkManger执行请求
WorkManager.getInstance().enqueue(workRequest)

关于WorkManger的使用,请点击:Android Jetpack架构组件之WorkManger

好了,Android Jetpack组件介绍完毕了,开篇时还是十一之前,前前后后拖了好久!本篇是开篇也是入门介绍篇,但确实是在分析和使用了所有组件之后做的一点介绍和总结,当你把Jetpack所有组件联合使用时,你就会发现不一样的妙处,组件之间的联系产生了化学反应,使得整个项目的架构和逻辑清晰明了,项目的运行也变得更加稳定,希望这几篇的学习能对所有想使用Jetpack组件的同学有所帮助!