RecyclerView और java.lang.IndexOutOfBoundsException: असंगति का पता चला। सैमसंग उपकरणों में अमान्य व्यू होल्डर अडॉप्टर पोजिशन व्यूहोलडर


253

मेरे पास एक पुनर्नवीनीकरण दृश्य है जो सैमसंग को छोड़कर सभी उपकरणों पर पूरी तरह से काम करता है। सैमसंग पर, मुझे मिल रहा है

java.lang.IndexOutOfBoundsException: असंगतता का पता चला। अमान्य दृश्य धारक अडैप्टर स्थितिदृश्य फ़ोल्डर

जब मैं एक अन्य गतिविधि से पुनर्नवीनीकरण दृश्य के साथ खंड में वापस जा रहा हूं।

एडाप्टर कोड:

public class FeedRecyclerAdapter extends RecyclerView.Adapter<FeedRecyclerAdapter.MovieViewHolder> {
    public static final String getUserPhoto = APIConstants.BASE_URL + APIConstants.PICTURE_PATH_SMALL;
    Movie[] mMovies = null;
    Context mContext = null;
    Activity mActivity = null;
    LinearLayoutManager mManager = null;
    private Bus uiBus = null;
    int mCountOfLikes = 0;

    //Constructor
    public FeedRecyclerAdapter(Movie[] movies, Context context, Activity activity,
                               LinearLayoutManager manager) {
        mContext = context;
        mActivity = activity;
        mMovies = movies;
        mManager = manager;
        uiBus = BusProvider.getUIBusInstance();
    }

    public void setMoviesAndNotify(Movie[] movies, boolean movieIgnored) {
        mMovies = movies;
        int firstItem = mManager.findFirstVisibleItemPosition();
        View firstItemView = mManager.findViewByPosition(firstItem);
        int topOffset = firstItemView.getTop();
        notifyDataSetChanged();
        if(movieIgnored) {
            mManager.scrollToPositionWithOffset(firstItem - 1, topOffset);
        } else {
            mManager.scrollToPositionWithOffset(firstItem, topOffset);
        }
    }

