RecyclerView自动向上滚动并闪烁

3
基本上,我正在使用带有gridAdapter的RecyclerView从服务器加载图像。但问题是RecyclerView的项目以一种奇怪的方式闪烁。我尝试了所有可能的解决方案,但到目前为止都没有起作用。
我尝试将glide版本从4.4.0更新到4.8.0,但是徒劳无功。我还尝试禁用RecyclerView的动画,但那也没什么用。请问有人可以帮我解决这个问题吗?

See how Images are blinking

代码:

GridLayoutManager gridLayoutManager = new GridLayoutManager(v.getContext(),3);
gridLayoutManager.setSmoothScrollbarEnabled(true);
gridLayoutManager.setItemPrefetchEnabled(true);
gridLayoutManager.setInitialPrefetchItemCount(20);

posts_rView.setLayoutManager(gridLayoutManager);
posts_rView.setItemAnimator(null);
posts_rView.setHasFixedSize(true);

gridPostAdapter=new StarredAdapter(timelineDataList);
posts_rView.setAdapter(gridPostAdapter);

数据更新代码:

private  Emitter.Listener handlePosts = new Emitter.Listener(){

    @Override
    public void call(final Object... args){
        try {
            JSONArray jsonArray=(JSONArray)args[0];
            Needle.onMainThread().execute(() -> {
                timelineDataList.clear();
                swipeRefreshLayout.setRefreshing(false);

                for(int i=0;i<jsonArray.length();i++){
                    try {
                        //JSONArray arr=jsonArray.getJSONArray(i);
                        JSONObject ob=jsonArray.getJSONObject(i);

                        post_username=ob.getString("_pid");
                        post_fullname=ob.getString("owner_fullname");

                        if(ob.has("owner_profPic"))post_profPic=ob.getString("owner_profPic");
                        else post_profPic="";

                        post_time=ob.getString("time");

                        post_link=ob.getString("img_link");
                        likes_counter=ob.getString("likes_counter");
                        comments_counter=ob.getString("comments_counter");
                        if(ob.has("caption")) post_caption=ob.getString("caption");
                        else post_caption=null;

                        //Skipping Private Posts
                        if(ob.getString("private_post_stat").equals("yes")&&!post_username.equals(my_username)) {
                            continue;
                        }
                        else
                            private_post_stat = ob.getString("private_post_stat");

                        comment_disabled=ob.getString("comment_disabled");

                        share_disabled=ob.getString("share_disabled");

                        download_disabled=ob.getString("download_disabled");

                        if(ob.has("short_book_content")) short_book_content=ob.getString("short_book_content");
                        else short_book_content=null;
                        society_name_adp=ob.getString("society");

                        addTimelineData(post_username,post_fullname,post_profPic,post_time,post_link,post_caption,
                                private_post_stat,comment_disabled,share_disabled,download_disabled,likes_counter,comments_counter,short_book_content,society_name_adp);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                RecyclerView.Adapter adapter=posts_rView.getAdapter();
                posts_rView.setAdapter(null);
                posts_rView.setAdapter(adapter);
            });
        } catch (Exception e) {
            Log.e("error",e.toString());
        }
    }
};

private void addTimelineData(String username,String fullname,String post_profPic,String time,String img_link,String caption,
                             String private_post_stat,String comment_disabled,String share_disabled,String download_disabled,String likes_counter,
                             String comments_counter,String short_book_content,String society_name_adp){
    boolean isRepeated = false;
    for(TimelineData data:timelineDataList){
        if (data.getTime().equals(time)) {
            isRepeated = true;
        }
    }

    if(!isRepeated){
        timelineDataList.add(new TimelineData(username,fullname,post_profPic,time,img_link,caption,private_post_stat,comment_disabled,share_disabled,download_disabled,likes_counter,comments_counter,short_book_content,society_name_adp));
        gridPostAdapter.notifyDataSetChanged();
        // posts_rView.scrollToPosition(gridPostAdapter.getItemCount()-1);
       // posts_rView.scrollToPosition(0);
    }

     //gridPostAdapter.notifyItemInserted(timelineDataList.size()-1);
}

适配器类:
@Override
public void onBindViewHolder(StarViewHolder holder, int position) {

    //loading img
    Glide.with( parent.getContext()).asBitmap().load(arrayList.get(position)).apply(new RequestOptions()
        .override(200, 200)
        .dontAnimate()
        .placeholder(new ColorDrawable(Color.parseColor("#20001919"))))
        .thumbnail(0.1f)
        .into(holder.img);
}

@Override
public int getItemCount() {
    return arrayList.size();
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position) {
    return position;
}

你为什么会将RecyclerView的Adapter设置为null,然后再次设置适配器RecyclerView.Adapter adapter = posts_rView.getAdapter(); posts_rView.setAdapter(null); - Chetan Shelake
请在这里发布项目布局。 - Quick learner
1个回答

3
我还不太明白为什么您的情况会出现闪烁和重新定位到第一个元素,因为我没有看到您的RecyclerView的更新策略。但是,我想提供一些可能解决问题的建议。
  1. 建议在设置GridLayoutManager时删除setInitialPrefetchItemCount和setItemPrefetchEnabled配置,这将有助于嵌套的RecyclerView(这不是您的情况)。
  2. 每次从服务器更新数据时都会设置适配器。我猜测您在滚动项目时调用更新操作代码。您应该避免这样做。此外,请在更新数据集后仅使用notifyDataSetChanged而不是设置RecyclerView的适配器。不要清除timelineDataList,而是附加新项,然后在适配器上调用notifyDataSetChanged。
  3. 在列表中添加每个元素后,您都会在addTimelineData中调用notifyDataSetChanged。这应该只在添加所有元素后完成。
因此,我想提出以下代码来设置适配器并更新您的RecyclerView。请注意,我尚未测试该代码,您可能需要修改一些可能发生的错误。
设置布局管理器和适配器的代码:
GridLayoutManager gridLayoutManager = new GridLayoutManager(v.getContext(),3);
posts_rView.setLayoutManager(gridLayoutManager);
posts_rView.setHasFixedSize(true);

gridPostAdapter = new StarredAdapter(timelineDataList);
posts_rView.setAdapter(gridPostAdapter);

更新列表的代码。
private  Emitter.Listener handlePosts = new Emitter.Listener(){

    @Override
    public void call(final Object... args){
        try {
            JSONArray jsonArray = (JSONArray)args[0];
            Needle.onMainThread().execute(() -> {

                // Do not clear the list. Just append the new data in the list instead
                // timelineDataList.clear();

                swipeRefreshLayout.setRefreshing(false);

                for(int i = 0; i < jsonArray.length(); i++){
                    try {
                        JSONObject ob = jsonArray.getJSONObject(i);

                        post_username = ob.getString("_pid");
                        post_fullname = ob.getString("owner_fullname");
                        if(ob.has("owner_profPic")) post_profPic = ob.getString("owner_profPic");
                        else post_profPic = "";

                        post_time = ob.getString("time");

                        post_link = ob.getString("img_link");
                        likes_counter = ob.getString("likes_counter");
                        comments_counter = ob.getString("comments_counter");
                        if(ob.has("caption")) post_caption = ob.getString("caption");
                        else post_caption = null;

                        //Skipping Private Posts
                        if(ob.getString("private_post_stat").equals("yes")&&!post_username.equals(my_username)) {
                            continue;
                        }
                        else
                            private_post_stat = ob.getString("private_post_stat");

                        comment_disabled = ob.getString("comment_disabled");
                        share_disabled = ob.getString("share_disabled");
                        download_disabled = ob.getString("download_disabled");

                        if (ob.has("short_book_content")) short_book_content = ob.getString("short_book_content");
                        else short_book_content = null;

                        society_name_adp = ob.getString("society");
                        addTimelineData(post_username, post_fullname, post_profPic, post_time, post_link,post_caption, private_post_stat, comment_disabled, share_disabled, download_disabled, likes_counter, comments_counter, short_book_content, society_name_adp);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }

                gridPostAdapter.notifyDataSetChanged();
            });

        } catch (Exception e) {
            Log.e("error",e.toString());
        }
    }
};

private void addTimelineData(String username, String fullname, String post_profPic, String time, String img_link, String caption, String private_post_stat, String comment_disabled, String share_disabled, String download_disabled, String likes_counter, String comments_counter, String short_book_content, String society_name_adp) {

    boolean isRepeated = false;
    for(TimelineData data:timelineDataList){
        if (data.getTime().equals(time)) {
            isRepeated = true;
        }
    }

    if(!isRepeated){
        timelineDataList.add(new TimelineData(username,fullname,post_profPic,time,img_link,caption,private_post_stat,comment_disabled,share_disabled,download_disabled,likes_counter,comments_counter,short_book_content,society_name_adp));

        // Do not call notifyDataSetChanged each time you are adding an item. This will be called in the call function above. So remove this line.
        // gridPostAdapter.notifyDataSetChanged();
    }
}

尝试在服务器端API中添加一些分页,如果还没有的话,这样当您向下滚动时,可以获取下一个20个数据集,而不是再次获取整个数据集。希望能对您有所帮助。

很高兴知道我能帮到你。关于分页,这是另一个完整的讨论。不过,我只是提醒你一下。尝试从客户端发送一个额外的参数页码,例如1,以便服务器理解它需要发送前20个数据。要获取接下来的20个数据,请从客户端发送页面编号2,以此类推... - Reaz Murshed
再次感谢您的大力帮助。 - anonymous
@ReazMurshed 我也遇到了类似的问题,正如你所说,我嵌套了图像的recyclerview,它经常会闪烁。所以我尝试删除图像recyclerview,但结果相同。我正在使用reverse layout来进行recyclerview操作,你认为这可能是问题的原因吗? - Parag Pawar
设置RecyclerView与反向布局应该不是问题。但是如果没有看到代码,很难理解您的问题。如果您已经在某个地方发布了一个问题,请在此处发布链接 - 我会尝试查看! - Reaz Murshed
我猜测我找到了问题所在,它与LinearLayoutManager.stackFromEnd标志有关,我将其更改为true,看起来现在它正在工作。谢谢您。如果我再次遇到这个问题,我会告诉您的,再次感谢 :) - Parag Pawar
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接