Android Jetpack 六大架构组件全面了解

Android框架 专栏收录该内容
16 篇文章 1 订阅

项目地址

一.项目简介

本项目实现了对Lifecycle,LiveData,ViewModel,Room,Paging,Navigation这六个官方构架组件的全面使用,组件的单独使用或者合作使用都有(PS:WorkManager  bug 太多,不建议使用,我这里也不会提到他,因为我反正是有坑,迈不过去)

贴一张项目主界面图,大家可以先下载项目自己运行一下

 

二.对于六大组件的简介

1.Lifecycle(监听activity生命周期)

Lifecycle主要作用是方便监听activity和Fragment生命周期

在监听activity和Fragment时,在代码里没有什么区别,和下面一样

getLifecycle().addObserver(new IPresenter());


    class IPresenter implements LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        void onCreate( LifecycleOwner owner){
            tv.setText(tv.getText()+"onCreate\n");
        }
。。。。。。。
    }

但是他有一个枚举类,有点意思

Lifecycle.State 是一个枚举类,用于描述当前 生命周期拥有者 的状态,与onStop之类的有点不一样,更加宽泛点 ,
通过此函数获取getLifecycle().getCurrentState(),

DESTROYED:onDestroy执行中和之后    
INITIALIZED : onCreate执行前包括执行时   
CREATED:onCreate与onStop之间
STARTED:onStart与onPause之间  
RESUMED:onResume执行中和 到 onPause开始执行前

还有一个特殊的比较方法,getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED),这个比较的当前值的等级是否等于或高于给的值,
也就是说State枚举类里的值越往后面,值越大,如果当前是 RESUMED ,那上面这个判断是 true

所以在我们刷新界面时,可以添加一个判断  if(getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)),保证当前activity 可见时才刷新

 

2.LiveData(监听自身变化的数据类)

LIveData是一个抽象类,实现类有MutableLiveData、MediatorLiveData

MutableLiveData:这个数据类有着监听自身变化的能力,并且通过监听者模式告诉 其他组件数据更新。这个能够与ViewModel、Room配合,这个后面说

 

    MutableLiveData<Integer> num=new MutableLiveData<>();
    MyObserver observer;        

        observer=new MyObserver();
        num.observe(this,observer);

    class MyObserver implements Observer<Integer> {

        @Override
        public void onChanged(@Nullable Integer integer) {
            tv.setText(""+integer);
        }
    }

MediatorLiveData 与 MutableLiveData的不同之处在于,他能统合 MutableLiveData,就像是一个ArrayList添加一个list一样,不仅数据添加进去了,而且如果添加进去的 MutableLiveData 有Observer ,而MediatorLiveData 也有Observer,在这个MutableLiveData 数据发生改变时, MediatorLiveData 的Observer也会触发。

以下代码就是将MutableLiveData添加到 MediatorLiveData,

       mediatorLiveData.addSource(num,mediatorLiveData::setValue);

 

3.ViewModel(跨组件通讯)

我们先看看我们如何获取ViewModel这个类的对象
ViewModelProviders.of(getActivity()).get(MyViewModel.class);

而这个getActivity()也可以换成Fragment的实例

现在我说一下这个为何能够做到跨组件通讯,因为它能跨组件获取同一个实例

比如:在ActivityA里有FragmentA、FragmentB,你在FragmentA通过给getActivity()得到ViewModel的实例,和你在FragmentB也这样做得到的实例是一样的。说白了,在FragmentA你如果改变这个ViewModel的LIveData这样的属性,在FragmentB能够监听的到

        viewModel= ViewModelProviders.of(getActivity()).get(MyViewModel.class);
        btn_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                viewModel.setNum(viewModel.getNum().getValue()+1);
            }
        });
        viewModel= ViewModelProviders.of(getActivity()).get(MyViewModel.class);
        viewModel.getNum().observe(this,new MyObserver());

 

4.Room(数据库框架)

Room有三个部分:实体类、数据库操控类、数据库创建类

实体类,和GreenDao、Realm一样通过注解来创建表,和修改属性

这个是实体类的属性能够是LIveData

@Entity(tableName = "test")
public class TestBean {

    @PrimaryKey
    private long id;

    private String name="";

......
}

数据库操控类,你别看他是接口类,但是他通过Room框架的注解却有着真正的操控数据的能力,

@Dao
public interface TestDao {

    @Query("SELECT * FROM test")
    List<TestBean> getAll();

    @Query("SELECT * FROM test WHERE id = (:id)")
    TestBean getById(int id);