    // Create new views (called by layout manager)
    @Override
    public MovieViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.feed_one_recommended_movie_layout, parent, false);

        return new MovieViewHolder(view);
    }

    // Replaced contend of each view (called by layout manager)
    @Override
    public void onBindViewHolder(MovieViewHolder holder, int position) {
        setLikes(holder, position);
        setAddToCollection(holder, position);
        setTitle(holder, position);
        setIgnoreMovieInfo(holder, position);
        setMovieInfo(holder, position);
        setPosterAndTrailer(holder, position);
        setDescription(holder, position);
        setTags(holder, position);
    }

    // returns item count (called by layout manager)
    @Override
    public int getItemCount() {
        return mMovies != null ? mMovies.length : 0;
    }

    private void setLikes(final MovieViewHolder holder, final int position) {
        List<Reason> likes = new ArrayList<>();
        for(Reason reason : mMovies[position].reasons) {
            if(reason.title.equals("Liked this movie")) {
                likes.add(reason);
            }
        }
        mCountOfLikes = likes.size();
        holder.likeButton.setText(mContext.getString(R.string.like)
            + Html.fromHtml(getCountOfLikesString(mCountOfLikes)));
        final MovieRepo repo = MovieRepo.getInstance();
        final int pos = position;
        final MovieViewHolder viewHolder = holder;
        holder.likeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mMovies[pos].isLiked) {
                    repo.unlikeMovie(AuthStore.getInstance()
                        .getAuthToken(), mMovies[pos].id, new Callback<Movie>() {
                        @Override
                        public void success(Movie movie, Response response) {
                            Drawable img = mContext.getResources().getDrawable(R.drawable.ic_like);
                            viewHolder.likeButton
                                .setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);
                            if (--mCountOfLikes <= 0) {
                                viewHolder.likeButton.setText(mContext.getString(R.string.like));
                            } else {
                                viewHolder.likeButton
                                    .setText(Html.fromHtml(mContext.getString(R.string.like)
                                        + getCountOfLikesString(mCountOfLikes)));
                            }
                            mMovies[pos].isLiked = false;
                        }

                        @Override
                        public void failure(RetrofitError error) {
                            Toast.makeText(mContext.getApplicationContext(),
                                mContext.getString(R.string.cannot_like), Toast.LENGTH_LONG)
                                .show();
                        }
                    });
                } else {
                    repo.likeMovie(AuthStore.getInstance()
                        .getAuthToken(), mMovies[pos].id, new Callback<Movie>() {
                        @Override
                        public void success(Movie movie, Response response) {
                            Drawable img = mContext.getResources().getDrawable(R.drawable.ic_liked_green);
                            viewHolder.likeButton
                                .setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);
                            viewHolder.likeButton
                                .setText(Html.fromHtml(mContext.getString(R.string.like)
                                    + getCountOfLikesString(++mCountOfLikes)));
                            mMovies[pos].isLiked = true;
                            setComments(holder, position);
                        }

                        @Override
                        public void failure(RetrofitError error) {
                            Toast.makeText(mContext,
                                mContext.getString(R.string.cannot_like), Toast.LENGTH_LONG).show();
                        }
                    });
                }
            }
        });
    }

    private void setComments(final MovieViewHolder holder, final int position) {
        holder.likeAndSaveButtonLayout.setVisibility(View.GONE);
        holder.commentsLayout.setVisibility(View.VISIBLE);
        holder.sendCommentButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (holder.commentsInputEdit.getText().length() > 0) {
                    CommentRepo repo = CommentRepo.getInstance();
                  repo.sendUserComment(AuthStore.getInstance().getAuthToken(), mMovies[position].id,
                        holder.commentsInputEdit.getText().toString(), new Callback<Void>() {
                            @Override
                            public void success(Void aVoid, Response response) {
                                Toast.makeText(mContext, mContext.getString(R.string.thanks_for_your_comment),
                                    Toast.LENGTH_SHORT).show();
                                hideCommentsLayout(holder);
                            }

                            @Override
                            public void failure(RetrofitError error) {
                                Toast.makeText(mContext, mContext.getString(R.string.cannot_add_comment),
                                    Toast.LENGTH_LONG).show();
                            }
                        });
                } else {
                    hideCommentsLayout(holder);
                }
            }
        });
    }

    private void hideCommentsLayout(MovieViewHolder holder) {
        holder.commentsLayout.setVisibility(View.GONE);
        holder.likeAndSaveButtonLayout.setVisibility(View.VISIBLE);
    }

    private void setAddToCollection(final MovieViewHolder holder, int position) {
        final int pos = position;
        if(mMovies[position].isInWatchlist) {
            holder.saveButton
              .setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_check_green, 0, 0, 0);
        }
        final CollectionRepo repo = CollectionRepo.getInstance();
        holder.saveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!mMovies[pos].isInWatchlist) {
                   repo.addMovieToCollection(AuthStore.getInstance().getAuthToken(), 0, mMovies[pos].id, new Callback<MovieCollection[]>() {
                            @Override
                            public void success(MovieCollection[] movieCollections, Response response) {
                                holder.saveButton
                                    .setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_check_green, 0, 0, 0);

                                mMovies[pos].isInWatchlist = true;
                            }

                            @Override
                            public void failure(RetrofitError error) {
                                Toast.makeText(mContext, mContext.getString(R.string.movie_not_added_to_collection),
                                    Toast.LENGTH_LONG).show();
                            }
                        });
                } else {
                 repo.removeMovieFromCollection(AuthStore.getInstance().getAuthToken(), 0,
                        mMovies[pos].id, new Callback<MovieCollection[]>() {
                        @Override
                        public void success(MovieCollection[] movieCollections, Response response) {
                            holder.saveButton
                                .setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_plus, 0, 0, 0);

                            mMovies[pos].isInWatchlist = false;
                        }

                        @Override
                        public void failure(RetrofitError error) {
                            Toast.makeText(mContext,
                                mContext.getString(R.string.cannot_delete_movie_from_watchlist),
                                Toast.LENGTH_LONG).show();
                        }
                    });
                }
            }
        });
    }

    private String getCountOfLikesString(int countOfLikes) {
        String countOfLikesStr;
        if(countOfLikes == 0) {
            countOfLikesStr = "";
        } else if(countOfLikes > 999) {
            countOfLikesStr = " " + (countOfLikes/1000) + "K";
        } else if (countOfLikes > 999999){
            countOfLikesStr = " " + (countOfLikes/1000000) + "M";
        } else {
            countOfLikesStr = " " + String.valueOf(countOfLikes);
        }
        return "<small>" + countOfLikesStr + "</small>";
    }

    private void setTitle(MovieViewHolder holder, final int position) {
        holder.movieTitleTextView.setText(mMovies[position].title);
        holder.movieTitleTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MovieDetailActivity.openView(mContext, mMovies[position].id, true, false);
            }
        });
    }

    private void setIgnoreMovieInfo(MovieViewHolder holder, final int position) {
        holder.ignoreMovie.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MovieRepo repo = MovieRepo.getInstance();
                repo.hideMovie(AuthStore.getInstance().getAuthToken(), mMovies[position].id,
                    new Callback<Void>() {
                        @Override
                        public void success(Void aVoid, Response response) {
                            Movie[] newMovies = new Movie[mMovies.length - 1];
                            for (int i = 0, j = 0; j < mMovies.length; i++, j++) {
                                if (i != position) {
                                    newMovies[i] = mMovies[j];
                                } else {
                                    if (++j < mMovies.length) {
                                        newMovies[i] = mMovies[j];
                                    }
                                }
                            }
                            uiBus.post(new MoviesChangedEvent(newMovies));
                            setMoviesAndNotify(newMovies, true);
                            Toast.makeText(mContext, mContext.getString(R.string.movie_ignored),
                                Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void failure(RetrofitError error) {
                            Toast.makeText(mContext, mContext.getString(R.string.movie_ignored_failed),
                                Toast.LENGTH_LONG).show();
                        }
                    });
            }
        });
    }

    private void setMovieInfo(MovieViewHolder holder, int position) {
        String imdp = "IMDB: ";
        String sources = "", date;
        if(mMovies[position].showtimes != null && mMovies[position].showtimes.length > 0) {
            int countOfSources = mMovies[position].showtimes.length;
            for(int i = 0; i < countOfSources; i++) {
                sources += mMovies[position].showtimes[i].name + ", ";
            }
            sources = sources.trim();
            if(sources.charAt(sources.length() - 1) == ',') {
                if(sources.length() > 1) {
                    sources = sources.substring(0, sources.length() - 2);
                } else {
                    sources = "";
                }
            }
        } else {
            sources = "";
        }
        imdp += mMovies[position].imdbRating + " | ";
        if(sources.isEmpty()) {
            date = mMovies[position].releaseYear;
        } else {
            date = mMovies[position].releaseYear + " | ";
        }

        holder.movieInfoTextView.setText(imdp + date + sources);
    }

    private void setPosterAndTrailer(final MovieViewHolder holder, final int position) {
        if (mMovies[position] != null && mMovies[position].posterPath != null
            && !mMovies[position].posterPath.isEmpty()) {
            Picasso.with(mContext)
                .load(mMovies[position].posterPath)
             .error(mContext.getResources().getDrawable(R.drawable.noposter))
                .into(holder.posterImageView);
        } else {
            holder.posterImageView.setImageResource(R.drawable.noposter);
        }
        holder.posterImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MovieDetailActivity.openView(mActivity, mMovies[position].id, false, false);
            }
        });
        if(mMovies[position] != null && mMovies[position].trailerLink  != null
            && !mMovies[position].trailerLink.isEmpty()) {
            holder.playTrailer.setVisibility(View.VISIBLE);
            holder.playTrailer.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    MovieDetailActivity.openView(mActivity, mMovies[position].id, false, true);
                }
            });
        }
    }

    private void setDescription(MovieViewHolder holder, int position) {
        String text = mMovies[position].overview;
        if(text == null || text.isEmpty()) {
       holder.descriptionText.setText(mContext.getString(R.string.no_description));
        } else if(text.length() > 200) {
            text = text.substring(0, 196) + "...";
            holder.descriptionText.setText(text);
        } else {
            holder.descriptionText.setText(text);
        }
        final int pos = position;
        holder.descriptionText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MovieDetailActivity.openView(mActivity, mMovies[pos].id, false, false);
            }
        });
    }

    private void setTags(MovieViewHolder holder, int position) {
        List<String> tags = Arrays.asList(mMovies[position].tags);
        if(tags.size() > 0) {
            CastAndTagsFeedAdapter adapter = new CastAndTagsFeedAdapter(tags,
                mContext, ((FragmentActivity) mActivity).getSupportFragmentManager());
            holder.tags.setItemMargin(10);
            holder.tags.setAdapter(adapter);
        } else {
            holder.tags.setVisibility(View.GONE);
        }
    }

    // class view holder that provide us a link for each element of list
    public static class MovieViewHolder extends RecyclerView.ViewHolder {
        TextView movieTitleTextView, movieInfoTextView, descriptionText, reasonsCountText;
        TextView reasonText1, reasonAuthor1, reasonText2, reasonAuthor2;
        EditText commentsInputEdit;
        Button likeButton, saveButton, playTrailer, sendCommentButton;
        ImageButton ignoreMovie;
        ImageView posterImageView, userPicture1, userPicture2;
        TwoWayView tags;
        RelativeLayout mainReasonsLayout, firstReasonLayout, secondReasonLayout, reasonsListLayout;
        RelativeLayout commentsLayout;
        LinearLayout likeAndSaveButtonLayout;
        ProgressBar progressBar;

        public MovieViewHolder(View view) {
            super(view);
            movieTitleTextView = (TextView)view.findViewById(R.id.movie_title_text);
            movieInfoTextView = (TextView)view.findViewById(R.id.movie_info_text);
            descriptionText = (TextView)view.findViewById(R.id.text_description);
            reasonsCountText = (TextView)view.findViewById(R.id.reason_count);
            reasonText1 = (TextView)view.findViewById(R.id.reason_text_1);
            reasonAuthor1 = (TextView)view.findViewById(R.id.author_1);
            reasonText2 = (TextView)view.findViewById(R.id.reason_text_2);
            reasonAuthor2 = (TextView)view.findViewById(R.id.author_2);
            commentsInputEdit = (EditText)view.findViewById(R.id.comment_input);
            likeButton = (Button)view.findViewById(R.id.like_button);
            saveButton = (Button)view.findViewById(R.id.save_button);
            playTrailer = (Button)view.findViewById(R.id.play_trailer_button);
            sendCommentButton = (Button)view.findViewById(R.id.send_button);
            ignoreMovie = (ImageButton)view.findViewById(R.id.ignore_movie_imagebutton);
            posterImageView = (ImageView)view.findViewById(R.id.poster_image);
            userPicture1 = (ImageView)view.findViewById(R.id.user_picture_1);
            userPicture2 = (ImageView)view.findViewById(R.id.user_picture_2);
            tags = (TwoWayView)view.findViewById(R.id.list_view_feed_tags);
            mainReasonsLayout = (RelativeLayout)view.findViewById(R.id.reasons_main_layout);
            firstReasonLayout = (RelativeLayout)view.findViewById(R.id.first_reason);
            secondReasonLayout = (RelativeLayout)view.findViewById(R.id.second_reason);
            reasonsListLayout = (RelativeLayout)view.findViewById(R.id.reasons_list);
            commentsLayout = (RelativeLayout)view.findViewById(R.id.comments_layout);
            likeAndSaveButtonLayout = (LinearLayout)view
                .findViewById(R.id.like_and_save_buttons_layout);
            progressBar = (ProgressBar)view.findViewById(R.id.centered_progress_bar);
        }
    }
}

