android - 如何观察数据库的变化以更新 LiveData
问题描述
我正在将应用程序从LoaderManager
with迁移Callbacks
到使用ViewModel
and的实现LiveData
。我想继续使用现有的SQLiteDatabase
.
主要实现工作正常。Activity
实例化ViewModel
并创建一个Observer
更新 的,如果View
它观察到 中的MutableLiveData
变化ViewModel
。通过使用. ViewModel
_SQLiteDatabase
ContentProvider
但是我有其他可以对数据库进行更改的活动,虽然MainActivity
被停止但没有被破坏。还有一个后台服务可以MainActivity
在前台更改数据库。
其他活动和后台服务可以更改数据库中的值,因此会对MutableLiveData
.ViewModel
我的问题是:如何观察变化SQLiteDatabase
以便更新LiveData
?
这是一个简化版本MainActivity
:
public class MainActivity extends AppCompatActivity {
private DrawerAdapter mDrawerAdapter;
HomeActivityViewModel homeActivityViewModel;
private Observer<Cursor> leftDrawerLiveDataObserver = new Observer<Cursor>() {
@Override
public void onChanged(@Nullable Cursor cursor) {
if (cursor != null && cursor.moveToFirst()) { // Do we have a non-empty cursor?
mDrawerAdapter.setCursor(cursor);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
homeActivityViewModel = ViewModelProviders.of(this).get(HomeActivityViewModel.class);
homeActivityViewModel.getLiveData().observe(this, leftDrawerLiveDataObserver);
homeActivityViewModel.updateLiveData(); //,LEFT_DRAWER_LIVEDATA_ID);
}
@Override
protected void onResume(){ // update the LiveData on Resume
super.onResume();
homeActivityViewModel.updateLiveData();
}
}
这是我的ViewModel
:
public class HomeActivityViewModel extends AndroidViewModel {
public HomeActivityViewModel(Application application) {
super(application);
}
@NonNull
private final MutableLiveData<Integer> updateCookie = new MutableLiveData<>();
@NonNull
private final LiveData<Cursor> cursorLeftDrawer =
Transformations.switchMap(updateCookie,
new Function<Integer, LiveData<Cursor>>() {
private QueryHandler mQueryHandler;
@Override
public LiveData<Cursor> apply(Integer input) {
mQueryHandler = new QueryHandler(getApplication().getContentResolver());
MutableLiveData<Cursor> cursorMutableLiveData = new MutableLiveData<>();
mQueryHandler.startQuery(ID, cursorMutableLiveData, URI,
new String[]{FeedData.ID, FeedData.URL},
null,null,null
);
return cursorMutableLiveData;
}
}
);
// By changing the value of the updateCookie, LiveData gets refreshed through the Observer.
void updateLiveData() {
Integer x = updateCookie.getValue();
int y = (x != null) ? Math.abs(x -1) : 1 ;
updateCookie.setValue(y);
}
@NonNull
LiveData<Cursor> getLiveData() {
return cursorLeftDrawer;
}
/**
* Inner class to perform a query on a background thread.
* When the query is completed, the result is handled in onQueryComplete
*/
private static class QueryHandler extends AsyncQueryHandler {
QueryHandler(ContentResolver cr) {
super(cr);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
MutableLiveData<Cursor> cursorMutableLiveData = (MutableLiveData<Cursor>) cookie;
cursorMutableLiveData.setValue(cursor);
}
}
}
解决方案
也许你应该看看Room
。LiveData
Room 数据库在后台使用 SQLite,并在数据库发生任何更改时自动通知您的对象。因此,您永远不需要担心查询和游标等。看看这个教程!
推荐阅读
- windows - 如何从 WSL2 运行 .exe?
- c++ - 使用类成员函数初始化 std::barrier
- c# - DSharp+ RPG 为服务器成员赋值
- r - 使用 mlr3 结合弹性网络和逻辑回归的两级堆叠学习器(集成模型)
- c# - 使用 Blazor 渲染未知深度的树结构
- .net-core - 如何让 BluetoothSocket.Connect() 成功?(读取失败,套接字可能关闭或超时,读取 ret:-1)
- elasticsearch - 用于搜索多个实体的 Elasticsearch 索引策略
- android - Android如何等待几秒钟然后关闭应用程序
- sendgrid - 将 Strapi 系列连接到 sendgrid 联系人
- c# - Unity 3d我的角色没有旋转到我画的raycasthit点