    @Insert
    void insert(TestBean testBean);

    @Delete
    void delete(TestBean testBean);

    @Update
    void update(TestBean testBean);

}

数据库创建类,能够创建数据库,并且能够修改数据库版本

@Database(entities = {TestBean.class},version = 1)
public abstract class TestDataBase extends RoomDatabase{

    public abstract TestDao testDao();


}

Room数据库的数据可以通过 给MutableLiveData,来完成对界面刷新的绑定

        data.observe(this, new Observer<List<TestBean>>() {
            @Override
            public void onChanged(@Nullable List<TestBean> testBeans) {
             
            }
        });     
   data.setValue(testDao.getAll());

5.Paging(分页加载)

Paging实现的分页加载指的是:你如果有100条数据,但是你的屏幕能够显示出来的只有10条,那你把100条item都加载到RecyclerView里,就会浪费内存,那你先给RecyclerView加载20条数据,当你把RecyclerView拉到底部,Paging再给RecyclerView 20条数据,让他再加载出20条item给用户看。

还是三个步骤实现Paging的基础使用

第一个LiveData数据类,这个PageSize就是你每一次给RecyclerView的数据数量

val allCheeses = LivePagedListBuilder(dao.allCheesesByName(), PagedList.Config.Builder()
                    .setPageSize(PAGE_SIZE)
                    .setEnablePlaceholders(ENABLE_PLACEHOLDERS)
                    .build()).build()

第二个实现PagedListAdapter,其中还用了DiffUtil这个帮助RecyclerView优化更新的工具类

class CheeseAdapter : PagedListAdapter<Cheese, CheeseViewHolder>(diffCallback) {
    override fun onBindViewHolder(holder: CheeseViewHolder, position: Int) {
        holder.bindTo(getItem(position))
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CheeseViewHolder =
            CheeseViewHolder(parent)

    companion object {

        private val diffCallback = object : DiffUtil.ItemCallback<Cheese>() {
            override fun areItemsTheSame(oldItem: Cheese, newItem: Cheese): Boolean =
                    oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: Cheese, newItem: Cheese): Boolean =
                    oldItem == newItem
        }
    }
}

第三个将Adapter与数据库连接起来

viewModel.allCheeses.observe(this, Observer(adapter::submitList))

说实话代码太多了,大家还是看看项目代码比较好,这个例子是Kotlin的语言,我是从官方例子里弄出来的

 

6.Navigation(Fragment控制框架)

首先用NavHostFragment占个位,并且设置xml来控制Fragment的显示和跳转

    <fragment
        android:id="@+id/my_nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph_main" />

然后看看这个 nav_graph_main 写了啥,开头 这个app:startDestination 设置了默认显示Fragment

<navigation 
    app:startDestination="@id/page1Fragment">

然后接下来 在fragment标签里 指定了该fragment 的具体实现类和 action(活动)

通过id 来唯一标识, name来指定 实现类

    <fragment
        android:id="@+id/page1Fragment"
        android:name="com.example.lilingzhi.llvr.fragment.MainPage1Fragment"
        android:label="fragment_page1"
        tools:layout="@layout/fragment_main_page1">
        <action
            android:id="@+id/action_page2"
            app:destination="@id/page2Fragment"
            app:enterAnim="@anim/slide_right_in"
            app:exitAnim="@anim/slide_left_out"
            app:popEnterAnim="@anim/slide_left_in"
            app:popExitAnim="@anim/slide_right_out" />
    </fragment>

action标签描述的是Fragment跳转的 目的地和跳转动画(目的地 进入动画、出发地退出、出发地返回时 进入、目的地返回时退出),   而action标签里,id是唯一标识,app:destination指定了跳转目的地

,在Java代码通过以下触发(从出发地到目的地)

Navigation.findNavController(it).navigate(R.id.action_page2)

想要返回时(目的地到出发地)

Navigation.findNavController(it).navigateUp()

在activity点击返回键可以触发 返回动画

    override fun onSupportNavigateUp() =
            findNavController(this, R.id.my_nav_host_fragment).navigateUp()

 

 

 

参考文章

Android架构组件(二)——LiveData

Android架构组件Room的使用

Android官方架构组件Navigation:大巧不工的Fragment管理框架

Android.Arch.Paging: 分页加载的新选项

Android 架构组件(一)——Lifecycle-Aware Components

Android架构组件(三)——ViewModel

官网

官方github 源码

 

  • 8
    点赞
  • 3
    评论
  • 8
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值