如何观察数据库的变化以更新 LiveData
Posted
技术标签:
【中文标题】如何观察数据库的变化以更新 LiveData【英文标题】:How to observe changes in database in order to update LiveData 【发布时间】:2019-03-18 01:07:13 【问题描述】:我正在将应用程序从带有 Callbacks
的 LoaderManager
迁移到使用 ViewModel
和 LiveData
的实现。我想继续使用现有的SQLiteDatabase
。
主要实现工作正常。 Activity
实例化 ViewModel
并创建一个 Observer
,如果它观察到位于 ViewModel
中的 MutableLiveData
的变化,它会更新 View
。 ViewModel
通过使用ContentProvider
的查询从SQLiteDatabase
获取数据(光标)。
但我还有其他可以更改数据库的活动,而 MainActivity
已停止但未销毁。还有一个后台服务可以在MainActivity
处于前台时更改数据库。
其他活动和后台服务可以更改数据库中的值,因此会对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();
这是我的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);
【问题讨论】:
可能使用developer.android.com/reference/android/database/…(并在内容解析器中通知!***.com/questions/24465999/…) 这也许是个不错的方法。我会进一步研究一下。谢谢! 我实现了一个简单的ContentObserver
,它就像一个魅力。谢谢你的帮助! @zapl
【参考方案1】:
也许你应该看看Room
。 Room 数据库在后台使用 SQLite,并在数据库发生任何更改时自动通知您的 LiveData
对象。因此,您永远不需要担心查询和游标等。
看看这个tutorial!
【讨论】:
谢谢。我一定会调查Room
。不幸的是,这是一个具有相当复杂的内容提供者和数据库的现有应用程序。 Android 弃用了CursorLoaders
(顺便说一句,它工作得非常好),所以我想先迁移到 ViewModels 并保持应用程序正常运行。之后,我可以采取措施实现Room
。
好吧,在这种情况下 ContentObserver 可能会更好:)以上是关于如何观察数据库的变化以更新 LiveData的主要内容,如果未能解决你的问题,请参考以下文章
Android jetpack架构组件LiveData实战与源码解析
Room:来自 Dao 的 LiveData 将在每次更新时触发 Observer.onChanged,即使 LiveData 值没有变化