首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在聊天屏幕中,RecyclerView在notifyDataSetChanged上滚动到顶部

在聊天屏幕中,RecyclerView在notifyDataSetChanged上滚动到顶部
EN

Stack Overflow用户
提问于 2017-03-31 00:25:04
回答 10查看 12.5K关注 0票数 15

我试图创建消息类屏幕使用recyclerView,这将从底部开始,并将loadMore数据时,用户达到顶端的聊天。但我正面临着这个奇怪的问题。

在调用notifyDataSetChanged时,我的recyclerView会滚动到顶部。由于这个原因,onLoadMore被多次调用。

下面是我的代码:

代码语言:javascript
复制
LinearLayoutManager llm = new LinearLayoutManager(context);
llm.setOrientation(LinearLayoutManager.VERTICAL);
llm.setStackFromEnd(true);
recyclerView.setLayoutManager(llm);

**在适配器中

代码语言:javascript
复制
 @Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (messages.size() > 8 && position == 0 && null != mLoadMoreCallbacks) {
        mLoadMoreCallbacks.onLoadMore();
    }

**在活动中

代码语言:javascript
复制
@Override
public void onLoadMore() {
    // Get data from database and add into arrayList
      chatMessagesAdapter.notifyDataSetChanged();
}

只是recyclerView会滚动到顶部。如果滚动到顶部停止,此问题将得到解决。请帮我找出这个问题的原因。提前谢谢。

EN

回答 10

Stack Overflow用户

发布于 2017-04-19 14:48:25

我认为你不应该那样使用onBindViewHolder,删除那些代码,适配器应该只绑定模型数据,而不是监听滚动。

我通常这样做"onLoadMore“:

在本练习中:

代码语言:javascript
复制
private boolean isLoading, totallyLoaded; //
RecyclerView mMessages;
LinearLayoutManager manager;
ArrayList<Message> messagesArray;
MessagesAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //...
    mMessages.setHasFixedSize(true);
    manager = new LinearLayoutManager(this);
    manager.setStackFromEnd(true);
    mMessages.setLayoutManager(manager);
    mMessages.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            if (manager.findFirstVisibleItemPosition() == 0 && !isLoading && !totallyLoaded) {
                onLoadMore();
                isLoading = true;
            }
        }
    });
    messagesArray = new ArrayList<>();
    adapter = new MessagesAdapter(messagesArray, this);
    mMessages.setAdapter(adapter);
}


@Override
public void onLoadMore() {
    //get more messages...
    messagesArray.addAll(0, moreMessagesArray);
    adapter.notifyItemRangeInserted(0, (int) moreMessagesArray.size();
    isLoading = false;
}

这对我来说非常有效,如果服务器没有返回更多的消息,就使用"totallyLoaded“来停止服务器调用。希望能对你有所帮助。

票数 5
EN

Stack Overflow用户

发布于 2017-04-16 14:18:28

您知道,当您插入新项目时,List会很自然地滚动到最上面的项目。您的方向是对的,但是我想您忘记添加了setReverseLayout(true).

在这里,setStackFromEnd(true)只是告诉List从视图底部开始堆叠项目,但是当与setReverseLayout(true)结合使用时,它会颠倒项目和视图的顺序,因此最新的项目总是显示在视图的底部。

最终的layoutManager应该是这样的:

代码语言:javascript
复制
        mLayoutManager = new LinearLayoutManager(getActivity());
        mLayoutManager.setReverseLayout(true);
        mLayoutManager.setStackFromEnd(true);
        mRecyclerView.setLayoutManager(mLayoutManager);
票数 2
EN

Stack Overflow用户

发布于 2017-04-16 15:16:22

不要在RecyclerView上调用notifyDataSetChanged()。使用新方法,如notifyItemChanged()notifyItemRangeChanged()notifyItemInserted()等。如果你使用notifyItemRangeInserted()--

在那之后不要调用setAdapter()方法..!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43123400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档