अपवाद:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{42319ed8 position=1 id=-1, oldPos=0, pLpos:0 scrap tmpDetached no parent}
 at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:4166)
 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4297)
 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4278)
 at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1947)
 at android.support.v7.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:434)
 at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1322)
 at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:556)
 at android.support.v7.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:171)
 at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2627)
 at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2971)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:562)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
 at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1626)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
 at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
 at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1626)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
 at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
 at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
 at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
 at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
 at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
 at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
07-30 12:48:22.688    9590-9590/com.Filmgrail.android.debug W/System.err? at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1677)
 at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1531)
 at android.widget.LinearLayout.onLayout(LinearLayout.java:1440)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
 at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
 at android.view.View.layout(View.java:15746)
 at android.view.ViewGroup.layout(ViewGroup.java:4867)
 at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2356)
 at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2069)
 at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
 at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6630)
 at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803)
 at android.view.Choreographer.doCallbacks(Choreographer.java:603)
 at android.view.Choreographer.doFrame(Choreographer.java:573)
 at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789)
 at android.os.Handler.handleCallback(Handler.java:733)
 at android.os.Handler.dispatchMessage(Handler.java:95)
 at android.os.Looper.loop(Looper.java:136)
 at android.app.ActivityThread.main(ActivityThread.java:5479)
 at java.lang.reflect.Method.invokeNative(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:515)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
 at dalvik.system.NativeStart.main(Native Method)

मैं इसे कैसे ठीक करूं?


जब आप वापस आते हैं, तो क्या आपका डेटा वैसा ही होता है जब आप पृष्ठ छोड़ते हैं?
खुशव

मैं उसी मुद्दे को समझ रहा हूं कि आप कैसे हल करते हैं ....
अश्विन

@ Владимир क्या आपको निश्चित उत्तर मिला?
अलीरज़ा नूराली

मेरे मामले में, ऐसा इसलिए था क्योंकि मैंने async टास्क शुरू किया था, और जब उनमें से एक दूसरे से पहले पूरा हो जाता है और उपयोगकर्ता नीचे स्क्रॉल करता है और इस बीच में एक और पूर्ण और अपडेट एडॉप्टर उपयोगकर्ता को इस तरह का अपवाद मिल सकता है क्योंकि दूसरा कार्य डेटा की कम राशि
लौटाता है

जवाबों:


196

यह समस्या RecyclerViewअलग-अलग थ्रेड में संशोधित डेटा के कारण होती है । सबसे अच्छा तरीका सभी डेटा एक्सेस की जांच करना है। और एक वर्कअराउंड रैपिंग है LinearLayoutManager

