java - RecyclerView 自动向上滚动并闪烁

标签 java android gridview android-recyclerview

基本上,我使用 RecyclerViewgridAdapter 从服务器加载图像。但问题是 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 的更新策略。但是,我想提出一些可能会解决问题的建议。

  1. 我建议您在设置 GridLayoutManager 时删除 setInitialPrefetchItemCountsetItemPrefetchEnabled 配置。如果你有一个嵌套的 RecyclerView,这将有助于你的情况。
  2. 每次从服务器更新数据时,您都在设置适配器。我猜你在滚动项目时正在调用更新操作代码。你不应该这样做。此外,请删除每次更新数据集时设置 RecyclerView 的适配器。只需在每次更新后使用 notifyDataSetChanged。不要清除 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 个数据集,而不是在向下滚动时再次获取整个数据。

希望对您有所帮助。

关于java - RecyclerView 自动向上滚动并闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51999670/

相关文章:

java - 测试运行失败: Instrumentation run failed due to 'kotlin.UninitializedPropertyAccessException'

java - 将 SQLite 数据库转换为 Java Arraylist

android - 在某些 Android 设备中,图像无法在 FlatList 上呈现

java - 从 SD 卡获取图像时出现 FileNotFoundException

android - 不同屏幕尺寸的样式可以不同吗?

java - Hibernate:这个映射到外键连接的子类有什么问题?

java - 如何阻止鼠标退出窗口?

c# - gridview 中的 Oracle 数据库表

Java 使用外部文本文件中的数据

android - 在圆圈内绘制正方形布局