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);

        }
    }

}