Как наблюдать за изменениями в базе данных для обновления LiveData

Я переношу приложение с LoaderManager с Callbacks на реализацию с использованием ViewModel и 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);

        }
    }

}

person Paul Naveda    schedule 12.10.2018    source источник
comment
вероятно, используя developer.android.com/reference/android/database/ (и уведомление в содержимом распознавателя! )   -  person zapl    schedule 12.10.2018
comment
Это может быть хорошим способом двигаться вперед. Я посмотрю на это немного дальше. Спасибо!   -  person Paul Naveda    schedule 12.10.2018
comment
Я реализовал простой ContentObserver, и он работает как шарм. Спасибо за вашу помощь! @запл   -  person Paul Naveda    schedule 13.10.2018


Ответы (1)


Может быть, вам стоит взглянуть Room. База данных Room использует SQLite в фоновом режиме и будет автоматически уведомлять ваши LiveData объекты при любых изменениях в базе данных. Таким образом, вам никогда не придется беспокоиться о запросах, курсорах и так далее. Ознакомьтесь с этим руководством!

person Criticalstone    schedule 12.10.2018
comment
Спасибо. Я обязательно посмотрю Room. К сожалению, это существующее приложение с довольно сложным контент-провайдером и базой данных. Android устарел CursorLoaders (кстати, он отлично работал), поэтому я подумал сначала перейти на ViewModels и сохранить приложение в рабочем состоянии. После этого я могу предпринять шаги для реализации Room. - person Paul Naveda; 13.10.2018
comment
Хорошо, в таком случае ContentObserver может работать лучше :) - person Criticalstone; 15.10.2018