पिछला उत्तर

वास्तव में RecyclerView में एक बग था और समर्थन 23.1.1 अभी भी तय नहीं है।

वर्कअराउंड के लिए, ध्यान दें कि बैकट्रेस स्टैक, अगर हम Exceptionइसे किसी एक क्लास में पकड़ सकते हैं तो यह क्रैश को छोड़ सकता है। मेरे लिए, मैं एक बनाता हूं LinearLayoutManagerWrapperऔर ओवरराइड करता हूं onLayoutChildren:

public class WrapContentLinearLayoutManager extends LinearLayoutManager {
    //... constructor
    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        try {
            super.onLayoutChildren(recycler, state);
        } catch (IndexOutOfBoundsException e) {
            Log.e("TAG", "meet a IOOBE in RecyclerView");
        }
    }
}

फिर इसे इसके लिए सेट करें RecyclerView:

RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);

recyclerView.setLayoutManager(new WrapContentLinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false));

वास्तव में इस अपवाद को पकड़ते हैं, और अभी तक कोई दुष्प्रभाव नहीं है।

इसके अलावा, यदि आप उपयोग करते हैं GridLayoutManagerया StaggeredGridLayoutManagerआपको इसके लिए एक आवरण बनाना होगा।

सूचना: RecyclerViewएक गलत आंतरिक स्थिति में हो सकती है।


1
वास्तव में आप इसे कहाँ रखते हैं? एडॉप्टर या गतिविधि पर?
स्टीव कामाऊ

इसका विस्तार करें LinearLayoutManagerऔर इसे ओवरराइड करें। मैं अपने जवाब में एक जोड़ दूंगा।
साकिम

14
code.google.com/p/android/issues/detail?id=158046 उत्तर # 12 ने कहा कि ऐसा मत करो।
रॉबर्ट

ummm, तुम सही हो। मेरे ऐप में सभी संभावित गैर-यूआई-थ्रेड संशोधनों को परिभाषित करना कठिन लगता है, मैं इसे केवल वर्कअराउंड तरीके के रूप में रखूंगा।
साकिन

1
अपने मामले के लिए मैं एक ही सूत्र पर काम कर रहा हूं। । mDataHolder.get () removeAll (mHiddenGenre); mAdapter.notifyItemRangeRemoved (mExpandButtonPosition, mHiddenGenre.size ());
जेहादकाड

73

यह पूरी तरह से नई सामग्री के साथ डेटा को ताज़ा करने के लिए एक उदाहरण है। अपनी आवश्यकताओं को पूरा करने के लिए आप इसे आसानी से संशोधित कर सकते हैं। मैंने कॉल करके अपने मामले में इसे हल किया:

notifyItemRangeRemoved(0, previousContentSize);

इससे पहले:

notifyItemRangeInserted(0, newContentSize);

यह सही समाधान है और इस पोस्ट में AOSP परियोजना के सदस्य द्वारा भी इसका उल्लेख किया गया है ।


2
यह समाधान मेरे लिए काम करता है मैंने यहां बहुत से उत्तर दिए, लेकिन वे काम नहीं करते हैं (मैंने पहले समाधान के परीक्षण का परीक्षण नहीं किया)
एंड्रोलाइफ

समस्या इन विधियों का उपयोग कर रही है, उस विसंगति का निर्माण करती है, जब एक ही धागे पर भी किया जाता है।
जेहादकाक

मैं notifyItemRangeInsertedकुछ सैमसंग उपकरणों के साथ इस मुद्दे का उपयोग नहीं करता और करता हूं
उपयोगकर्ता 25

और यहाँ काफी ऑफ टॉपिक है। लेखक का उपयोग नहीं कियाnotifyItemRangeInserted
23:25 पर उपयोगकर्ता 25

1
धन्यवाद! इससे मुझे मदद मिली।
दिमित्रीकुननिकॉफ

35

मुझे एक बार इस मुद्दे का सामना करना पड़ा, और मैंने इसे लपेटकर हल किया LayoutManager भविष्यवाणी के एनिमेशन को और अक्षम ।

यहाँ एक उदाहरण है:

public class LinearLayoutManagerWrapper extends LinearLayoutManager {

  public LinearLayoutManagerWrapper(Context context) {
    super(context);
  }

  public LinearLayoutManagerWrapper(Context context, int orientation, boolean reverseLayout) {
    super(context, orientation, reverseLayout);
  }

  public LinearLayoutManagerWrapper(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
  }

  @Override
  public boolean supportsPredictiveItemAnimations() {
    return false;
  }
}

और इसे सेट करें RecyclerView:

RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManagerWrapper(context, LinearLayoutManager.VERTICAL, false);

यह मेरे लिए काम करने लगता है, लेकिन क्या आप बता सकते हैं कि यह काम क्यों करता है?
डेनिस एंडरसन

मेरे लिए भी तय। आपने कैसे भविष्यवाणी की कि यह इस दुर्घटना का कारण हो सकता है।
राहुल रस्तोगी

1
LinearLayoutManager विधि का आधार वर्ग डिफ़ॉल्ट रूप से गलत (रिटर्न) गलत का समर्थन करता है। यहाँ विधि को ओवरराइड करके हम क्या प्राप्त कर रहे हैं? public boolean supportsPredictiveItemAnimations() { return false; }
एम। हिग

