我们决定将RxJava的Flowable与Room持久性库一起使用。我们有一些表,其中服务会无限期地添加内容(每隔几秒钟有2-3次更新插入),并且该表的行已在BaseAdapter中订阅,以便实时更改视图。
问题在于,无论何时进行任何更新/插入操作,我们都会再次获得整个列表,从而使基本适配器重新生成视图。可能会有删除操作,也使行长对我们毫无用处。
我想问是否还有其他运算符支持实时数据并在新数据上调用onNext,并提供有关删除操作的完整列表。
答案 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实现,并且在将数据插入数据库时,发布具有添加/删除数据的事件。订阅它,您可以得到想要的东西。