GoogleComponentsDemo
Google Architecture Components 演示程序
在MVVM框架基础上简单使用了Room、LiveData、ViewModel框架组件。
关于我
演示效果(请star支持)
何为 Google Architecture Components
Google Architecture Components是Google在I/O大会上发布的一套应用框架库,它的使用基础是DataBinding和MVVM框架。详细介绍可参见:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/1107/8715.html
架构库的架构图
架构库的基本组成
Lifecycle:Android声明周期的回调,帮助我们将原先需要在onStart()等生命周期回调的代码可以分离到Activity或者Fragment之外。
LiveData:一个数据持有类,持有数据并且这个数据可以被观察被监听,和其他Observer不同的是,它和Lifecycle是绑定的。
ViewModel:用于实现架构中的ViewModel,同时是与Lifecycle绑定的,使用者无需担心生命周期。方便在多个Fragment之前分享数据,比如旋转屏幕后Activity会重新create,这时候使用ViewModel可以方便使用之前的数据,不需要再次请求网络数
Room:谷歌推出的一个Sqlite ORM库,使用注解,极大简化数据库的操作。
框架的补充
框架补充:
- 如果不满足官方的库其实可以自己实现。比如LiveData在某些情况下可使用RxJava代替。
- 数据层官方推荐使用Room或者Realm或者其他Sqlite ORM等都可以。
- 网络请求推荐使用Retrofit。
- 各层之间的耦合推荐使用服务发现(Service Locator)或者依赖注入(DI),推荐Dagger。
如何使用Google Architecture Components
1.在Android Studio上使用,需要在module级别的build.gradle上添加对DataBinding的支持:
android {
....
dataBinding {
enabled = true
}
}
2.配置Room schemaLocation
android {
....
defaultConfig {
....
//指定room.schemaLocation生成的文件路径
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()
]
}
}
}
}
3.配置依赖dependencies
dependencies {
....
// Architecture Components
implementation "android.arch.persistence.room:runtime:1.0.0-alpha1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
implementation "android.arch.lifecycle:runtime:1.0.0-alpha1"
implementation "android.arch.lifecycle:extensions:1.0.0-alpha1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"
}
4.配置使用Room
1.使用@Entity注解配置数据库的实体类
下面是用户信息数据库的实体配置:
@Entity(tableName = "_UserInfo")
public class UserInfoEntity {
@PrimaryKey(autoGenerate = true)
private int Id;
/**
* 登录名
*/
@ColumnInfo(name = "name")
private String LoginName;
/**
* 登录密码
*/
@ColumnInfo(name = "password")
private String LoginPassword;
/**
* 别名
*/
private String Alias;
/**
* 年龄
*/
private int Age;
/**
* 性别
*/
private String Gender;
/**
* 出生日期
*/
private Date BirthDay;
/**
* 签名
*/
private String Signature = "这个家伙很懒,什么也没留下~~";
....
}
创建后生成的数据库表如下:
2.构建数据库操作Dao
数据库操作Dao是一个加了@Dao注解修饰的接口,里面定义了数据库操作的方法,所有的数据库操作都是通过Sql语句实现的,查询出来的结果能够自动转化为实体对象或者LiveData对象。代码如下:
@Dao
public interface UserInfoDao {
@Query("SELECT * FROM _UserInfo")
LiveData<List<UserInfoEntity>> loadAllUserInfos();
@Query("SELECT * FROM _UserInfo where name = :loginName and password = :loginPassword")
LiveData<UserInfoEntity> queryUserInfo(String loginName, String loginPassword);
/**
* 同步操作
*
* @param loginName
* @param loginPassword
* @return
*/
@Query("SELECT * FROM _UserInfo where name = :loginName and password = :loginPassword")
List<UserInfoEntity> queryUserInfoSync(String loginName, String loginPassword);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<UserInfoEntity> userInfos);
}
需要注意的是,Room最好的特性之一是如果你在主线程中执行数据库操作,app将崩溃,显示下面的信息:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
3.构建数据库
继承RoomDatabase,并通过@Database注解进行数据库的信息配置,代码如下:
@Database(entities = {UserInfoEntity.class}, version = 1)
@TypeConverters(DateConverter.class)
public abstract class AppDatabase extends RoomDatabase {
//注册数据库操作Dao
public abstract UserInfoDao userInfoDao();
}
细心的你可能会发现,上面的数据库实体的字段里居然出现了”Date”对象!是的,Room数据库组件支持复杂类型的存储。只需要给数据库提供一个类型转化类,通过注解@TypeConverters配置即可,@TypeConverter是注解的转化方法。下面是Date转化为时间戳的方法:
public class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
@TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
Room数据库的其他操作详解,可参见:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0726/8249.html
5.将获取到的LiveData数据源填充到ViewModel中,并进行数据变化的绑定。
LiveData 是一款基于观察者模式的可感知生命周期的核心组件。LiveData 为界面代码 (Observer)的监视对象 (Observable),当 LiveData 所持有的数据改变时,它会通知相应的界面代码进行更新。代码如下:
public UserInfoListViewModel(Application application) {
super(application);
mObservableUserInfos = new MediatorLiveData<>();
// set by default null, until we get data from the database.
mObservableUserInfos.setValue(null);
LiveData<List<UserInfoEntity>> userInfos = ((DemoApp) application).getRepository().getUserInfos();
// observe the changes of the userInfos from the database and forward them
mObservableUserInfos.addSource(userInfos, mObservableUserInfos::setValue);
}
6.如同MVVM框架中,将ViewModel绑定到View中
XML中注册ViewModel
<data>
<variable
name="UserInfoList"
type="com.xuexiang.googlecomponentsdemo.viewmodel.UserInfoListViewModel" />
</data>
Activity/Fragment中设置绑定ViewModel
final UserInfoListViewModel viewModel = ViewModelProviders.of(this).get(UserInfoListViewModel.class);
binding.setUserInfoList(viewModel);
7.将LiveData数据源与View的生命周期进行绑定
这样LiveData数据源便能感知View的生命周期,并进行相应的处理。同时数据发生变化时,也能对View进行通知处理。
viewModel.getUserInfos().observe(this, new Observer<List<UserInfoEntity>>() {
@Override
public void onChanged(@Nullable List<UserInfoEntity> userInfoEntityList) {
if (userInfoEntityList != null) {
binding.setIsLoading(false);
mUserInfoAdapter.setUserInfoList(userInfoEntityList);
} else {
binding.setIsLoading(true);
}
// espresso does not know how to wait for data binding's loop so we execute changes
// sync.
binding.executePendingBindings();
}
});
以上便简单地使用了Google Architecture Components,总体来说功能比较实用,而且如果结合RxJava、Retrofit、Dagger2和ARouter后,将会更加强大。