android - 分页 3 : How to load list at item position or at item with specific id

标签 android android-room android-paging android-paging-3

我有一个消息列表。
每条消息都有一个唯一的 GUID。
我的设置适用于正常使用:用户单击对话,列表打开,其中包含属于该对话的所有消息,按最近的顺序排列。
对话 fragment


    @Override
    public void onViewCreated(
        @NonNull View view,
        @Nullable Bundle savedInstanceState
    ) {
        LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
        viewModel = new ViewModelProvider(this).get(ConversationViewModel.class);
        viewModel
            .getMessageList(lifecycleOwner, conversationId) // conversationId is a global variable
            .observe(lifecycleOwner, messagePagingData -> adapter.submitData(
                lifecycleOwner.getLifecycle(),
                messagePagingData 
            ));

        super.onViewCreated(view, savedInstanceState);

    }
session View 模型

    final PagingConfig pagingConfig = new PagingConfig(10, 10, false, 20);
    private final ConversationRepository conversationRepository;

    public ConversationViewModel(@NonNull Application application) {
        super(application);
        conversationRepository = new ConversationRepository(application);
    }

    public LiveData<PagingData<ItemMessage>> getMessageList(
        @NonNull LifecycleOwner lifecycleOwner,
        @NonNull String conversationId
    ) {
        return PagingLiveData.cachedIn(
            PagingLiveData.getLiveData(new Pager<>(pagingConfig, () -> conversationRepository.getMessageList(conversationId))),
            lifecycleOwner.getLifecycle()
        );
    }
session 存储库
    private final MessageDao messageDao;

    public ConversationRepository(@NonNull Context context) {
        AppDatabase database = AppDatabase.getDatabase(context);
        messageDao = database.messageDao();
    }

    public PagingSource<Integer, ItemMessage> getMessageList(@NonNull String conversationId) {
        return messageDao.getMessageList(conversationId);
    }
消息道
    @Query(
        "SELECT * FROM Message " +
        "WHERE Message.conversationId = :conversationId " +
        "ORDER BY Message.time DESC"
    )
    public abstract PagingSource<Integer, ItemMessage> getMessageList(String conversationId);

现在我的目标是能够打开已经在特定消息处滚动的对话。
我也不想加载整个对话然后滚动到消息,有些对话可能很长,我不想让用户自动滚动可能需要很长时间才能到达特定消息。
理想情况下,我认为正确的方式是传递消息 id 以显示在 View 中,加载围绕该消息 id 前后的一大块 X 消息,然后在它已经在 RecyclerView 中呈现给用户之后如果用户上升或下降,它将加载更多。
这并不意味着使用网络请求,整个 session 已经在数据库中可用,因此它只会使用数据库中已经存在的信息。
我尝试理解使用 ItemKeyedDataSource 的示例或 PageKeyedDataSource ,但我不能去任何地方,因为每次这些示例都只在 Kotlin 中,并且需要 Retrofit 才能工作,我不使用它。因为这些示例对于像我这样使用 Java 且不使用 Retrofit 的人来说完全没用。
如何做到这一点?
请用 Java 提供答案,而不仅仅是 Kotlin(只要它也在 Java 中,kotlin 就可以)并且请不要建议新的库。

最佳答案

据我所知,官方文档没有提供任何关于如何解决 Paging + Room 集成的线索。事实上,它没有提供任何解决方案来滚动到 PagingDataAdapter 中的项目。 , 时期。
到目前为止,唯一对我有用的是每次我希望完成此操作时运行两个查询:一个在结果查询列表中查找项目位置,另一个使用 initialKey 实际加载所述列表。设置在 Pager具有我们之前查询的项目位置的值的构造函数。
如果你感到有点困惑,这里并没有结束,因为即使是对 initialKey 的解释也是如此。以及如何使用它只是没有记录。不,说真的:What does the initialKey parameter do in the Pager constructor
所以这里有两个猜谜游戏:一个是找到从结果列表中查找项目索引的正确方法,另一个是在最终查询中正确设置它。
我希望 Paging 3 文档很快得到改进,以涵盖这些非常基本的问题。
最后,这是我如何设法让这个问题为我工作的一个例子,即使我不知道这是否是正确的方法,因为同样,这个部门绝对缺乏他们的文档。

  • 为您想要的列表结果创建两个相同的查询
  • 其中一个查询仅根据您将用于唯一标识项目的键返回结果的完整列表。就我而言,它是 messageId .
  • 在 2 中加载查询并使用 for... 单独迭代结果列表循环,直到找到您想知道其在列表中的位置的项目。该位置由您在循环 block 中使用的迭代器给出。
  • 将项目位置从 3 传递为 initialKey参数到您的Pager最终查询的生成器
  • 您现在将收到的第一个数据 block 将包含您想要的项目
  • 如果您愿意,您现在可以在 RecyclerView 中滚动到该项目。 ,但您必须从适配器中加载的当前项目列表中查询它。了解如何使用 .snapshot()PagingAdapter

  • 就是这样,现在我终于可以使用 Paging 3 + Room 将项目加载到某个位置,由于完全没有文档,我完全不知道这是否是正确的方法。

    关于android - 分页 3 : How to load list at item position or at item with specific id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64811702/

    相关文章:

    android - 如何在android中更改超链接的颜色

    android - 如果存在则更新记录,否则在 Room 中插入新记录

    Android分页库java.lang.IllegalArgumentException : MainThreadExecutor required

    java - 我如何通过我的存储库获取我的 ID?

    android - Room LiveData vs AsyncTask 用于不需要更新的单个查询

    android-paging - Jetpack Paging3 RemoteMediator 在 #load 附加上返回相同的 PagingSatate

    java - 如何在 In FirestorePagingAdapter 中获取文档 ID?

    java - CursorAdapter 与 android 和非法错误

    android - 当电话打断应用程序时,android 应用程序会发生什么情况?

    android - 如何将作为 json 字符串接收到的 .net DateTime 解析为 java 的 Date 对象