[译]Android架构组件 – 查看Room和LiveData – 第一部分
2017-06-12 19:32
489 查看
原文链接:https://riggaroo.co.za/android-architecture-components-looking-room-livedata-part-1/
Room - 一个SQLite对象映射器。非常类似于其他库,如ORMlite或greenDAO。它使用SQL,同时仍然允许对查询的编译时保证。
LiveData - 一个Lifecycle可观察的核心组件。
ViewModel - 应用程序的其他部分与Activities/Fragmets通讯点。它们与UI代码无关。
Lifecycle - 架构自检的核心部分,它包含组件(例如一个Activity)的生命状态信息。
LifecycleOwner - 具有Lifecycle(Activity,Fragment,Process,自定义组件)的组件的核心接口。
LifecycleObserver - 指定出发某些生命周期方法是应该发生的情况。创建LifecycleObserver允许组件自包含。
下图说明了使用新架构组件构建的Android应用程序的结构。该图详细说明了我们将在本系列中构建的“日期倒计时”应用程序的最终结果。 它还指出哪些架构组件在应用程序的哪个部分中使用。
MVP和MVVM之间的主要区别在于,MVVM ViewModels公开数据,有兴趣的方面可以收听该数据(或忽略它),而使用MVP,View和Presenter之间存在严格的绑定。使用MVP,它们更难以重复使用Presenters,因为它们与View紧密耦合。使用MVVM,Views可以从ViewModel订阅他们感兴趣的数据。
Room提供了集中不同的查询数据的方式:
可以订阅发射事件流的
使用RxJava2的
将同步调用放在后台线程,例如
在Android Studio中创建一个带默认空Activity的新工程。
在顶级build.gradle中添加Google Maven仓库:
在
创建一个名为
通过创建一个名为
创建一个名为
你注意到抽象方法
值得注意的是,
使用
现在有了添加,查询和删除条目的结构,我们可以使用它们,并讨论上面定义的
创建一个名为
在Fragment中,添加RecyclerView,
在Fragment中,我们可以轻松的得到
通过传递的第一个参数
保存按钮的
现在我们可以访问数据库,并且可以通过UI轻松地插入或查询数据库。
直接在Activity或Fragment中加载数据有一些缺陷。主要问题是Activity或Fragment与数据库紧密耦合。如果要添加测试或在另一个地方重用逻辑,这不是一个好办法。将数据库逻辑与View逻辑分开是一种更好的方法。
Room文档
LiveData文档
本系列第二部分
新的架构组件是什么?
架构组件的基本框架包括:Room - 一个SQLite对象映射器。非常类似于其他库,如ORMlite或greenDAO。它使用SQL,同时仍然允许对查询的编译时保证。
LiveData - 一个Lifecycle可观察的核心组件。
ViewModel - 应用程序的其他部分与Activities/Fragmets通讯点。它们与UI代码无关。
Lifecycle - 架构自检的核心部分,它包含组件(例如一个Activity)的生命状态信息。
LifecycleOwner - 具有Lifecycle(Activity,Fragment,Process,自定义组件)的组件的核心接口。
LifecycleObserver - 指定出发某些生命周期方法是应该发生的情况。创建LifecycleObserver允许组件自包含。
使用新架构组件构建应用
我们将构建一个应用程序,该应用程序是您添加到应用程序的不同事件的倒计时。 我们将使用MVVM模式。下图说明了使用新架构组件构建的Android应用程序的结构。该图详细说明了我们将在本系列中构建的“日期倒计时”应用程序的最终结果。 它还指出哪些架构组件在应用程序的哪个部分中使用。
MVP和MVVM之间的主要区别在于,MVVM ViewModels公开数据,有兴趣的方面可以收听该数据(或忽略它),而使用MVP,View和Presenter之间存在严格的绑定。使用MVP,它们更难以重复使用Presenters,因为它们与View紧密耦合。使用MVVM,Views可以从ViewModel订阅他们感兴趣的数据。
什么是Room?
Room是Android应用一种新的创建数据库方式。Room**删除了大量之前用于存储数据的重复代码**。Roon是一个介于Java类和SQLite的ORM。使用Room,你不再需要用到Cursors和
Loaders。Room不是一个完整的ORM,例如,不能像其他ORM解决方案那样提供对象的复杂嵌套。
Room提供了集中不同的查询数据的方式:
可以订阅发射事件流的
LiveData类来接收更新。课用在主线程,因为它是异步的。
使用RxJava2的
Flowable抽象类。
将同步调用放在后台线程,例如
AsyncTask。
开始使用Room
完整代码在此在Android Studio中创建一个带默认空Activity的新工程。
在顶级build.gradle中添加Google Maven仓库:
allprojects { repositories { maven { url 'https://maven.google.com' } jcenter() } }
在
app/build.gradle中添加Roomd依赖:
compile "android.arch.lifecycle:extensions:1.0.0-alpha1" compile "android.arch.persistence.room:runtime:1.0.0-alpha1" annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1" annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
创建一个名为
Event的实体。表单将存储事件列表。使用
@Entity注解和表名标注这个类。id域标记
@PrimaryKey注解,选项
autoGenerate域设置为true。然后,Room将自动使用对象中定义的所有域创建表。
@Entity(tableName = TABLE_NAME) public class Event { public static final String TABLE_NAME = "events"; public static final String DATE_FIELD = "date"; @PrimaryKey(autoGenerate = true) private int id; private String name; private String description; @ColumnInfo(name = DATE_FIELD) private LocalDateTime date; public Event(int id, String name, String description, LocalDateTime date) { this.id = id; this.name = name; this.description = description; this.date = date; } public int getId() { return id; } public String getName() { return name; } public String getDescription() { return description; } public LocalDateTime getDate() { return date; } @Override public String toString() { return "Event{" + "id=" + id + ", name='" + name + '\'' + ", description='" + description + '\'' + ", date=" + date + '}'; } public long getDaysUntil() { return ChronoUnit.DAYS.between(LocalDateTime.now(), getDate()); } }
通过创建一个名为
EventDao的接口创建数据访问对象(或者DAO)。使用
@Dao注解标记这个类。然后,Room将生成一个类实现,实现接口中定义的方法(非常类似于Retrofit的工作原理)。我们可以在这里使用不同的注释,如@Query,@Delete,@Insert,@Update等注释。@Query注释可以采用SQL结构化查询。这些注解很大的一部分是编译时检查脚本。例如:如果您不正确地键入表的名称,则Room将不允许编译应用程序,直到修改正确。
@Dao public interface EventDao { @Query("SELECT * FROM " + Event.TABLE_NAME + " WHERE " + Event.DATE_FIELD + " > :minDate") LiveData<List<Event>> getEvents(LocalDateTime minDate); @Insert(onConflict = REPLACE) void addEvent(Event event); @Delete void deleteEvent(Event event); @Update(onConflict = REPLACE) void updateEvent(Event event); }
创建一个名为
EventDatabase的抽象类,它将连接创建的不同实体(或表单)。这个类继承
RoomDatabase。
@Database(entities = {Event.class}, version = 1) @TypeConverters(DateTypeConverter.class) public abstract class EventDatabase extends RoomDatabase { public abstract EventDao eventDao(); }
你注意到抽象方法
eventdao()返回刚创建的
EventDao。Room在运行时返回正取的类实例。
值得注意的是,
@TypeConverters(DateTypeConverter.class)注解自动将
LocalDateTime对象日期序列化为其String格式,并将其从存储器读取时将其反序列化为
LocalDateTime对象。 以下是
DateTypeConverter类的示例类定义:
public class DateTypeConverter { @TypeConverter public static LocalDateTime toDate(Long timestamp) { //.. convert } @TypeConverter public static Long toTimestamp(LocalDateTime date) { //.. convert } }
使用
Room.databaseBuilder(...)创建一个单例
EventDatabase对象。也可以使用`Room.inMemoryDatabaseBuilder(…)’创建一个内存数据库。可以用Dagger轻松地做到这一点,或者手动创建单例。使用Dagger,我们的模块如下(有关更多信息,请参阅完整的源代码):
@Module public class CountdownModule { private CountdownApplication countdownApplication; public CountdownModule(CountdownApplication countdownApplication) { this.countdownApplication = countdownApplication; } @Provides Context applicationContext() { return countdownApplication; } @Provides @Singleton EventRepository providesEventRepository(EventDatabase eventDatabase) { return new EventRepositoryImpl(eventDatabase); } @Provides @Singleton EventDatabase providesEventDatabase(Context context) { return Room.databaseBuilder(context.getApplicationContext(), EventDatabase.class, "event_db").build(); } }
现在有了添加,查询和删除条目的结构,我们可以使用它们,并讨论上面定义的
EventDao中使用的
LiveData类。
什么是LiveData?
LiveData允许您在应用程序的多个组件中观察数据的更改,而不会在它们之间创建明确的和严格的依赖路径。LiveData将识别Activity和Fragment的不同生命周期。当LiveData与Room结合使用时,应用将自动收到数据库更新,而这些更新很难使用标准
SQLiteDatabase来实现。
创建一个名为
EventListActivity的Activity和
EventListFragment的Fragment。在Activity中得到Fragment。确保你的Fragment继承
LifecycleFragment
在Fragment中,添加RecyclerView,
[EventAdapter](),
[EventViewHoler](),用于显示事件列表。
在Fragment中,我们可以轻松的得到
EventDatabase引用,以及观察到数据库增加了新的条目。在可观察的回调中,可以接着设置条目到adapter中。可以使用Dagger注入
EventDatabase。
eventDao = eventDatabase.eventDao(); eventDao.getEvents().observe(this, events -> { Log.d(TAG, "Events Changed:" + events); adapter.setItems(events); });
通过传递的第一个参数
this,可观察的
LiveData将自动被管理。这意味着当Fragment不再使用时,Fragment将处理可观测性的部署。
LiveData类是
LivecycleOberver的一个实例。当生命周期处于
Lifecycle.State.DESTROYED状态时,它自动停止发送更新,而生命周期处于
Lifecycle.State.STARTED状态时,它重新发送更新。
使用Room添加新事件
创建一个Fragment包含两个EditText域,一个日期选择器和一个报错
Button。
保存按钮的
onClickListener调用
eventDatabase.eventDao().addEvent()就可以写入事件数据库。
String eventTitle = editTextTitle.getText().toString(); String eventDescription = editTextDescription.getText().toString(); Event event = new Event(0, eventTitle, eventDescription, eventDateTime); eventDatabase.eventDao().addEvent(event); //Run this in a background thread.
现在我们可以访问数据库,并且可以通过UI轻松地插入或查询数据库。
总结
Room是一个在Android平台中封装SQLite实现的易于使用的库。它还提供了一个直观的接口来处理对象而不是Cursor或
ContentProviders。 使用
LiveData的
Room是魔法真正发生的地方。它允许通过数据更改通知视图,这可能难以用标准的SQLiteDatabase来实现。
直接在Activity或Fragment中加载数据有一些缺陷。主要问题是Activity或Fragment与数据库紧密耦合。如果要添加测试或在另一个地方重用逻辑,这不是一个好办法。将数据库逻辑与View逻辑分开是一种更好的方法。
ViewModel架构组件旨在解决这个问题。在下一篇博客文章中,我们将介绍如何使用
ViewModel和
ViewModelProvider来更好地按照开始时详细介绍的图表构建我们的倒计时应用程序。
参考
An Opinionated Guide to Architecting Mobile AppsRoom文档
LiveData文档
本系列第二部分
相关文章推荐
- Android官方架构组件介绍之LiveData
- Android架构组件之LiveData
- Android架构组件四 Android Architecture Components LiveData组件解析
- [置顶] Android架构组件ViewModel和LiveData介绍及使用
- android架构组件之Room
- Android架构组件Room指南
- Android Architecture Components应用架构组件源码详解(基于1.0以上)(第二篇ViewModel和LiveData)
- ObjectBox[七] 支持LiveData(Android体系结构组件)
- Android架构组件Room的使用
- Android架构组件Room的使用详解
- [译]Android架构组件 – 查看ViewModel – 第二部分
- Android 架构组件之Room数据库 处理Schema export Error
- [置顶] Android架构组件Room介绍与使用
- Android架构组件Room的使用
- [译]Android架构组件 - 查看Lifecycles - 第三部分
- Android4.2.2下Stagefright多媒体架构中的A31的OMX插件和Codec组件
- 如何在Eclipse中查看Android源码或者第三方组件包源码
- 如何在Eclipse中查看Android源码或者第三方组件包源码
- Android层次化安全架构及核心组件概览
- Android 学习笔记 —— Android 四大组件 与 MVC 架构模式