项目地址 <https://github.com/979451341/SixOfficialArchitectureComponents>

一.项目简介


本项目实现了对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
<https://blog.csdn.net/z979451341/article/details/81185356>

Android架构组件Room的使用 <https://blog.csdn.net/qq_21793463/article/details/78905316>

Android官方架构组件Navigation:大巧不工的Fragment管理框架
<https://blog.csdn.net/mq2553299/article/details/80445952>

Android.Arch.Paging: 分页加载的新选项
<https://juejin.im/entry/5a6fd4b7f265da3e261c3cc4>

Android 架构组件(一)——Lifecycle-Aware Components
<http://shymanzhu.com/2017/12/02/Android%20%E6%9E%B6%E6%9E%84%E7%BB%84%E4%BB%B6%EF%BC%88%E4%B8%80%EF%BC%89%E2%80%94%E2%80%94Lifecycle-Aware%20Components/#more>

Android架构组件(三)——ViewModel
<https://blog.csdn.net/zhuzp_blog/article/details/78910535>

官网
<https://developer.android.google.cn/topic/libraries/architecture/adding-components#lifecycle>

官方github 源码 <https://github.com/googlesamples/android-architecture-components>

 

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信