拥抱Jetpack之印象篇

目录

前言

一、什么是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,以上这些组件都是我们平时开发中可能会经常使用到的,其余的组件这里就不再多做介绍了,有需要的大家可以自己到网上搜索一下相关的文章,或者自行到谷歌的官网上学习一下。

今天的内容就到这里啦,下期再会!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值