目录
前言
一、什么是Jetpack
二、Jetpack的优势
三、Jetpack组件库介绍
3.1、Navigation
3.2、Lifecycle
3.3、ViewModel
3.4、LiveData
3.5、Room
3.6、DataBinding
3.7、WorkManager
前言
正文开始前还得絮叨两句,可以忽略这一段内容,哈哈。。。问个问题:你已经拥抱Jetpack了吗?今天我们就来学习一下Jetpack组件库,今天不做技术讲解,我们只是简单的了解一下什么是Jetpack,所以今天的内容很轻松,大家可以愉快的度过这几分钟的时间啦!
本文参考资料:慕课网《移动端架构师》课程学习
官网地址:https://developer.android.google.cn/jetpack
一、什么是Jetpack
Jetpack是众多优秀组件的集合,是谷歌推出的一套为开发者逐渐统一开发规范的新的架构。
谷歌官方对Jetpack的介绍如下:
Jetpack 是一个由多个库组成的套件,可帮助开发者遵循最佳做法、减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码,让开发者可将精力集中于真正重要的编码工作。
我们需要重要掌握的是Android Architecture Components,简称AAC,即:安卓架构组件,我们可以通过下面一张图大致了解一下:
二、Jetpack的优势
- Jetpack提供的众多组件具有基于生命周期感知的能力,可以减少NPE崩溃、内存泄漏及模板代码,可以让我们开发出更加健壮且高质量的应用程序。
- Jetpack提供的组件可以单独使用,也可以搭配使用,并且搭配Kotlin语言特性可以进一步加速开发。
三、Jetpack组件库介绍
下面就简单介绍一下我们平时开发中经常用到的几个组件库:
3.1、Navigation
它是为单Activity架构而生的端内路由
- 特点:Activity、Fragment、Dialog提供路由能力的组件、导航时可携带参数、指定转场动画、支持deepline页面直达、fragment回退栈管理等能力;
- 缺点:十分依赖xml文件(构建页面导航结构图),不利于模块化,组件化开发。
添加依赖的方式如下:
implementation "androidx.navigation:navigation-fragment:versionNumber"
implementation "androidx.navigation:navigation-ui:versionNumber"
路由跳转,可以携带参数,指定转场动画:
NavController navController;
navController.navigate(int resId,Bundle args,NavOptions navOptions);
deepLink实现页面直达能力:
navController.handleDeepLink(intent);
管理Fragment回退栈:
navController.popBackStack(int destinationId,boolean inclusive);
3.2、Lifecycle
它是具备宿主生命周期感知能力的组件
特点:持有组件(比如:Activity或者Fragment)生命周期状态的信息,并且允许其他对象观察此状态。
添加依赖的方式如下:
implementation 'androidx.appcompat:appcompat:1.3.0'
// 或者单独引入下面的依赖
implementation "androidx.lifecycle:lifecycle-common:2.5.0"
经典用法:
// Fragment中实现了Lifecycle
public class Fragment implement xxx,LifecycleOwner{
//该对象内部是key-value的map集合,用来存储注册进去的Observer对象
//会在Fragment的每个生命周期方法中遍历存储的Observer观察者,从而实现分发宿主状态
LifecycleRegistry mLifecycleRegistry;
@Override
@NonNull
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
private void initLifecycle() {
mLifecycleRegistry = new LifecycleRegistry(this);
}
}
// 使用方式:任意类实现LifecycleObserver接口,在生命周期方法上添加以下注解即可
class MyLocation implements LifecycleObserver{
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void onCreate(@NonNull LifecycleOwner owner) {}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void onDestroy(@NonNull LifecycleOwner owner){}
}
// 然后在宿主页面订阅
getLifecycle().addObserver(myLocation); //注册观察者,观察宿主生命周期状态
3.3、ViewModel
它是具备生命周期感知能力的数据存储组件
特点:页面配置发生改变时数据不丢失、生命周期感知、数据共享
添加依赖的方式如下:
implementation 'androidx.appcompat:appcompat:1.3.0'
// 或者单独引入以下组件,通常情况下ViewModel会和LiveData搭配使用
implementation "androidx.lifecycle:lifecycle-viewmodel:2.5.0"
implementation "androidx.lifecycle:lifecycle-livedata:2.5.0"
ViewModel的数据存储、生命周期感知:
// 创建ViewModel类,并不会感知宿主所有生命周期变化,会感知宿主onDestroy被销毁时状态的变化
class MyViewModel extends ViewModel {
@Override
protected void onCleared() {
super.onCleared();
// 宿主销毁时,会执行到这里,可以自行清理释放资源
}
MutableLiveData<User> userInfoData = new MutableLiveData<>();
public void getUserInfo(LifecycleOwner owner, Observer<User> observer){
userInfoData.observe(owner,observer);
// ......从数据库中查询用户数据
userInfoData.setValue(user);
}
}
ViewModel数据共享:场景:单Activity多Fragment
// 构建ViewModel实例对象,需要使用ViewModelProvider来获取ViewModel对象
// 如果ViewModelStore中已存在那么就返回公用实例,如果不存在,则使用factory创建并缓存
// 不同fragment当中获取同一个ViewModel实例,从而实现数据共享
class FragmentA extends Fragment{
public void onCreate(Bundle bundle){
MyViewModel viewModel = new ViewModelProvider(getActivity().getViewModelStore(),new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
}
}
3.4、LiveData
它是具备生命周期感知能力的数据订阅、分发组件
- 特点:支持共享资源、支持黏性事件的分发(后注册的观察者可以接收之前的数据)、不再需要手动处理生命周期(自动和宿主生命周期相关联,当宿主被销毁时它会自动反注册Observer)、确保界面符合数据状态
- 缺点:黏性事件不支持取消
MutableLiveData<T> liveData = new MutableLiveData<>();
// 注册一个跟宿主生命周期绑定的观察者,宿主销毁会自动解除注册
observe(LifecycleOwner owner, Observer<? super T> observer)
// 观察不到宿主生命周期,不会自动解除注册
observeForever(Observer<? super T> observer)
// 以下两个方法都是分发数据给所有的观察者
// 只能用在主线程
setValue(T value)
// 子线程,主线程都可以使用
postValue(T value)
3.5、Room
它是轻量级orm数据库,本质上是一个SQLite抽象层
特点:使用更加简单(类似于Retrofit库),通过注解的方式实现相关功能,编译时自动生成实现类impl
添加依赖的方式如下:
implementation "androidx.room:room-runtime:2.4.2"
annotationProcessor "androidx.room:room-compiler:2.4.2"
Room数据库读写操作:
// 创建一个操作数据库的实体层
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
List<User> getAll();
@Update
User updateUser(User...users);
@Insert
void insertAll(User...users);
@Delete
void deleteUser(User user);
}
// 创建数据库
@Database(entities = {User.class},version = 1)
public abstract class MyDatabase extends RoomDatabase {
public static MyDatabase myDb;
static {
myDb = Room.databaseBuilder(getApplicationContext(),
MyDatabase.class,"database-name").build();
}
public abstract UserDao userDao();
}
// 通过数据库单例对象,获取userDao数据操作对象,访问数据库
myDb.userDao().getAll();
3.6、DataBinding
相信很多人对它都已经是很熟悉了,这里就简单的说一下,它只是一种工具,它解决的是View和数据之间的双向绑定,MVVM是一种架构模式,这两者是有本质区别的。
特点:数据与视图双向绑定、数据绑定空安全、减少模板代码、释放Activity/Fragment的压力
开启dataBinding:
android{
...
dataBinding{
enabled = true
}
}
布局中绑定数据:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="user"
type="com.jarchie.foundation.User" />
<import type="com.jarchie.foundation.UserManager" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tvName"
android:layout_width="200dp" //不能使用动态绑定
android:layout_height="wrap_content"
android:text="@{user.name}" //单向绑定数据变更自动通知UI
android:text="@{user.name+@string/addStr}" //字符串拼接需要引用资源
android:text="@{UserManager.getUsername()}" //调用静态方法,类必须先导入
android:textSize="@{@dimen/16sp}" //资源引用
android:onClick="@{()->UserManager.login()}" //lambda表达式形式实现点击事件
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
//双向绑定数据变更自动更新UI,UI变更了也能自动更新user中name的数据,比单向绑定多一个=
android:text="@={user.name}"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
当我们写完了xml布局之后,每一个dataBinding布局都会生成一个由布局文件名称命名的DataBinding类,比如:
ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.tvName.setText("不用写findViewById啦啦啦啦啦");
3.7、WorkManager
它是新一代的后台任务管理组件,service能做的事情它都能做
特点:支持周期性任务调度、链式任务调度、丰富的任务约束条件(比如网络条件必须是wifi的条件下才能执行),即使程序退出,依旧能保证任务的执行
添加依赖的方式如下:
implementation "androidx.work:work-runtime:2.7.1"
执行任务:
// 构建任务
public class DownloadFileWorker extends Worker{
public DownloadFileWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public Result doWork() {
return Result.success();
}
}
// 构建执行任务的Request对象
OneTimeWorkRequest request = new OneTimeWorkRequest
.Builder(DownloadFileWorker.class)
.build();
// 把任务加入到任务队列
WorkContinuation workContinuation = WorkManager.getInstance(this).beginWith(request);
workContinuation.then(workB).then(workC).enqueue();
OK,以上这些组件都是我们平时开发中可能会经常使用到的,其余的组件这里就不再多做介绍了,有需要的大家可以自己到网上搜索一下相关的文章,或者自行到谷歌的官网上学习一下。
今天的内容就到这里啦,下期再会!
|