1
@ M.Hig के लिए दस्तावेज़ यह LinearLayoutManagerकहता है कि डिफ़ॉल्ट गलत है, लेकिन यह कथन गलत है :-( के लिए LinearLayoutManagerडिकम्पेल्ड कोड में यह है: सार्वजनिक बूलियनPredictiveItemAnimations का समर्थन करता है () {इसे वापस भेजें। ;}
क्लाइड

मैं अपने रिसायकलर व्यू अडैप्टर को अपडेट करने के लिए अलग-अलग बर्तनों का उपयोग करता हूं और इस उत्तर ने क्रैश को ठीक कर दिया है। बहुत बहुत धन्यवाद, प्रिय लेखक!
यूजीन पी।

29

नया उत्तर: सभी पुनर्नवीनीकरण अपडेट के लिए डिफुटिल का उपयोग करें। यह प्रदर्शन और ऊपर बग दोनों के साथ मदद करेगा। यहाँ देखें

पिछला जवाब: यह मेरे लिए काम किया। कुंजी का उपयोग नहीं करना है notifyDataSetChanged()और सही चीजों को सही क्रम में करना है:

public void setItems(ArrayList<Article> newArticles) {
    //get the current items
    int currentSize = articles.size();
    //remove the current items
    articles.clear();
    //add all the new items
    articles.addAll(newArticles);
    //tell the recycler view that all the old items are gone
    notifyItemRangeRemoved(0, currentSize);
    //tell the recycler view how many new items we added
    notifyItemRangeInserted(0, newArticles.size());
}

1
यह एक अच्छी व्याख्या के साथ सबसे गहन समाधान है। धन्यवाद!
साकिबॉय

तो फिर क्या है नोटिडेटसेशनचार्ज (), @ बोलिंग के बजाय, नोटिफ़िमेट्रिंजिन्सेरेटेड का उपयोग करने का उद्देश्य।
अंकुर_009

@FilipLuch क्या आप बता सकते हैं कि क्यों?
श्रीकांत करुमनघाट

3
@ श्रीकांतकर्मनघाट ज़रूर, दुनो मैंने कारण क्यों नहीं बताया। मूल रूप से वह तब साफ़ करता है जब सूची में सभी आइटम फिर से बनते हैं। जैसे खोज परिणामों में, बहुत बार आपको एक ही आइटम मिलता है, या जब ताज़ा किया जाता है तो आपको एक ही आइटम मिलता है और फिर आप सब कुछ फिर से बना लेंगे, जो प्रदर्शन की बर्बादी है। इसके बजाय डिफ्यूटल का उपयोग करें और केवल सभी मदों के बजाय परिवर्तनों को अपडेट करें। यह हर बार ए से जेड तक जाने जैसा है, लेकिन आपने केवल एफ को वहां बदल दिया है।
फ़िलिप लुचिएनेंको

2
डिफ्यूटिल एक छिपा हुआ खजाना है। साझा करने के लिए धन्यवाद!
सिलेरिया

22

कारण इस समस्या के कारण:

  1. जब आइटम एनिमेशन सक्षम होते हैं तो रिसाइकलर में एक आंतरिक समस्या
  2. एक और धागे में रिसाइकलर डेटा पर संशोधन
  3. गलत तरीके से सूचना विधियों को कॉल करना

उपाय:

----------------- समाधान 1 ---------------

  • अपवाद को पकड़ने (विशेष रूप से # 3 कारण के लिए अनुशंसित नहीं)

निम्नलिखित के रूप में एक कस्टम LinearLayoutManager बनाएं और इसे ReyclerView पर सेट करें

    public class CustomLinearLayoutManager extends LinearLayoutManager {

            //Generate constructors

            @Override
            public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {

                try {

                    super.onLayoutChildren(recycler, state);

                } catch (IndexOutOfBoundsException e) {

                    Log.e(TAG, "Inconsistency detected");
                }

            }
        }

फिर RecyclerVIew लेआउट प्रबंधक को निम्नानुसार सेट करें:

recyclerView.setLayoutManager(new CustomLinearLayoutManager(activity));

----------------- समाधान 2 ---------------

  • आइटम ऐनिमेशन अक्षम करें (यदि समस्या # 1 के कारण हो तो समस्या को हल करता है):

फिर से, एक कस्टम रैखिक लेआउट प्रबंधक बनाएं जैसा कि निम्नलिखित है:

    public class CustomLinearLayoutManager extends LinearLayoutManager {

            //Generate constructors

             @Override
             public boolean supportsPredictiveItemAnimations() {
                 return false;
             }
        }

फिर RecyclerVIew लेआउट प्रबंधक को निम्नानुसार सेट करें:

recyclerView.setLayoutManager(new CustomLinearLayoutManager(activity));

----------------- समाधान 3 ---------------

  • यह समाधान समस्या को ठीक करता है यदि यह # 3 कारण से होता है। आपको यह सुनिश्चित करने की आवश्यकता है कि आप सही तरीके से अधिसूचित विधियों का उपयोग कर रहे हैं। वैकल्पिक रूप से, स्मार्ट, आसान और सहज तरीके से परिवर्तन को संभालने के लिए डिफ्यूटिल का उपयोग करें। Android RecyclerView में DiffUtil का उपयोग करना

----------------- समाधान 4 ---------------

  • # 2 कारण के लिए, आपको रिसाइकलर सूची में सभी डेटा एक्सेस की जांच करने और यह सुनिश्चित करने की आवश्यकता है कि किसी अन्य थ्रेड पर कोई संशोधन नहीं है।

इसने मेरे परिदृश्य में काम किया, मैं डिफुटिल का उपयोग नहीं कर सकता क्योंकि मेरे पास रिसाइकलर्स और एडेप्टर के लिए कस्टम घटक हैं, और त्रुटि बिल्कुल विशिष्ट परिदृश्यों में होती है, जो कि ज्ञात हैं, मुझे बस आइटम एनिमेटरों को हटाने का सहारा लेने के बिना पैच करने की आवश्यकता है, इसलिए केवल इसे एक कोशिश और कैच में लपेटा
RJFares

17

मुझे भी ऐसी ही समस्या का समाधान करना पड़ा था।

नीचे त्रुटि कोड में समस्या:

int prevSize = messageListHistory.size();
// some insert
adapter.notifyItemRangeInserted(prevSize - 1, messageListHistory.size() -1);

उपाय:

int prevSize = messageListHistory.size();
// some insert
adapter.notifyItemRangeInserted(prevSize, messageListHistory.size() -prevSize);

यह मेरे लिए बहुत अच्छा काम किया! यकीन नहीं है कि हम बस का उपयोग क्यों नहीं कर सकते हैं newList.size() - 1
waseefakhtar

15

इस समस्या के अनुसार , समस्या को हल कर दिया गया है और संभवतः 2015 की शुरुआत के पास कुछ समय जारी किया गया था। उसी धागे से एक उद्धरण :

यह विशेष रूप से CallDataSetChanged से संबंधित है। [...]

Btw, मैं जोरदार सलाह देते हैं कि InformDataSetChanged का उपयोग न करें क्योंकि यह एनिमेशन और प्रदर्शन को मारता है। इस मामले के लिए, विशिष्ट सूचनाओं का उपयोग करके समस्या के चारों ओर काम किया जाएगा।

यदि आप अभी भी समर्थन लाइब्रेरी के हाल के संस्करण के साथ समस्याएँ हैं, तो मैं आपको अपने एडॉप्टर के अंदर notifyXXX(विशेष रूप से, आपके उपयोग की notifyDataSetChanged) कॉल की समीक्षा करने का सुझाव दूंगा ताकि आप (कुछ नाज़ुक / अस्पष्ट) RecyclerView.Adapterअनुबंध का पालन कर सकें । इसके अलावा उन सूचनाओं को मुख्य धागे पर जारी करना सुनिश्चित करें।


16
वास्तव में नहीं, मैं प्रदर्शन के बारे में आपके हिस्से से सहमत हूं, लेकिन InformDataSetChanged () एनिमेशन को नहीं मारता है, अधिसूचित करने के लिए अनौपचारिक रूप से InformDataSetChanged (), a) कॉल सेटहैसटेबल (सच्चा) अपने RecyclerView.Adcape ऑब्जेक्ट और b) ओवरराइड getItemId को अपने एडेप्टर के अंदर वापस करने के लिए। प्रत्येक पंक्ति के लिए अद्वितीय लंबा मान और इसे देखें, एनिमेशन काम करते हैं
PirateApp

@PirateApp आपको अपनी टिप्पणी को एक उत्तर के रूप में बनाने पर विचार करना चाहिए। मैंने इसे आजमाया है और यह ठीक काम कर रहा है।
mr5

सच नहीं! फिर भी इस समस्या के बारे में Google कंसोल से रिपोर्ट प्राप्त करें। और निश्चित रूप से डिवाइस सैमसंग -Samsung Galaxy J3(2017) (j3y17lte), Android 8.0
user25

10

मुझे भी यही समस्या थी। यह कारण था क्योंकि मैंने आइटम डालने के बारे में एडाप्टर के लिए अधिसूचना में देरी की।

लेकिन ViewHolderइसमें कुछ डेटा को देखने के लिए फिर से शुरू करने की कोशिश की गई और इसने RecyclerViewबच्चों की गणना को मापना और पुनरावृत्ति करना शुरू कर दिया - उस समय यह दुर्घटनाग्रस्त हो गया (आइटम सूची और यह आकार पहले से ही अद्यतन किया गया था, लेकिन एडॉप्टर अभी तक अधिसूचित नहीं किया गया था)।


8

यह तब होता है जब आप InformItemChanged, InformItemRangeInserted etc.For मेरे लिए गलत स्थिति निर्दिष्ट करते हैं:

पहले: (त्रुटिपूर्ण)

public void addData(List<ChannelItem> list) {
  int initialSize = list.size();
  mChannelItemList.addAll(list);
  notifyItemRangeChanged(initialSize - 1, mChannelItemList.size());
 } 

के बाद: (सही)

 public void addData(List<ChannelItem> list) {
  int initialSize = mChannelItemList.size();
  mChannelItemList.addAll(list);
  notifyItemRangeInserted(initialSize, mChannelItemList.size()-1); //Correct position 
 }

1
क्यों notifyItemRangeInserted(initialSize, mChannelItemList.size()-1);और क्या नहीं notifyItemRangeInserted(initialSize, list.size());?
कूलमाइंड

Undestood। आप मिश्रित initialSizeऔर listआकार। तो, आपके दोनों वेरिएंट गलत हैं।
CoolMind

मेरे लिए यह साथ काम करता है notifyItemRangeInserted(initialSize, list.size()-1);लेकिन मुझे नहीं मिलता। मुझे आइटम कााउंट के लिए सम्मिलित आकार को एक-एक करके कम क्यों करना होगा?
प्लेक्सस

7

एक अन्य कारण यह समस्या तब होती है जब आप इन विधियों को गलत अनुक्रमित कहते हैं (ऐसे अनुक्रमणिका जिनमें कोई प्रविष्टि सम्मिलित नहीं हुई है या उन्हें हटाया नहीं गया है)

-notifyItemRangeRemoved

-notifyItemRemoved

-notifyItemRangeInserted

-notifyItemInserted

इन विधियों को अनुक्रमित मापदंडों की जाँच करें और सुनिश्चित करें कि वे सटीक और सही हैं।


2
यह मेरी समस्या थी। सूची में कुछ नहीं जोड़ने पर अपवाद होता है।
रसैल

6

यह बग अभी भी 23.1.1 में तय नहीं किया गया है, लेकिन एक सामान्य समाधान अपवाद को पकड़ने के लिए होगा।


18
इसे पकड़ो, बिल्कुल कहाँ? स्टैक ट्रेस में एकमात्र कोड मूल Android कोड है।
Howettl

1
इसे @saki_M उत्तर की तरह ही पकड़ें।
रेना बंदेइरा

क्या यह वास्तव में आपके लिए हालांकि रेनन का काम करता है? क्या आपने कुछ समय के लिए फिक्स का परीक्षण किया है? बग केवल कभी-कभी होता है इसलिए मैं केवल यह देखूंगा कि यह समय के साथ काम करता है या नहीं।
सिमोन

यह वास्तव में काम करता है, लेकिन मेरे कुछ बच्चे के विचार असंगत रूप से बने हुए हैं।
दाविद

@david असंगतता बनी हुई है इसका परिणाम क्या है?
श्रीकांत करुमनघाट

4

यह समस्या विभिन्न थ्रेड में संशोधित RecyclerView Data के कारण होती है

एक समस्या के रूप में थ्रेडिंग की पुष्टि कर सकते हैं और जब से मैं इस मुद्दे में भाग गया और RxJava तेजी से लोकप्रिय हो रहा है: सुनिश्चित करें कि आप .observeOn(AndroidSchedulers.mainThread())जब भी कॉल कर रहे हैंnotify[whatever changed]

एडेप्टर से कोड उदाहरण:

myAuxDataStructure.getChangeObservable().observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<AuxDataStructure>() {

    [...]

    @Override
    public void onNext(AuxDataStructure o) {
        [notify here]
    }
});

