Room的使用我们这里就不写了,需要看的同学请移步Room使用手册,我们下就开始分析
自定义DAO代码如下:
@Dao
public interface ProductDao {
@Query("SELECT * FROM products")
LiveData<List<ProductEntity>> loadAllProducts();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(List<ProductEntity> products);
@Query("select * from products where id = :productId")
LiveData<ProductEntity> loadProduct(int productId);
@Query("select * from products where id = :productId")
ProductEntity loadProductSync(int productId);
}
框架为我们生成的代码如下:
路径:build->generated->source->apt->debug->com->..后面是自己的报名->ProductDao_Impl
public class ProductDao_Impl implements ProductDao {
private final RoomDatabase __db;
private final EntityInsertionAdapter __insertionAdapterOfProductEntity;
public ProductDao_Impl(RoomDatabase __db) {
this.__db = __db;
this.__insertionAdapterOfProductEntity = new EntityInsertionAdapter<ProductEntity>(__db) {
@Override
public String createQuery() {
return "INSERT OR REPLACE INTO `products`(`id`,`name`,`description`,`price`) VALUES (?,?,?,?)";
}
@Override
public void bind(SupportSQLiteStatement stmt, ProductEntity value) {
stmt.bindLong(1, value.getId());
if (value.getName() == null) {
stmt.bindNull(2);
} else {
stmt.bindString(2, value.getName());
}
if (value.getDescription() == null) {
stmt.bindNull(3);
} else {
stmt.bindString(3, value.getDescription());
}
stmt.bindLong(4, value.getPrice());
}
};
}
@Override
public void insertAll(List<ProductEntity> products) {
__db.beginTransaction();
try {
__insertionAdapterOfProductEntity.insert(products);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
@Override
public LiveData<List<ProductEntity>> loadAllProducts() {
final String _sql = "SELECT * FROM products";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
return new ComputableLiveData<List<ProductEntity>>() {
private Observer _observer;
@Override
protected List<ProductEntity> compute() {
if (_observer == null) {
_observer = new Observer("products") {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};
__db.getInvalidationTracker().addWeakObserver(_observer);
}
final Cursor _cursor = __db.query(_statement);
try {
final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
final int _cursorIndexOfName = _cursor.getColumnIndexOrThrow("name");
final int _cursorIndexOfDescription = _cursor.getColumnIndexOrThrow("description");
final int _cursorIndexOfPrice = _cursor.getColumnIndexOrThrow("price");
final List<ProductEntity> _result = new ArrayList<ProductEntity>(_cursor.getCount());
while(_cursor.moveToNext()) {
final ProductEntity _item;
_item = new ProductEntity();
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_item.setId(_tmpId);
final String _tmpName;
_tmpName = _cursor.getString(_cursorIndexOfName);
_item.setName(_tmpName);
final String _tmpDescription;
_tmpDescription = _cursor.getString(_cursorIndexOfDescription);
_item.setDescription(_tmpDescription);
final int _tmpPrice;
_tmpPrice = _cursor.getInt(_cursorIndexOfPrice);
_item.setPrice(_tmpPrice);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
}.getLiveData();
}
@Override
public LiveData<ProductEntity> loadProduct(int productId) {
final String _sql = "select * from products where id = ?";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
int _argIndex = 1;
_statement.bindLong(_argIndex, productId);
return new ComputableLiveData<ProductEntity>() {
private Observer _observer;
@Override
protected ProductEntity compute() {
if (_observer == null) {
_observer = new Observer("products") {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};
__db.getInvalidationTracker().addWeakObserver(_observer);
}
final Cursor _cursor = __db.query(_statement);
try {
final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
final int _cursorIndexOfName = _cursor.getColumnIndexOrThrow("name");
final int _cursorIndexOfDescription = _cursor.getColumnIndexOrThrow("description");
final int _cursorIndexOfPrice = _cursor.getColumnIndexOrThrow("price");
final ProductEntity _result;
if(_cursor.moveToFirst()) {
_result = new ProductEntity();
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_result.setId(_tmpId);
final String _tmpName;
_tmpName = _cursor.getString(_cursorIndexOfName);
_result.setName(_tmpName);
final String _tmpDescription;
_tmpDescription = _cursor.getString(_cursorIndexOfDescription);
_result.setDescription(_tmpDescription);
final int _tmpPrice;
_tmpPrice = _cursor.getInt(_cursorIndexOfPrice);
_result.setPrice(_tmpPrice);
} else {
_result = null;
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
}.getLiveData();
}
@Override
public ProductEntity loadProductSync(int productId) {
final String _sql = "select * from products where id = ?";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
int _argIndex = 1;
_statement.bindLong(_argIndex, productId);
final Cursor _cursor = __db.query(_statement);
try {
final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
final int _cursorIndexOfName = _cursor.getColumnIndexOrThrow("name");
final int _cursorIndexOfDescription = _cursor.getColumnIndexOrThrow("description");
final int _cursorIndexOfPrice = _cursor.getColumnIndexOrThrow("price");
final ProductEntity _result;
if(_cursor.moveToFirst()) {
_result = new ProductEntity();
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_result.setId(_tmpId);
final String _tmpName;
_tmpName = _cursor.getString(_cursorIndexOfName);
_result.setName(_tmpName);
final String _tmpDescription;
_tmpDescription = _cursor.getString(_cursorIndexOfDescription);
_result.setDescription(_tmpDescription);
final int _tmpPrice;
_tmpPrice = _cursor.getInt(_cursorIndexOfPrice);
_result.setPrice(_tmpPrice);
} else {
_result = null;
}
return _result;
} finally {
_cursor.close();
_statement.release();
}
}
}
ProductDao_Impl implements ProductDao 这个ProductDao_Impl继承了我们书写的ProductDao抽象类,其实我们获取的对象也是ProductDao_Impl的的实例。
我们先看loadAllProducts方法,
@Override
public LiveData<List<ProductEntity>> loadAllProducts() {
final String _sql = "SELECT * FROM products";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
return new ComputableLiveData<List<ProductEntity>>() {
private Observer _observer;
@Override
protected List<ProductEntity> compute() {
if (_observer == null) {
_observer = new Observer("products") {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};
__db.getInvalidationTracker().addWeakObserver(_observer);
}
final Cursor _cursor = __db.query(_statement);
try {
final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
final int _cursorIndexOfName = _cursor.getColumnIndexOrThrow("name");
final int _cursorIndexOfDescription = _cursor.getColumnIndexOrThrow("description");
final int _cursorIndexOfPrice = _cursor.getColumnIndexOrThrow("price");
final List<ProductEntity> _result = new ArrayList<ProductEntity>(_cursor.getCount());
while(_cursor.moveToNext()) {
final ProductEntity _item;
_item = new ProductEntity();
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_item.setId(_tmpId);
final String _tmpName;
_tmpName = _cursor.getString(_cursorIndexOfName);
_item.setName(_tmpName);
final String _tmpDescription;
_tmpDescription = _cursor.getString(_cursorIndexOfDescription);
_item.setDescription(_tmpDescription);
final int _tmpPrice;
_tmpPrice = _cursor.getInt(_cursorIndexOfPrice);
_item.setPrice(_tmpPrice);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
}.getLiveData();
}
我们首先看ComputableLiveData类的构造方法
public ComputableLiveData() {
this(ArchTaskExecutor.getIOThreadExecutor());
}
/**
*
* Creates a computable live data that computes values on the specified executor.
*
* @param executor Executor that is used to compute new LiveData values.
*/
@SuppressWarnings("WeakerAccess")
public ComputableLiveData(@NonNull Executor executor) {
mExecutor = executor;
mLiveData = new LiveData<T>() {
@Override
protected void onActive() {
mExecutor.execute(mRefreshRunnable);
}
};
}
上面代码我们知道的信息是:
ComputableLiveData持有的ArchTaskExecutor.getIOThreadExecutor(),非主现场的线程池,
mLiveData = new LiveData<T>() {
@Override
protected void onActive() {
mExecutor.execute(mRefreshRunnable);
}
};
这部分代码可以知道ComputableLiveData自己new了一个LiveData实例,并且实现了重写了onActive方法
重点来了 mExecutor.execute(mRefreshRunnable);这是在一步线程中的操作,重点是mRefreshRunnable做了哪些事情呢?
@VisibleForTesting
final Runnable mRefreshRunnable = new Runnable() {
@WorkerThread
@Override
public void run() {
boolean computed;
do {
computed = false;
// compute can happen only in 1 thread but no reason to lock others.
if (mComputing.compareAndSet(false, true)) {
// as long as it is invalid, keep computing.
try {
T value = null;
while (mInvalid.compareAndSet(true, false)) {
computed = true;
value = compute();
}
if (computed) {
mLiveData.postValue(value);
}
} finally {
// release compute lock
mComputing.set(false);
}
}
// check invalid after releasing compute lock to avoid the following scenario.
// Thread A runs compute()
// Thread A checks invalid, it is false
// Main thread sets invalid to true
// Thread B runs, fails to acquire compute lock and skips
// Thread A releases compute lock
// We've left invalid in set state. The check below recovers.
} while (computed && mInvalid.get());
}
};
我们把重点代码摘出来分析一下
T value = null;
while (mInvalid.compareAndSet(true, false)) {
computed = true;
value = compute();
}
if (computed) {
mLiveData.postValue(value);
}
compute()这个方法不就是我们最开始创建ComputableLiveData对象重写的方法吗?我们回头看一下
@Override
protected List<ProductEntity> compute() {
if (_observer == null) {
_observer = new Observer("products") {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};
__db.getInvalidationTracker().addWeakObserver(_observer);
}
final Cursor _cursor = __db.query(_statement);
try {
final int _cursorIndexOfId = _cursor.getColumnIndexOrThrow("id");
final int _cursorIndexOfName = _cursor.getColumnIndexOrThrow("name");
final int _cursorIndexOfDescription = _cursor.getColumnIndexOrThrow("description");
final int _cursorIndexOfPrice = _cursor.getColumnIndexOrThrow("price");
final List<ProductEntity> _result = new ArrayList<ProductEntity>(_cursor.getCount());
while(_cursor.moveToNext()) {
final ProductEntity _item;
_item = new ProductEntity();
final int _tmpId;
_tmpId = _cursor.getInt(_cursorIndexOfId);
_item.setId(_tmpId);
final String _tmpName;
_tmpName = _cursor.getString(_cursorIndexOfName);
_item.setName(_tmpName);
final String _tmpDescription;
_tmpDescription = _cursor.getString(_cursorIndexOfDescription);
_item.setDescription(_tmpDescription);
final int _tmpPrice;
_tmpPrice = _cursor.getInt(_cursorIndexOfPrice);
_item.setPrice(_tmpPrice);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
上面的代码很明显的看出是我们的Room查询数据的并得到结果的方法,巧妙的将LiveData和Room联系到了一起,那么数据是怎么传递出去的呢?我们会使用LiveData的observe方法来观察数据。但是原理是啥呢?我们继续看
if (computed) {
mLiveData.postValue(value);
}
重点是mLiveData.postValue(value)这个方法,是将我们的数据传递到observe设置的观察着中的,大家肯定非常疑惑,我们继续分析代码。
protected void postValue(T value) {
.....
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
在主现场中执行mPostValueRunnable,mPostValueRunnable的代码
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
.....
//noinspection unchecked
setValue((T) newValue);
}
};
setValue方法源码:
@MainThread
protected void setValue(T value) {
....
dispatchingValue(null);
}
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
.....
considerNotify(initiator);
....
}
private void considerNotify(ObserverWrapper observer) {
......
observer.mObserver.onChanged((T) mData);
}
终于调到了我们观察者的onChanged方法了。
通过上面的代码我们可以知道:当我们使用LiveData的postValue或着setValue方法的时候会就调用使用observer方法注册的观察着的onChanged方法了
上面的分析是我们如何通知到观察者的,那么我们什么时候出发的mLiveData的onActive方法呢?也就是什么时候执行的事件出触发事件的执行呢?需要在研究,下篇文章继续