Android 如何观察数据库中的更改以更新LiveData
我正在将一个应用程序从带有Android 如何观察数据库中的更改以更新LiveData,android,viewmodel,contentobserver,mutablelivedata,Android,Viewmodel,Contentobserver,Mutablelivedata,我正在将一个应用程序从带有回调的LoaderManager迁移到使用ViewModel和LiveData的实现。我想继续使用现有的SQLiteDatabase 主要实现工作正常。活动实例化视图模型并创建一个观察者,如果观察到视图模型中存在的可变活动数据中的变化,该观察者将更新视图。ViewModel通过使用ContentProvider的查询,从SQLiteDatabase获取it数据(光标) 但是我还有其他可以对数据库进行更改的活动,而MainActivity会被停止,但不会被销毁。还有一个后
回调的LoaderManager
迁移到使用ViewModel
和LiveData
的实现。我想继续使用现有的SQLiteDatabase
主要实现工作正常。活动
实例化视图模型
并创建一个观察者
,如果观察到视图模型
中存在的可变活动数据
中的变化,该观察者将更新视图
。ViewModel
通过使用ContentProvider
的查询,从SQLiteDatabase
获取it数据(光标)
但是我还有其他可以对数据库进行更改的活动,而MainActivity
会被停止,但不会被销毁。还有一个后台服务,可以在main活动
处于前台时对数据库进行更改
其他活动和后台服务可能会更改数据库中的值,因此会对ViewModel
中的MutableLiveData
产生影响
我的问题是:如何观察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();
}
}
也许你应该看看房间
。房间数据库在后台使用SQLite,并在数据库中进行任何更改时自动通知LiveData
对象。因此,您无需担心查询和游标等问题。
看看这个 可能使用(并在contentresolver中通知!)这可能是一个很好的方法。我将进一步研究这一点。谢谢我实现了一个简单的ContentObserver
,它就像一个魔咒。谢谢你的帮助@扎普勒:谢谢。我一定会去看看房间
。不幸的是,这是一个具有相当复杂的内容提供者和数据库的现有应用程序。Android不推荐使用游标加载程序
(顺便说一句,它工作得非常好),所以我想先迁移到ViewModels,让应用程序继续运行。之后,我可以采取步骤实现Room
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);
}
}
}