DiffUtil.calculateDiff (diffUtilForecastItemChangesAnlayser (this.mWeatherForecatsItemWithMainAndWeathers, weatherworecastItems)) को कॉल करते हुए मैं मुख्य थ्रेड पर हूं। लॉग स्पष्ट है: थ्रेड [मुख्य, 5, मुख्य]
मैथियास

4

मेरे केस में हर बार जब मैं InformItemRemoved (0) को कॉल करता हूं, तो यह क्रैश हो जाता है। यह पता चला कि मैंने सेट किया है setHasStableIds(true)और getItemIdमैंने अभी आइटम स्थिति वापस की है। मैंने आइटम के hashCode()स्व-परिभाषित यूनिक आईडी को वापस करने के लिए इसे अपडेट करना समाप्त कर दिया , जिससे समस्या हल हो गई।


4

मेरे मामले में, सर्वर से डेटा अपडेट प्राप्त करने के कारण मुझे यह समस्या हो रही थी (मैं फायरबेस फायरस्टार का उपयोग कर रहा हूं) और जबकि डेटा के पहले सेट को डिफ्यूटिल द्वारा पृष्ठभूमि में संसाधित किया जा रहा है, डेटा अपडेट का एक और सेट आता है और एक संक्षिप्त मुद्दे का कारण बनता है एक और डिफुटिल शुरू करके।

