走进Jetpack组件库
- 什么是Jetpack
- Jetpack的优势
- 为什么要使用Jetpack
- Jetpack众多优秀组件介绍
- 使用Jetpack架构开发
什么是Jetpack组件
- 概括:Jetpack是众多优秀组件的集合,是Google推出一套引领Android开发的逐一统一开发规范的架构
Jetpack的优势
- 基于生命周期的感知,可以减少NPE崩溃、内存泄漏、模板代码。为我们开发出健壮且高质量的程序提供强力保障
- 组件可以单独使用,也可以搭配使用,搭配Kotlin语言特性可以进一步加速开发
为什么要使用Jetpack
-
遵循最佳做法
- Android Jetpack 组件采用最新的设计方法构建,具有向后兼容性,可以减少崩溃和内存泄露。
-
消除样板代码
- Android Jetpack 可以管理各种繁琐的 Activity(如后台任务、导航和生命周期管理),以便您可以专注于打造出色的应用。
-
减少不一致
- 这些库可在各种 Android 版本和设备中以一致的方式运作,助您降低复杂性。
Jetpack众多组件介绍
使用Jetpack组件需要将项目升级到AndoridX
Jetpack 包含一系列 Android 库,它们都采用最佳做法并在 Android 应用中提供向后兼容性
Navigation : 为单个Activity架构而生的端内路由
- 特性:Activity,Fragment,Dialog提供路由能力的组件、导航时可携带参数、指定转场动画、支持deepLink页面直达、fragment回退栈管理能力
- 不足之处:十分依赖xml文件,不利于模块化,组件化开发
- 添加依赖
def nav_version = "2.3.2"
// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
- 路由调转,可携带参数,指定转场动画
NavController navController = navHostFragment.getNavController();
navController.navigate(int resId, Bundle args, NavOptions navOptions)
- deppLink实现页面直达能力
navController.handleDeepLink("/**/**")
- 管理Fragment回退栈
navController.popBackStack(int destinationId, boolean inclusive)
Lifecycles
构建生命周期感知型组件,这些组件可以根据 Activity 或 Fragment 的当前生命周期状态调整行为。
// 添加依赖
api 'androidx.appcompat:appcompat:1.1.0'
api 'androidx.lifecycler:lifecycle-common:2.1.0'
// 用法
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun connectListener() {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun disconnectListener() {
...
}
}
// 宿主需要实现LifecycleOwner接口
class MyFragment : xxx, LifecycleOwner {
var mLifecycleRegistry = LifecycleRegistry(this)
// 提供宿主Lifecycle对象
override fun getLifecycle():Lifecycle {
return mLifecycleRegistry
}
}
getLifecycle().addObserver(MyObserver())//注册观察者,观察宿主生命周期状态变化
ViewModel 具备生命周期感知的数据存储组件
具有生命周期感知、页面配置更改数据不会丢失、数据共享
// 添加依赖
api 'androidx.appcompat:appcompat:1.1.0'
api 'androidx.lifecycler:lifecycle-viewmodel:2.0.0'
api 'androidx.lifecycle:lifecycle-livedata:2.0.0'
// 使用方式
class MyViewModel : ViewModel() {
private val users: MutableLiveData> by lazy {
MutableLiveData().also {
loadUsers()
}
}
fun getUsers(): LiveData> {
return users
}
private fun loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
// 创建ViewModel
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// 创建ViewModel
val model: MyViewModel by viewModels()
// 获取数据 , 更新UI
model.getUsers().observe(this, Observer>{ users ->
// update UI
})
}
}
LiveData 数据共享
配合ViewModel使用
特性:支持共享资源、支持粘性事件分发、生命周期感知、确保符合页面需要的数据
不足:粘性时间不能自动取消
MutableLiveData liveData = new MutableLiveData();
//注册一个跟宿主生命周期绑定的观察者,宿主销毁了,会自动解除注册
observe(LifecycleOwner owner,Observer super T> observer)
//观察不到宿主生命周期,不会自动解除注册
observeForever(Observer super T> observer)
//以下俩方法都是分发数据给所有的观察者
//只能用在主线程
setValue(T value)
//子线程,主线程都可以使用
postValue(T value)
Room 轻量级orm数据库,本质上是一个SQLite抽象层
特性:使用更加简单(类似于Retrofit),通过注解的方式实现相关功能。编译时自动生成实现类impl
api "android.arch.persistence.room:runtime:1.1.1"
kapt "android.arch.persistence.room:compiler:1.1.1"
//1. 创建一个操作数据库数据的实体层
// 增删改查
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
List getAll();
@update("update table user set desc=:desc and where user_id = :userId")
User updateUser(String desc,String userId);
@Insert
void insertAll(User... users);
@Delete
void delete(User user);
}
//2. 创建数据库
@Database(entities = {User.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase {
public static MyDatabase mAppDb;
static{
mAppDb = Room.databaseBuilder(getApplicationContext(),
AppDatabase.class, "database-name").build();
}
public abstract UserDao userDao();
}
//3. 通过数据库单例对象,获取userDao数据操作对象.访问数据库
mAppDb.userDao().getAll();
DataBinding 是一种工具,数据与View的双向绑定
特性:减少findViewById模版代码、空安全判断、数据与视图双向绑定、释放Fragment/Activity
// 开启DataBinding
build.gradle中
android {
}
LayoutUserInfoItemBinding binding = DataBindingUtils.inflate(....)
Paging 列表分页组件。可以轻松完成分页预加载达到无限滑动分页效果
实现基于liveData页面分页加载功能
不足之处:不支持列表数据增删改,列表添加HeaderView 和FooterView定位不准确
// 添加依赖
api 'android.arch.paging:runtime:1.0.0'
// 使用方式
//1.构建PagedList.Config对象,用以声明以何种方式分页
PagedList.Config config = new PagedList.Config.Builder()
.setPageSize(10)//指定每次分页加载的条目数量
.setInitialLoadSizeHint(12)//指定初始化数据加载的条目数量
.build();
//2.创建数据源工厂类,用来创建数据提供者
DataSource.Factory factory = new DataSource.Factory() {
@NonNull
@Override
public DataSource create() {
return new ItemKeyedDataSource();
}
};
//3.构建一个能够触发加载页面初始化数据的LiveData对象,并且把上面创建的DataSource.Factory和PagedList.Config 传递进去
LiveData> pageData = new LivePagedListBuilder(factory, config)
.build();//最后通过build方法 构建出LiveData对象。请注意它的 泛型是>
//4.最后我们只需要拿到前面构建出来的LiveData对象注册一个Observer观察者,仅仅如此就可以触发页面初始化数据的加载了
mViewModel.getPageData().observe(this, pagedList -> submitList(pagedList));
class MyItemKeyedDataSource extends ItemKeyedDataSource{
public abstract void loadInitial(LoadInitialParams params,LoadInitialCallback callback){
//页面初始化数据加载
callback.onResult(list)
}
public void loadAfter(@NonNull LoadParams params,LoadCallback callback){
//向后分页数据加载...
callback.onResult(list)
}
public void loadBefore(LoadParams params,LoadCallback callback){
//向前分页数据加载...
callback.onResult(list)
}
}
WorkManager : 新一代后台任务管理组件,功能比较强大,service能做的事情它都能做
支持周期性任务调度、链式任务调度、丰富的任务约束条件、即便程序退出,依旧能保证任务的执行
api "android.arch.work:work-runtime:1.0.1"
//#1.构建任务
class UploadFileWorker extends Worker{
public Result doWork() {
//执行文件上传的任务
return Result.success()
}
}
//#2.构建 执行任务的request对象
OneTimeWorkRequest request = new OneTimeWorkRequest
.Builder(UploadFileWorker.class)
.build()
//#3.把任务加入调度队列
WorkContinuation workContinuation = WorkManager.getInstance(context).beginWith(request);
workContinuation.then(workB).then(workC).enqueue()