当Room db中的数据发生更改时,RxJava Flowable不会调用Subscriber onNext

时间:2018-03-06 16:34:10

标签: android rx-java2 android-room

我正在使用Android Room作为持久层和RxJava 2构建Android应用。

在我的UI中,我订阅了一个Room dao返回的Flowable:

MainActivity.java

mTaskViewModel.getTasksForDay(SessionManager.getInstance(this).getUser().getId(), CalendarManager.getInstance().getDayString(CalendarManager.getInstance().getSelectedDate()))
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(taskModelsSubscriber);

MainActivity中的订阅者

private Subscriber<List<Task>> taskModelsSubscriber = new Subscriber<List<Task>>() {
        @Override
        public void onSubscribe(Subscription s) {
            s.request(Long.MAX_VALUE);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mRefreshLayout.setRefreshing(true);
                }
            });
        }

        @Override
        public void onNext(List<Task> tasks) {
            mTasksList = tasks;
            scheduleNotifications();
            Collections.sort(mTasksList);

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    TaskArrayAdapter taskArrayAdapter = new TaskArrayAdapter(MainActivity.this, mTasksList, SessionManager.getInstance(getApplicationContext()).getUser());
                    tasksListView.setAdapter(taskArrayAdapter);
                    mRefreshLayout.setRefreshing(false);
                }
            });
        }

        @Override
        public void onError(Throwable t) {
            Log.d(TAG, t.getMessage());
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mRefreshLayout.setRefreshing(false);
                    Toast.makeText(context, R.string.calendar_download_failed, Toast.LENGTH_SHORT).show();
                }
            });
        }

        @Override
        public void onComplete() {
            mRefreshLayout.setRefreshing(false);
        }
    };

这似乎有效。但是,现在我想更新来自不同类的基础数据(定期作业)。

某些课程:

TaskDataSource dataSource = Injection.provideTaskDataSource(context);

                        List<String> uuids = new ArrayList<>();
                        for (Task task : tasks){
                            try {
                                task.setUserId(userId);
                                Task found = dataSource.getTask(task.getUuid(), userId, today, task.getType()).blockingGet();

                                if (found != null){
                                    dataSource.updateTask(task);
                                } else {
                                     //Task doesn't exist, insert
                                    dataSource.insertTask(task);
                                }
                                uuids.add(task.getUuid());
                            } catch(NoSuchElementException ex) {
                                Log.d(TAG, ex.getMessage());
                            }
                        }

因为我在Stackoverflow上的某处读到了为了使它工作,所以两个类都需要使用相同的DAO实例,我创建了TaskDataSource类,它是一个Singleton,并获得与我在MainActivity中使用的ViewModel相同的TaskDao实例。 (mTaskViewModel)。

但它仍然无效。但是类可以访问数据,但插入,删除或更新数据不会触发对MainActivity中订阅服务器的onNext的调用。

供参考,以下是缺少的课程:

Injection.java

public class Injection {
    public static UserDataSource provideUserDataSource(Context context) {
        DeliciousDatabase database = DeliciousDatabase.getInstance(context);
        return new LocalUserDataSource(database.userDao());
    }

    public static TaskDataSource provideTaskDataSource(Context context) {
        //DeliciousDatabase database = DeliciousDatabase.getInstance(context);
        return LocalTaskDataSource.getInstance(context);
    }

    public static ViewModelFactory provideViewModelFactory(Context context) {
        UserDataSource userDataSource = provideUserDataSource(context);
        TaskDataSource taskDataSource = provideTaskDataSource(context);

        return new ViewModelFactory(userDataSource, taskDataSource);
    }
}

LocalTask​​DataSource(实现TaskDataSource)

public class LocalTaskDataSource implements TaskDataSource {

    private final TaskDao mTaskDao;

    private static LocalTaskDataSource mInstance;

    private LocalTaskDataSource(TaskDao taskDao) {
        mTaskDao = taskDao;
    }

    public static LocalTaskDataSource getInstance(Context context) {
        if(mInstance == null) mInstance = new LocalTaskDataSource(DeliciousDatabase.getInstance(context).taskDao());
        return mInstance;
    }

    @Override
    public Flowable<List<Task>> getTasksForDay(String userId, String day) {
        return Maybe.zip(
                mTaskDao.getQuestionnairesForDay(userId, day),
                mTaskDao.getPhysicalTestsForDay(userId, day),
                mTaskDao.getSpeechTestsForDay(userId, day),
                mTaskDao.getStressTestsForDay(userId, day),
                mTaskDao.getPlateControlsForDay(userId, day),
                mTaskDao.getWeeklyFeedbacksForDay(userId, day),
                (questionnaires, physicalTests, speechTests, stressTests, plateControls, weeklyFeedbacks) -> {
                    List<Task> combined = new ArrayList<>();
                    combined.addAll(questionnaires);
                    combined.addAll(physicalTests);
                    combined.addAll(speechTests);
                    combined.addAll(stressTests);
                    combined.addAll(plateControls);
                    combined.addAll(weeklyFeedbacks);
                    return combined;
                }
        ).toFlowable();
    }
}

和TaskViewModel:

public class TaskViewModel extends ViewModel {

    private final TaskDataSource mDataSource;

    private List<Task> mTasks;

    public TaskViewModel(TaskDataSource dataSource) {
        mDataSource = dataSource;
    }

    public Flowable<List<Task>> getTasksForDay(String userId, String day) {
        return mDataSource.getTasksForDay(userId, day);
    }

    public Maybe<? extends Task> getTask(int id, Task.Type type) {
        return mDataSource.getTaskById(id, type);
    }

    public void updateTask(Task task) {
        mDataSource.updateTask(task);
    }

    public Maybe<List<TaskStats>> getWeeklyStatistics(long start, long end) {
        return mDataSource.getWeeklyStatistics(start, end);
    }
}

1 个答案:

答案 0 :(得分:2)

似乎继承是罪魁祸首。如您所见,我正在执行的getTasksForDay查询返回Flowable<List<Task>>。但是,它实际上是Task子类的列表。当更改的基础数据类型不完全相同时,似乎不会发出Room查询。因此,如果您致电updateTask((Questionnaire) task),则Flowable<List<Task>>不会发出,但是当您拨打updateTask((Task) task)时,它会发出。