新款安卓架构设计-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