Android六大官方构架组件的基础使用(Lifecycle,LiveData,ViewModel,Room,Paging,Navigation)
一.项目简介
本项目完成了Lifecycle,LiveData,ViewModel,Room,Paging,Navigation这六个官方构架组件的基础使用,主要会为了初步了解这些组件的基础使用,所以对于这些组件的高级用法和深度思考是缺乏的。但是大家可以通过本项目初步了解这些组件的基础作用和用法。
贴一张项目主界面图,大家可以先下载项目自己运行一下
二.对于六大组件的简介
1.Lifecycle(监听activity生命周期)
Lifecycle主要作用是监听activity生命周期,比如方便大家使用MVP的时候Presenter监听activity生命周期。还可以与Rxjava配合,所以有了RxLifecycle框架。
getLifecycle().addObserver(new IPresenter());
class IPresenter implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void onCreate( LifecycleOwner owner){
tv.setText(tv.getText()+"onCreate\n");
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onStart( LifecycleOwner owner){
tv.setText(tv.getText()+"onStart\n");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume( LifecycleOwner owner){
tv.setText(tv.getText()+"onResume\n");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void onDestroy( LifecycleOwner owner){
tv.setText(tv.getText()+"onDestroy\n");
}
}
2.LiveData(监听自身变化的数据类)
LIveData,比如:MutableLiveData<Integer>。这个数据类有着监听自身变化的能力,并且通过监听者模式告诉 其他组件数据更新。这个能够与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);
}
}
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能够与RxJava合作,具体的看官网
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控制框架)
通过使用xml文件来设置Fragment的跳转逻辑和跳转动画
每一个fragment标签里都设置了id和对应Fragment路径、还有layout。并且还定义了action这个标签,设置了destination目的地,和四个跳转动画
<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
app:startDestination="@id/page1Fragment">
<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>
<fragment
android:id="@+id/page2Fragment"
android:name="com.example.lilingzhi.llvr.fragment.MainPage2Fragment"
android:label="fragment_page2"
tools:layout="@layout/fragment_main_page2">
<action
android:id="@+id/action_page1"
app:enterAnim="@anim/slide_right_in"
app:exitAnim="@anim/slide_left_out"
app:popEnterAnim="@anim/slide_left_in"
app:popExitAnim="@anim/slide_right_out"
app:popUpTo="@id/page1Fragment" />
<action
android:id="@+id/action_page3"
app:destination="@id/nav_graph_page3"
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>
<navigation
android:id="@+id/nav_graph_page3"
app:startDestination="@id/page3Fragment">
<fragment
android:id="@+id/page3Fragment"
android:name="com.example.lilingzhi.llvr.fragment.MainPage3Fragment"
android:label="fragment_page3"
tools:layout="@layout/fragment_main_page3" />
</navigation>
</navigation>
java类里触发action
btn.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.action_page2)
}
三.自我评论
因为我自身对这些组件的了解和掌握不够,所以没有写成 真正算的是 符合官方推荐 构架项目。
关于这个博客算是未完待续
参考文章
Android架构组件(二)——LiveData
Android官方架构组件Navigation:大巧不工的Fragment管理框架
Android 架构组件(一)——Lifecycle-Aware Components
上一篇: 20180502_从零开始的android持久库room其一
下一篇: DQL(数据查询语言)学习