संक्षेप में, यदि आप एक बैकग्राउंड थ्रेड पर DiffUtil का उपयोग कर रहे हैं, जो फिर RecylerView पर परिणाम भेजने के लिए मुख्य थ्रेड पर वापस आता है, तो आप कम समय में कई डेटा अपडेट आने पर इस त्रुटि को प्राप्त करने का मौका चलाते हैं।

मैंने इस अद्भुत स्पष्टीकरण में सलाह का पालन करके इसे हल किया: https://medium.com/@jonfhancock/get-threading-right-with-diffutil-423378e126d2

बस समाधान की व्याख्या करने के लिए अद्यतनों को धक्का देना है, जबकि वर्तमान एक Deque पर चल रहा है। वर्तमान में एक बार समाप्त होने के बाद, फिर लंबित अपडेट चला सकता है, इसलिए बाद के सभी अपडेट को संभाल सकता है, लेकिन असंगतता से भी बचा सकता है!

आशा है कि यह मदद करता है क्योंकि यह मुझे मेरे सिर खरोंच कर दिया!


लिंक के लिए धन्यवाद!
कूलमाइंड

3

मेरे लिए केवल तब समस्या आई:

मैंने एक खाली सूची के साथ एडॉप्टर बनाया । फिर मैंने आइटम डाले और कॉल किया notifyItemRangeInserted

उपाय:

मैंने इसे एडॉप्टर बनाने के बाद ही हल किया, क्योंकि मेरे पास डेटा का पहला हिस्सा है और इसे तुरंत शुरू करना है। अगला हिस्सा फिर डाला जा सकता है और notifyItemRangeInsertedबिना किसी समस्या के बुलाया जा सकता है।


मुझे नहीं लगता कि यह कारण है। मेरे पास खाली सूचियों के साथ कई एडेप्टर हैं, फिर आइटम को इसके साथ जोड़ा notifyItemRangeInserted, लेकिन वहां कभी भी इसका अपवाद नहीं था।
कूलमाइंड

3

मेरी समस्या यह थी कि भले ही मैंने रिसाइकलर दृश्य के लिए डेटा मॉडल युक्त दोनों सरणी सूची को साफ़ कर दिया था, लेकिन मैंने उस बदलाव के एडाप्टर को सूचित नहीं किया था, इसलिए इसमें पिछले मॉडल से बासी डेटा था। जिसके कारण व्यू होल्डर की स्थिति को लेकर भ्रम पैदा हो गया। इसे ठीक करने के लिए हमेशा एडेप्टर को सूचित करें कि डेटा-सेट जैसा कि फिर से अपडेट करने से पहले बदल गया है।


या इसके बजाय यदि आइटम को हटा दिया जाता है तो सूचित करें
रेमरियो

मेरा मॉडल कंटेनर के संदर्भ का उपयोग करता है कि क्यों
रेमरियो

3

मेरे मामले में मैं पहले mRecyclerView.post (नया Runnable ...) के साथ एक थ्रेड के अंदर डेटा बदल रहा था और फिर बाद में यूआई थ्रेड में डेटा बदल दिया, जिससे असंगति हुई।


1
मेरे पास आपके जैसी ही स्थिति है, आपने इसे कैसे हल किया? धन्यवाद
baderkhane

2

त्रुटि आपके परिवर्तनों के कारण हो सकती है जो आप सूचित कर रहे हैं। मेरे मामले में:

myList.set(position, newItem);
notifyItemInserted(position);

मुझे क्या करना था:

myList.add(position, newItem);
notifyItemInserted(position);

2

मेरे मामले में समस्या यह थी कि जब नए लोड किए गए डेटा की मात्रा प्रारंभिक डेटा से कम थी, तो मैंने InformDataSetChanged का उपयोग किया था। इस दृष्टिकोण ने मेरी मदद की:

adapter.notifyItemRangeChanged(0, newAmountOfData + 1);
adapter.notifyItemRangeRemoved(newAmountOfData + 1, previousAmountOfData);

notifyDataSetChangedनए डेटा पर क्यों निर्भर करता है मुझे लगा कि यह पूरी सूची को ताज़ा कर देगा।
CoolMind

2

मैं एक समस्या मे फंस गया।

मेरा ऐप मेरे पुनर्नवीनीकरण दृश्य वाले एक खंड के साथ नेविगेशन घटकों का उपयोग करता है। मेरी सूची ने ठीक दिखाया कि पहली बार टुकड़ा लोड किया गया था ... लेकिन दूर नेविगेट करने और वापस आने पर यह त्रुटि हुई।

जब दूर के जीवनचक्र को नेविगेट करना केवल onDestroyView के माध्यम से चला गया और वापस लौटने पर यह onCreateView पर शुरू हुआ। हालांकि, मेरे एडॉप्टर को टुकड़े के ऑनक्रिएट में इनिशियलाइज़ किया गया था और वापस लौटने पर रीइंस्ट्रिक्ट नहीं किया।

