新款安卓架构设计-Architecture Components介绍
来源:互联网 发布:微信扫码抽奖软件 编辑:程序博客网 时间:2024/05/02 21:32
架构模板篇介绍了mvp,mvi,mvvm(databinding),今天介绍的这款安卓架构框架是Google在今天5月17号推出的:Architecture Components. 它的第一版本解决如下问题:
1)自动管理activity和fragment的生命周期,从而避免资源和内存溢出问题
2)持续化java对象到sqlite数据库
主要包括组成部分:
1)Lifecycle Components
2)LiveData
3)ViewModel
4)Rom (Database, entity, DAO)
它的两个主要设计原则:
1)单一原则,不要把所有代码都写在Activity/Fragment, 隔离独立的模块
2)model(数据)驱动UI
完整的架构图:
1.添加到项目工程
allprojects { repositories { jcenter() maven { url 'https://maven.google.com' } }}
Lifecycles,LiveData, ViewModel,添加依赖:
compile "android.arch.lifecycle:runtime:1.0.0-alpha3"compile "android.arch.lifecycle:extensions:1.0.0-alpha3"annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha3"
Room,添加依赖
compile "android.arch.persistence.room:runtime:1.0.0-alpha3"annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha3"
添加Room的test依赖:
testCompile "android.arch.persistence.room:testing:1.0.0-alpha3"
添加room的rxjava支持依赖:
compile "android.arch.persistence.room:rxjava2:1.0.0-alpha3"
2.处理Lifecycles
Lifecycle持有Activity/Fragment的lifecycle状态,允许其他对象观察这些状态变化。使用下面两种枚举类跟踪关联组件的lifecycle状态:
1)Event
2)State
其对应的活动图:
在代码中,使用@Annotation的方式标识对应的关联组件的生命周期
class MyLocationListener implements LifecycleObserver { private boolean enabled = false; public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) { ... } @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { if (enabled) { // connect } } public void enable() { enabled = true; if (lifecycle.getState().isAtLeast(STARTED)) { // connect if not connected } } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) void stop() { // disconnect if connected }}
3.LiveData
LiveData是一个保存value和观察value变化的对象。不像其他的observable,它可以关联lifecycle.如果Observer的生命周期处于STARTED或RESUMED状态,则LiveData会将Observer视为活动状态。看下对面的代码片段:
public class LocationLiveData extends LiveData<Location> { private LocationManager locationManager; private SimpleLocationListener listener = new SimpleLocationListener() { @Override public void onLocationChanged(Location location) { setValue(location); } }; public LocationLiveData(Context context) { locationManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE); } @Override protected void onActive() { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener); } @Override protected void onInactive() { locationManager.removeUpdates(listener); }}
LiveData有三个方法:
1)onActive() 当LiveData有一个激活的observer时调用;
2)onInactive() 当LiveData没有任何激活的observer时调用;
3)setValue() 调用该方法更新LiveData的value,并通知相关的observer
在Fragment中使用LiveData:
public class MyFragment extends LifecycleFragment { public void onActivityCreated (Bundle savedInstanceState) { LiveData<Location> myLocationListener = ...; Util.checkUserStatus(result -> { if (result) { myLocationListener.addObserver(this, location -> { // update UI }); } }); }}
它具有如下优势:
1)没有内存泄漏:因为它的observers绑定到对应的Lifecycle对象,所以当Lifecycle销毁了,对应的LiveData也会被清除
2)不会导致Crash而停止activities,同样因为Lifecycle影响observer,当observer处于inactive状态,不会去接收event
3)总是更新到最新数据,这个很方便
4)正确处理configuration change(比如屏幕旋转),当屏幕旋转后,他仍然可以获取最新的可用数据
5)共享资源,可以把LiveData弄成单例模式
6)因为它绑定了Lifecycle,所以不需要手动管理Activity/Fragment对应的生命周期了。
4.ViewModel
它的设计就是为了保存和管理UI关联的数据,这样使得configuration change(比如屏幕旋转)发生时,数据可以恢复。
回顾下Activity恢复数据,如果Activity被重新创建或者发生屏幕旋转,保存和恢复周期
onCreate()onSaveInstanceState()onRestoreInstanceState()
但是它有缺点:只允许保存少量的数量,对于需要保存大量的数据:比如界面上所有的用户列表信息,无能为力。
Lifecycle提供了ViewModel,它负责为UI提供数据,ViewModel会自动保留当发生屏幕旋转时。这样就实现了代码分离:ViewModel负责准备数据,而不是放在Activity/Fragment中。
下面打代码示例演示了它是怎么使用的:
public class MyViewModel extends ViewModel { private MutableLiveData<List<User>> users; public LiveData<List<User>> getUsers() { if (users == null) { users = new MutableLiveData<List<Users>>(); loadUsers(); } return users; } private void loadUsers() { // do async operation to fetch users }}public class MyActivity extends AppCompatActivity { public void onCreate(Bundle savedInstanceState) { MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); model.getUsers().observe(this, users -> { // update UI }); }}
它的实现原理:activity被重新创建后,它会使用同样的ViewModel实例(上一个Activity创建的),当对应的activity被销毁了,框架会 调用ViewModel的onCleared方法来销毁资源。
注意:由于ViewModel超出了具体的Activity和Fragment实例生命周期,所以它不应该引用View或任何可能持有对活动上下文的引用的类。 如果ViewModel需要应用程序上下文(例如,找到系统服务),则可以扩展AndroidViewModel类,并在构造函数中接收应用程序的构造函数(因为Application类扩展了Context)
4.1实现fragment之间数据共享
很常见,一个Activity有多个Fragment, 而实现fragment之间的数据共享或者叫数据传递比较麻烦
fragment.setArgs(Bundle)Bundle bundle = fragment.getArgs()
而ViewModel帮我们简化了,看下下面的代码示例
public class SharedViewModel extends ViewModel { private final MutableLiveData<Item> selected = new MutableLiveData<Item>(); public void select(Item item) { selected.setValue(item); } public LiveData<Item> getSelected() { return selected; }}public class MasterFragment extends Fragment { private SharedViewModel model; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); itemSelector.setOnClickListener(item -> { model.select(item); }); }}public class DetailFragment extends LifecycleFragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); model.getSelected().observe(this, { item -> // update UI }); }}
这种机制的优势:
1)对activity来说,它是完全隔离,不知道任何fragment之间的细节
2)fragment之间不需要互相关注,除了ViewModel的细节
3)fragment实现互相独立。
5.Room
Room是一个持续library,Room在SQLite上提供了一个抽象层,以便在利用SQLite的全部功能的同时使流畅的数据库访问。它包括了三个主要组件:
1)Database
2)Entity
3)DAO
Room的架构设计图如下:
从左到右的顺序:database, DAO, entity
下面几个代码判断,展示了怎么编写这几个组件,以及怎么使用
1)Entity
@Entitypublic class User { @PrimaryKey private int uid; @ColumnInfo(name = "first_name") private String firstName; @ColumnInfo(name = "last_name") private String lastName; // Getters and setters are ignored for brevity, // but they're required for Room to work.}
2)DAO
@Daopublic interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Delete void delete(User user);}
3)Database
@Database(entities = {User.class}, version = 1)public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao();}
4)使用
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
5.总结
Lifecycle, LiveData,ViewModel,Room看起来是独立的,确实它们各自负责各自的功能,但是它们一旦串联起来,你会发现很多头疼的问题,比如:代码分离,数据持续化,异步加载结束确保Activity/Fragment没有被销毁后刷新UI,这些问题都透过架构的方式帮我们处理好了,既然它有这么多的优势还是值得一用的。
但是需要注意的是:它怎么样也只是一个架构模板,如果你有比它更好用的架构模板,可以比较之后再做出选择。
官方例子:
https://github.com/googlesamples/android-architecture-components
我的fork:https://github.com/Sherchen/android-architecture-components
来自developer上的blog:
https://android-developers.googleblog.com/2017/05/android-and-architecture.html
来自youtube上的官方video介绍:
https://www.youtube.com/watch?v=vOJCrbr144o
- 新款安卓架构设计-Architecture Components介绍
- Android Application Architecture 安卓APP架构
- Android and Architecture(安卓和架构)
- 谷歌官方推出Android应用开发架构组件介绍(Android Architecture Components)
- Android Architecture Components使用介绍(一)
- 安卓设计架构
- Android Interfaces and Architecture 安卓接口和架构
- Android Architecture Blueprints----安卓架构详细分析
- 查看安卓(Android)设备处理器(CPU)架构(Architecture)信息
- 安卓操作系统架构介绍
- Android官方应用程序架构设置指南--Architecture Components
- 基于Android Architecture Components的应用架构指南
- 基于Android Architecture Components的应用架构指南
- "Android 架构组件"详解( Architecture Components) 未完待续
- 安卓Architecture
- 软件架构(Architecture)及设计
- Oracle Architecture Components
- Android Architecture Components
- 【易初电商】人才孵化基地
- Hadoop集群搭建
- 指定位置输出字符串
- 【转载】Jforum环境安装
- 遍历Map的四种方式与sql优化
- 新款安卓架构设计-Architecture Components介绍
- 对象克隆
- GIC-400寄存器 之CPU接口
- Android7.0中文文档(API)-- ShareActionProvider
- Solr单集代码调用案例
- UVa12100
- Let the Balloon Rise
- [mark]Chrome webdriver 下载
- [机器学习入门] 李弘毅机器学习笔记-17(Unsupervised Learning: Deep Auto-encoder;无监督学习:深度自动编码器)