当前位置:   article > 正文

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

myobserver

项目地址

一.项目简介

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

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

 

二.对于六大组件的简介

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

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

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

  1. getLifecycle().addObserver(new IPresenter());
  2. class IPresenter implements LifecycleObserver {
  3. @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
  4. void onCreate( LifecycleOwner owner){
  5. tv.setText(tv.getText()+"onCreate\n");
  6. }
  7. 。。。。。。。
  8. }

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

  1. Lifecycle.State 是一个枚举类,用于描述当前 生命周期拥有者 的状态,与onStop之类的有点不一样,更加宽泛点 ,
  2. 通过此函数获取getLifecycle().getCurrentState(),
  3. DESTROYED:onDestroy执行中和之后
  4. INITIALIZED : onCreate执行前包括执行时
  5. CREATED:onCreate与onStop之间
  6. STARTED:onStart与onPause之间
  7. RESUMED:onResume执行中和 到 onPause开始执行前
  8. 还有一个特殊的比较方法,getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED),这个比较的当前值的等级是否等于或高于给的值,
  9. 也就是说State枚举类里的值越往后面,值越大,如果当前是 RESUMED ,那上面这个判断是 true

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

 

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

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

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

 

  1. MutableLiveData<Integer> num=new MutableLiveData<>();
  2. MyObserver observer;
  3. observer=new MyObserver();
  4. num.observe(this,observer);
  5. class MyObserver implements Observer<Integer> {
  6. @Override
  7. public void onChanged(@Nullable Integer integer) {
  8. tv.setText(""+integer);
  9. }
  10. }

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能够监听的到

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

 

4.Room(数据库框架)

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

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

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

  1. @Entity(tableName = "test")
  2. public class TestBean {
  3. @PrimaryKey
  4. private long id;
  5. private String name="";
  6. ......
  7. }

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

  1. @Dao
  2. public interface TestDao {
  3. @Query("SELECT * FROM test")
  4. List<TestBean> getAll();
  5. @Query("SELECT * FROM test WHERE id = (:id)")
  6. TestBean getById(int id);
  7. @Insert
  8. void insert(TestBean testBean);
  9. @Delete
  10. void delete(TestBean testBean);
  11. @Update
  12. void update(TestBean testBean);
  13. }

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

  1. @Database(entities = {TestBean.class},version = 1)
  2. public abstract class TestDataBase extends RoomDatabase{
  3. public abstract TestDao testDao();
  4. }

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

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

5.Paging(分页加载)

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

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

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

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

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

  1. class CheeseAdapter : PagedListAdapter<Cheese, CheeseViewHolder>(diffCallback) {
  2. override fun onBindViewHolder(holder: CheeseViewHolder, position: Int) {
  3. holder.bindTo(getItem(position))
  4. }
  5. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CheeseViewHolder =
  6. CheeseViewHolder(parent)
  7. companion object {
  8. private val diffCallback = object : DiffUtil.ItemCallback<Cheese>() {
  9. override fun areItemsTheSame(oldItem: Cheese, newItem: Cheese): Boolean =
  10. oldItem.id == newItem.id
  11. override fun areContentsTheSame(oldItem: Cheese, newItem: Cheese): Boolean =
  12. oldItem == newItem
  13. }
  14. }
  15. }

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

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

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

 

6.Navigation(Fragment控制框架)

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

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

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

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

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

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

  1. <fragment
  2. android:id="@+id/page1Fragment"
  3. android:name="com.example.lilingzhi.llvr.fragment.MainPage1Fragment"
  4. android:label="fragment_page1"
  5. tools:layout="@layout/fragment_main_page1">
  6. <action
  7. android:id="@+id/action_page2"
  8. app:destination="@id/page2Fragment"
  9. app:enterAnim="@anim/slide_right_in"
  10. app:exitAnim="@anim/slide_left_out"
  11. app:popEnterAnim="@anim/slide_left_in"
  12. app:popExitAnim="@anim/slide_right_out" />
  13. </fragment>

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

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

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

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

Navigation.findNavController(it).navigateUp()

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

  1. override fun onSupportNavigateUp() =
  2. 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 源码

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/253923
推荐阅读
相关标签
  

闽ICP备14008679号