具有Flowable的RxJava Room:仅返回新行

时间:2018-06-29 09:42:04

标签: android rx-java android-room

我们决定将RxJava的Flowable与Room持久性库一起使用。我们有一些表,其中服务会无限期地添加内容(每隔几秒钟有2-3次更新插入),并且该表的行已在BaseAdapter中订阅,以便实时更改视图。

问题在于,无论何时进行任何更新/插入操作,我们都会再次获得整个列表,从而使基本适配器重新生成视图。可能会有删除操作,也使行长对我们毫无用处。

我想问是否还有其他运算符支持实时数据并在新数据上调用onNext,并提供有关删除操作的完整列表。

2 个答案:

答案 0 :(得分:1)

  

已在 BaseAdapter

中订阅

将RecyclerView与细粒度的notify *调用(例如notifyItemInserted)一起使用,而不是ListView

  

问题在于,只要有任何更新/插入操作,我们就会再次获得整个列表

LiveData<List<T>>Flowable<List<T>>都是完全可以预期的行为。

  

使基本适配器重新生成视图。

那是因为您没有使用DiffUtil或没有使用RecyclerView的新增功能ListAdapter(内部自动处理差异)

  

提供有关删除操作的完整列表。

它实际上已经提供了整个列表(当然,没有删除的项目)。


AAC方面的解决方案是使用DataSource.Factory<Integer, T>而不是Flowable<List<T>>/LiveData<List<T>>,以便您可以通过LiveData<PagedList<T>>创建LivePagedListBuilder,并将其设置为{{1 }}。这样,它仅获取给定的页面大小而不是整个列表,并处理差异。

编辑:

PagedListAdapter

@Entity(tableName = Task.TABLE_NAME)
public class Task {
    public static DiffUtil.ItemCallback<Task> DIFF_CALLBACK = new DiffUtil.ItemCallback<Task>() {
        @Override
        public boolean areItemsTheSame(@NonNull Task oldItem, @NonNull Task newItem) {
            return oldItem.id == newItem.id;
        }

        @Override
        public boolean areContentsTheSame(@NonNull Task oldItem, @NonNull Task newItem) {
            return oldItem.equals(newItem);
        }
    };

    public static final String TABLE_NAME = "TASK";
    public static final String COLUMN_ID = "task_id";
    public static final String COLUMN_TEXT = "task_text";
    public static final String COLUMN_DATE = "task_date";

@Dao
public interface TaskDao {
    @Query("SELECT * FROM " + Task.TABLE_NAME + " ORDER BY " + Task.COLUMN_DATE + " ASC ")
    DataSource.Factory<Integer, Task> tasksSortedByDate();

    // ...
}

public class TaskViewModel
        extends ViewModel {
    private final TaskDao taskDao;

    private LiveData<PagedList<Task>> liveResults;

    public TaskViewModel(TaskDao taskDao) {
        this.taskDao = taskDao;
        liveResults = new LivePagedListBuilder<>(taskDao.tasksSortedByDate(),
                                                 new PagedList.Config.Builder() //
                                                         .setPageSize(20) //
                                                         .setPrefetchDistance(20) //
                                                         .setEnablePlaceholders(true) //
                                                         .build())
                .setInitialLoadKey(0)
                .build();
    }

    public LiveData<PagedList<Task>> getTasks() {
        return liveResults;
    }
}

public class TaskFragment
        extends Fragment {
    RecyclerView recyclerView;

    // ...

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        recyclerView = view.findViewById(R.id.recycler_view);
        TaskViewModel viewModel = ViewModelProviders.of(this).get(TaskViewModel.class);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
        final TaskAdapter taskAdapter = new TaskAdapter();
        recyclerView.setAdapter(taskAdapter);
        viewModel.getTasks().observe(this, pagedList -> {
            //noinspection Convert2MethodRef
            taskAdapter.submitList(pagedList);
        });
    }

    @Override
    protected void onDestroyView() {
        super.onDestroyView();
        viewModel.getTasks().removeObservers(this);
    }
}

答案 1 :(得分:0)

不,有房间,没有。如果您将Rx与Room一起使用,则可以使用Diff util 或者您可以使用List Adapter 还有一个称为SortedListAdapter的变体

从开发人员android提供示例实现

@Dao
 interface UserDao {
     @Query("SELECT * FROM user ORDER BY lastName ASC")
     public abstract LiveData<List<User>> usersByLastName();
 }

 class MyViewModel extends ViewModel {
     public final LiveData<List<User>> usersList;
     public MyViewModel(UserDao userDao) {
         usersList = userDao.usersByLastName();
     }
 }

 class MyActivity extends AppCompatActivity {
     @Override
     public void onCreate(Bundle savedState) {
         super.onCreate(savedState);
         MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
         RecyclerView recyclerView = findViewById(R.id.user_list);
         UserAdapter<User> adapter = new UserAdapter();
         viewModel.usersList.observe(this, list -> adapter.submitList(list));
         recyclerView.setAdapter(adapter);
     }
 }

 class UserAdapter extends ListAdapter<User, UserViewHolder> {
     public UserAdapter() {
         super(User.DIFF_CALLBACK);
     }
     @Override
     public void onBindViewHolder(UserViewHolder holder, int position) {
         holder.bindTo(getItem(position));
     }
     public static final DiffUtil.ItemCallback<User> DIFF_CALLBACK =
             new DiffUtil.ItemCallback<User>() {
         @Override
         public boolean areItemsTheSame(
                 @NonNull User oldUser, @NonNull User newUser) {
             // User properties may have changed if reloaded from the DB, but ID is fixed
             return oldUser.getId() == newUser.getId();
         }
         @Override
         public boolean areContentsTheSame(
                 @NonNull User oldUser, @NonNull User newUser) {
             // NOTE: if you use equals, your object must properly override Object#equals()
             // Incorrectly returning false here will result in too many animations.
             return oldUser.equals(newUser);
         }
     }
 }

或者,您可以创建一个RXBus实现,并且在将数据插入数据库时​​,发布具有添加/删除数据的事件。订阅它,您可以得到想要的东西。