फिक्स ऑनक्रिएट व्यू में एडेप्टर को इनिशियलाइज़ करना था।

आशा है कि यह किसी की मदद कर सकता है।


0

मुझे यह त्रुटि मिली क्योंकि मैं गलती से कई बार अपने रिसाइक्लेव्यू से एक विशिष्ट पंक्ति को हटाने के लिए एक विधि कह रहा था। मेरे पास एक तरीका था:

void removeFriends() {
    final int loc = data.indexOf(friendsView);
    data.remove(friendsView);
    notifyItemRemoved(loc);
}

मैं गलती से इस पद्धति को एक बार के बजाय तीन बार कॉल कर रहा था, इसलिए दूसरी बार loc-1 था और इसे हटाने की कोशिश करने पर त्रुटि दी गई थी। यह सुनिश्चित करने के लिए दो फ़िक्सेस थे कि विधि केवल एक बार बुलाई गई थी, और इस तरह से एक स्वच्छता जांच को जोड़ने के लिए:

void removeFriends() {
    final int loc = data.indexOf(friendsView);
    if (loc > -1) {
        data.remove(friendsView);
        notifyItemRemoved(loc);
    }
}

0

मुझे भी यही समस्या हुई और मैंने पढ़ा है कि यह सैमसंग फोन में ही हुआ था ... लेकिन वास्तविकता से पता चला है कि यह बहुत सारे ब्रांडों में होता है।

परीक्षण के बाद मुझे एहसास हुआ कि यह केवल तब होता है जब आप RecyclerView को तेजी से स्क्रॉल करते हैं और फिर आप बैक बटन या अप बटन के साथ वापस जाते हैं। तो मैं ऊपर बटन के अंदर डाल दिया और नीचे स्निपेट दबा दिया:

someList = new ArrayList<>();
mainRecyclerViewAdapter = new MainRecyclerViewAdapter(this, someList, this);
recyclerViewMain.setAdapter(mainRecyclerViewAdapter);
finish();

इस समाधान के साथ आप एडेप्टर के लिए एक नया Arraylist और recyclerView के लिए नया एडॉप्टर लोड करते हैं और फिर आप गतिविधि समाप्त करते हैं।

आशा है कि यह किसी की मदद करता है


0

मुझे यह त्रुटि मिली क्योंकि मैं गलती से दो बार "InformItemInserted" कह रहा था।


0

मेरे मामले में मेरे पास सूची में 5000 से अधिक आइटम हैं। मेरी समस्या यह थी कि जब पुनर्नवीनीकरण दृश्य को स्क्रॉल किया जाता है, तो कभी-कभी "myBustomAddItems" पद्धति को "onBindViewHolder" कहा जाता है, जो सूची को बदल रहा है।

मेरा समाधान डेटा सूची में परिवर्तन करने वाली सभी विधियों में "सिंक्रनाइज़ (सिंकऑब्जेक्ट) {}" को जोड़ना था। किसी भी समय इस तरह से केवल एक ही विधि इस सूची को पढ़ सकती है।


0

मेरे मामले में, एडॉप्टर डेटा बदल गया। और मैं गलत तरीके से इन परिवर्तनों के लिए InformItemInserted () का उपयोग कर रहा था। जब मैं InformItemChanged का उपयोग करता हूं, तो त्रुटि दूर हो गई है।


0

मैं उसी समस्या में भाग गया जब मैंने सूची में दोनों हटाए और अपडेट किए गए आइटम हैं ... जांच के दिनों के बाद मुझे लगता है कि मुझे आखिरकार एक समाधान मिला।

आपको जो करने की आवश्यकता है वह पहले notifyItemChangedअपनी सभी सूची में करें और उसके बाद ही सभी को notifyItemRemoved एक अवरोही क्रम में करें

मुझे उम्मीद है कि यह उन लोगों की मदद करेगा जो एक ही मुद्दे में चल रहे हैं ...


0

मैं एक कर्सर का उपयोग कर रहा हूं, इसलिए मैं डिफ्यूटल का उपयोग नहीं कर सकता जैसा कि लोकप्रिय उत्तरों में प्रस्तावित है। मेरे लिए यह काम करने के लिए मैं सूची को निष्क्रिय नहीं होने पर एनिमेशन को अक्षम कर रहा हूं। यह एक्सटेंशन है जो इस समस्या को हल करता है:

 fun RecyclerView.executeSafely(func : () -> Unit) {
        if (scrollState != RecyclerView.SCROLL_STATE_IDLE) {
            val animator = itemAnimator
            itemAnimator = null
            func()
            itemAnimator = animator
        } else {
            func()
        }
    }

फिर आप अपने एडॉप्टर को उसी तरह अपडेट कर सकते हैं

list.executeSafely {
  adapter.updateICursor(newCursor)
}

0

यदि समस्या मल्टी टच के बाद होती है तो आप मल्टी टच को अक्षम कर सकते हैं

android:splitMotionEvents="false" 

लेआउट फ़ाइल में।


-1

यदि आपका डेटा बहुत बदल जाता है, तो आप उपयोग कर सकते हैं

 mAdapter.notifyItemRangeChanged(0, yourData.size());

या आपके डेटा सेट में कुछ एकल आइटम परिवर्तन करते हैं, आपका उपयोग कर सकते हैं

 mAdapter.notifyItemChanged(pos);

विस्तृत तरीकों के उपयोग के लिए, आप एक तरह से डॉक्टर को संदर्भित कर सकते हैं , सीधे उपयोग न करने का प्रयास करें mAdapter.notifyDataSetChanged()


2
का उपयोग करके notifyItemRangeChangedभी एक ही दुर्घटना का उत्पादन करता है।
सिंहलम्सी

यह कुछ स्थिति के अनुकूल है। हो सकता है कि आपने बैकग्राउंड थ्रेड और UI थ्रेड दोनों में अपने डेटासेट को अपडेट किया हो, इससे असंगति भी होगी। यदि आप केवल UI थ्रेड में डेटासेट अपडेट करते हैं, तो यह काम करेगा।
एरोन काओ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.