রিসাইক্লারভিউ এবং জাভা.এলং.আইডেক্সআউটআউটফাউন্ডস এক্সেকশন: অসঙ্গতি ধরা পড়ে। স্যামসাং ডিভাইসে অবৈধ দর্শন ধারক অ্যাডাপ্টারের অবস্থানভিউহোল্ডার


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 কার্য শুরু করেছিলাম, এবং যখন তাদের মধ্যে একটির আগে অন্যটি ব্যবহারকারীর স্ক্রোল নেমে যায় এবং এর মধ্যে অন্য একটি সম্পূর্ণ এবং আপডেট অ্যাডাপ্টারের ব্যবহারকারী এমন ব্যতিক্রম পেতে পারে কারণ দ্বিতীয় টাস্কের পরিমাণ কম পরিমাণে ফিরে আসে
ভাসিফ

উত্তর:


195

এই সমস্যাটি RecyclerViewবিভিন্ন থ্রেডে ডেটা পরিবর্তিত হয়ে থাকে। সর্বোত্তম উপায় হ'ল সমস্ত ডেটা অ্যাক্সেস পরীক্ষা করা। এবং একটি workaround মোড়ানো হয় LinearLayoutManager

পূর্ববর্তী উত্তর

রিসাইক্লিউউতে আসলে একটি বাগ ছিল এবং সমর্থন 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
কোড.google.com/p/android/issues/detail?id=158046 উত্তর # 12 বলেছে এটি করবেন না।
রবার্ট

উম্মম, আপনি ঠিক বলেছেন। আমার অ্যাপ্লিকেশনটিতে সমস্ত সম্ভাব্য অ-ইউআই-থ্রেড সংশোধনগুলি হ্রাস করা কঠিন বলে মনে হচ্ছে, আমি এটিকে কেবলমাত্র এক কার্যকরী উপায় হিসাবে রাখব।
সাকিএম

1
আমার ক্ষেত্রে আমি একই থ্রেডে করছি doing । mDataHolder.get () removeAll (mHiddenGenre); mAdapter.notifyItemRangeRemoved (mExpandButtonPosition, mHmittedGenre.size ());
জেহান্দকে

73

সম্পূর্ণ নতুন সামগ্রী সহ তথ্য সতেজ করার জন্য এটি একটি উদাহরণ। আপনার প্রয়োজন অনুসারে আপনি এটি সহজেই সংশোধন করতে পারেন। আমি আমার মামলায় এটি কল করে সমাধান করেছি:

notifyItemRangeRemoved(0, previousContentSize);

আগে:

notifyItemRangeInserted(0, newContentSize);

এটি সঠিক সমাধান এবং এওএসপি প্রকল্পের কোনও সদস্য এই পোস্টে উল্লেখ করেছেন ।


2
এই সমাধানটি আমার পক্ষে কাজ করে আমি এখানে প্রচুর জবাব দিয়েছি কিন্তু সেগুলি কাজ করে না (আমি প্রথম সমাধানের তৌগ পরীক্ষা করিনি)
AndroLife

সমস্যাগুলি এই পদ্ধতিগুলি ব্যবহার করে সেই একই অসঙ্গতি তৈরি করে, এমনকি একই থ্রেডে সম্পন্ন করার পরেও।
জেহান্দকে

আমি notifyItemRangeInsertedকিছু স্যামসাং ডিভাইস নিয়ে এই সমস্যাটি ব্যবহার করি না এবং
রাখি

এবং বেশ অফ-বিষয় এখানে। লেখক ব্যবহার করেননিnotifyItemRangeInserted
ব্যবহারকারী 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
লিনিয়ারলআউটম্যানেজার পদ্ধতির বেস ক্লাস প্রেডিকটিভ অ্যানিমেশনস () এর ডিফল্টরূপে মিথ্যা ফিরিয়ে দেয়। আমরা এখানে পদ্ধতিটি ওভাররাইড করে কী পাচ্ছি? public boolean supportsPredictiveItemAnimations() { return false; }
এম হিগ

1
@ এম.এইচআইজি এর জন্য ডকুমেন্টেশন LinearLayoutManagerবলছে ডিফল্টটি মিথ্যা, তবে উক্ত বিবৃতিটি মিথ্যা :-( এর জন্য LinearLayoutManagerবিবর্তিত কোডটি রয়েছে: পাবলিক বুলিয়ান সমর্থন করে প্রিডিকটিভ আইটেম অ্যানিমেশনস () {এটিকে ফেরান P ;}
ক্লাইড

আমি আমার পুনর্ব্যবহারযোগ্য ভিউ অ্যাডাপ্টার আপডেট করার জন্য বিভিন্ন ব্যবহার করি এবং এই উত্তরটি একটি ক্র্যাশ স্থির করে। অনেক অনেক ধন্যবাদ প্রিয় লেখক!
ইউজিন পি।

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
এটি একটি ভাল ব্যাখ্যা সহ সর্বাধিক সম্পূর্ণ সমাধান। ধন্যবাদ!
সাকিবয়

তারপরে নোটিফাইটটাইজেটঞ্জেনড (), @ বলিংয়ের পরিবর্তে notifyitemrangeinsert ব্যবহারের উদ্দেশ্য কী।
অঙ্কুর_009

@ ফিলিপলুচ আপনি কি ব্যাখ্যা করতে পারেন কেন?
শ্রীকান্ত করুণাঘাট

3
@ শ্রীকান্ত কারুমানঘাট নিশ্চিত, কেন কারণ আমি তার কারণ ব্যাখ্যা করিনি। মূলত তিনি সাফ করেন তারপরে তালিকার সমস্ত জিনিস পুনরায় তৈরি করুন। অনুসন্ধানের ফলাফলগুলির মতো, প্রায়শই আপনি একই আইটেমগুলি পান বা রিফ্রেশ সম্পন্ন করার পরে আপনি একই আইটেমগুলি পান এবং তারপরে আপনি সবকিছু পুনরুদ্ধার করে শেষ করবেন যা কার্য সম্পাদনের অপচয়। পরিবর্তে ডিফুটিলগুলি ব্যবহার করুন এবং সমস্ত আইটেমের পরিবর্তে পরিবর্তনগুলি আপডেট করুন। এটি প্রতিবার A থেকে Z তে যাওয়ার মতো, তবে আপনি কেবল সেখানে F পরিবর্তন করেছেন changed
ফিলিপ লুচিয়েনকো

2
ডিফুটিল একটি গোপন ধন। ভাগ করে নেওয়ার জন্য ধন্যবাদ!
সিলেরিয়া

22

কারণএই সমস্যাটির :

  1. আইটেম অ্যানিমেশন সক্ষম করা হয় যখন পুনর্ব্যবহারকারী একটি অভ্যন্তরীণ সমস্যা
  2. অন্য থ্রেডে পুনর্ব্যবহারযোগ্য ডেটাতে পরিবর্তন
  3. পদ্ধতিগুলিকে ভুল উপায়ে কল করা

সমাধান:

----------------- সমাধান 1 ---------------

  • ব্যতিক্রম ধরা (বিশেষত # 3 কারণে প্রস্তাবিত নয়)

নিম্নলিখিত হিসাবে একটি কাস্টম লিনিয়ারলআউটআউট ম্যানেজার তৈরি করুন এবং এটিকে রেসক্লারভিউতে সেট করুন

    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.setLayoutManager(new CustomLinearLayoutManager(activity));

----------------- সমাধান 2 ---------------

  • আইটেম অ্যানিমেশনগুলি অক্ষম করুন (যদি এটি # 1 এর কারণ হিসাবে সমস্যাটি সমাধান করে):

আবার, নিম্নলিখিত হিসাবে একটি কাস্টম লিনিয়ার লেআউট ম্যানেজার তৈরি করুন:

    public class CustomLinearLayoutManager extends LinearLayoutManager {

            //Generate constructors

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

তারপরে রাইসকলিভিউ লেআউট ম্যানেজারটিকে নিম্নলিখিত হিসাবে সেট করুন:

recyclerView.setLayoutManager(new CustomLinearLayoutManager(activity));

----------------- সমাধান 3 ---------------

  • এই সমাধানটি # 3 কারণে কারণে সমস্যাটি সমাধান করে। আপনাকে নিশ্চিত করতে হবে যে আপনি সঠিক পদ্ধতিতে বিজ্ঞপ্তি পদ্ধতি ব্যবহার করছেন। বিকল্পভাবে, স্মার্ট, সহজ এবং মসৃণ উপায়ে পরিবর্তনটি পরিচালনা করতে ডিফুটিল ব্যবহার করুন। অ্যান্ড্রয়েড রিসাইকেলার ভিউতে ডিফুটিল ব্যবহার করে

----------------- সমাধান 4 ---------------

  • # 2 কারণে, আপনাকে পুনর্ব্যবহারযোগ্য তালিকার সমস্ত ডেটা অ্যাক্সেস পরীক্ষা করে পরীক্ষা করে দেখতে হবে যে অন্য থ্রেডে কোনও পরিবর্তন নেই ification

এটি আমার দৃশ্যে কাজ করেছে, আমি ডিফুটিল ব্যবহার করতে পারছি না কারণ আমার রিসাইক্লার এবং অ্যাডাপ্টারের জন্য কাস্টম উপাদান রয়েছে এবং ত্রুটিটি নির্দিষ্ট পরিস্থিতিতে দেখা যায় যা জানা যায়, আইটেম অ্যানিমেটারগুলি অপসারণের অবলম্বন ছাড়া আমার কেবল এটি প্যাচ করা দরকার, তাই আমি কেবল এটিকে একটি চেষ্টা করে
জড়িয়ে দিন

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যদিও ব্যবহার করতে পারি না ।
ওয়াসিফখত্তর

15

এই ইস্যু অনুসারে , সমস্যাটি সমাধান করা হয়েছে এবং সম্ভবত ২০১৫ এর শুরুতে কিছুটা সময় মুক্তি দেওয়া হয়েছিল that একই থ্রেডের একটি উদ্ধৃতি :

এটি বিশেষত notifyDataSetChanged কল করার সাথে সম্পর্কিত। [...]

বিটিডব্লিউ, আমি জোরালোভাবে notifyDataSetChanged ব্যবহার না করার পরামর্শ দিচ্ছি কারণ এটি অ্যানিমেশন এবং পারফরম্যান্সকে হত্যা করে। এছাড়াও এই ক্ষেত্রে, নির্দিষ্ট বিজ্ঞপ্তি ইভেন্টগুলি ব্যবহার করা সমস্যার সমাধান করবে।

যদি আপনার এখনও সমর্থন লাইব্রেরির সাম্প্রতিক সংস্করণ নিয়ে সমস্যা হয় , তবে আপনি (কিছুটা নাজুক / অস্পষ্ট) চুক্তি মানছেন কিনা তা নিশ্চিত করার জন্য আমি আপনার অ্যাডাপ্টারের অভ্যন্তরে আপনার কলগুলি notifyXXX(বিশেষত আপনার ব্যবহার notifyDataSetChanged) পর্যালোচনা করার পরামর্শ দেব RecyclerView.Adapter। এছাড়াও মূল থ্রেডে এই বিজ্ঞপ্তিগুলি জারি করতে ভুলবেন না।


16
প্রকৃতপক্ষে নয়, আমি পারফরম্যান্স সম্পর্কে আপনার অংশের সাথে একমত আছি তবে notifyDataSetChanged () অ্যানিমেশনগুলিকে হত্যা করে না, notifyDataSetChanged () ব্যবহার করে অ্যানিমেটেড করতে, আপনার রিসাইক্লার ভিউ-অ্যাডাপ্টার অবজেক্টে সেট সেট হ্যাশস্টেবলআইডস (সত্য) কল করুন এবং বি) আপনার অ্যাডাপ্টারের অভ্যন্তরে getItemId এ ফিরে আসুন প্রতিটি সারিটির জন্য স্বতন্ত্র দীর্ঘ মূল্য এবং এটি পরীক্ষা করে দেখুন, অ্যানিমেশনগুলি কাজ করে
পাইরেটএপ

@ পাইরেট অ্যাপ আপনার উত্তরটি হিসাবে আপনার মন্তব্য করা বিবেচনা করা উচিত। আমি এটি চেষ্টা করেছি এবং এটি ঠিকঠাক কাজ করছে।
এমআর 5

সত্য না! এখনও এই সমস্যা সম্পর্কে গুগল কনসোল থেকে প্রতিবেদন পান। এবং ডিভাইসটি অবশ্যই স্যামসাং -Samsung Galaxy J3(2017) (j3y17lte), Android 8.0
ব্যবহারকারী 25

10

আমারও একই সমস্যা ছিল। আইটেম সন্নিবেশ সম্পর্কে অ্যাডাপ্টারের জন্য বিজ্ঞপ্তিটি বিলম্ব করার কারণে এটি হয়েছিল।

তবে ViewHolderএর দৃষ্টিভঙ্গিতে কিছু ডেটা পুনরায় আঁকতে চেষ্টা করা হয়েছে এবং এটি RecyclerViewবাচ্চাদের গণনা পরিমাপ ও পুনর্নির্মাণের সূচনা করেছে - এই মুহুর্তে এটি ক্র্যাশ হয়ে গেছে (আইটেমের তালিকা এবং এর আকারটি ইতিমধ্যে আপডেট করা হয়েছিল, তবে অ্যাডাপ্টারটি এখনও অবহিত হয়নি)।


8

আপনি যখন notifyItemChanged, notifyItemRangeInsert ইত্যাদির জন্য ভুল অবস্থান নির্দিষ্ট করে থাকেন তখন এটি ঘটে:

আগে: (ভুল)

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আকার। সুতরাং, আপনার দুটি রূপই ভুল।
কুলমাইন্ড

আমার জন্য এটি কাজ করে notifyItemRangeInserted(initialSize, list.size()-1);তবে আমি তা পাই না। আইটেমকাউন্টের জন্য আমাকে কেন sizeোকানো আকারকে হ্রাস করতে হবে?
প্লেক্সাস

7

এই সমস্যাটি হওয়ার আরেকটি কারণ হ'ল আপনি যখন এই পদ্ধতিগুলিকে ভুল সূচকগুলি দিয়ে কল করেন (যে সূচিগুলি সন্নিবেশ করানো হয়নি বা সেগুলিতে সরিয়ে নেই)

-notifyItemRangeRemoved

-notifyItemRemoved

-notifyItemRangeInserted

-notifyItemInserted

এই পদ্ধতিগুলিতে সূচকের পরামিতিগুলি পরীক্ষা করুন এবং নিশ্চিত করুন যে সেগুলি সঠিক এবং সঠিক are


2
এটা আমার সমস্যা ছিল। তালিকায় কিছুই যুক্ত না করে ব্যতিক্রম ঘটে।
রাসেল

6

এই ত্রুটিটি এখনও 23.1.1 এ স্থির করা হয়নি তবে ব্যতিক্রমটি ধরা পড়ার জন্য একটি সাধারণ কাজ হবে।


18
এটা ধরো কোথায়? স্ট্যাক ট্রেসের একমাত্র কোডটি দেশীয় অ্যান্ড্রয়েড কোড।
হোয়েটল

1
@ সাকি_এম উত্তরের মতো এটি ধরুন।
রেনান বান্দেরা

রেনান যদিও এটি আপনার পক্ষে আসলে কাজ করে? আপনি কিছুক্ষণের জন্য স্থির পরীক্ষা করেছেন? বাগটি মাঝে মধ্যেই ঘটে থাকে তাই আমি কেবলমাত্র এটি দেখতে পাই এটি সময়ের সাথে কাজ করে কিনা।
সাইমন

এটি আসলে কাজ করে তবে আমার কিছু শিশু দৃষ্টিভঙ্গি অবিচ্ছিন্নভাবে রয়ে যায়।
ডেভিড

@ ডেভিড অবিচ্ছিন্নভাবে রয়ে গেছে এর পরিণতি কী হবে?
শ্রীকান্ত করুণাঘাট

4

এই সমস্যাটি বিভিন্ন থ্রেডে রিসাইক্লারভিউ ডেটা সংশোধিত হওয়ার কারণে ঘটে

থ্রেডিংটিকে একটি সমস্যা হিসাবে নিশ্চিত করতে পারি এবং যেহেতু আমি ইস্যুটিতে চলে এসেছি এবং আরএক্সজাভা ক্রমশ জনপ্রিয় হয়ে উঠছে: নিশ্চিত হন যে আপনি .observeOn(AndroidSchedulers.mainThread())যখনই ফোন করছেন তখনই আপনি ব্যবহার করছেনnotify[whatever changed]

অ্যাডাপ্টারের কোড উদাহরণ:

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

    [...]

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

আমি ডিফফটিলক্যালকুলেটডিফকে কল করার সময় মূল থ্রেডে আছি (ডিফুয়েলফোরকাস্টি আইটেমচ্যাঞ্জস এ্যানলেসার (এটি। এমওয়েদারফোরাক্যাটস আইটেম উইথমাইনঅ্যান্ড উইথারস, ওয়েদারফোরকাস্ট আইটেমস))। ডিসপ্যাচআপডেটসটো (এটি); লগটি স্পষ্টভাবে প্রকাশিত হয়েছে: থ্রেড [মূল, 5, প্রধান]
ম্যাথিয়াস সেগুয়ে Android2ee

4

আমার ক্ষেত্রে প্রতিবার যখন আমি notifIteTRemoved (0) কল করি তখন এটি ক্র্যাশ হয়ে যায়। আমি সেট করেছিলাম setHasStableIds(true)এবং getItemIdআমি এই আইটেমের অবস্থানটি ফিরে এসেছি। আমি আইটেমটির hashCode()বা স্ব-সংজ্ঞায়িত অনন্য আইডি ফিরিয়ে আনার জন্য এটি আপডেট করে শেষ করেছি , যা সমস্যার সমাধান করেছে।


4

আমার ক্ষেত্রে, সার্ভার থেকে ডেটা আপডেট পাওয়ার কারণে আমি এই সমস্যাটি পেয়েছিলাম (আমি ফায়ারবেস ফায়ারস্টোর ব্যবহার করছি) এবং যখন পটভূমিতে প্রথম সেট ডেফ ডিফুটিল দ্বারা প্রক্রিয়া করা হচ্ছে, তখন ডেটা আপডেটের আরও একটি সেট আসে এবং তাতে সম্মতিযুক্ত সমস্যার কারণ হয় অন্য একটি ডিফুটিল শুরু করে।

সংক্ষেপে, আপনি যদি ব্যাকগ্রাউন্ড থ্রেডে ডিফুটিল ব্যবহার করছেন যা পরে রিসেলারভিউতে ফলাফল প্রেরণের জন্য মেইন থ্রেডে ফিরে আসে, তবে একাধিক ডেটা আপডেট স্বল্প সময়ের মধ্যে এলে আপনি এই ত্রুটিটি পাওয়ার সম্ভাবনাটি চালান।

আমি এই দুর্দান্ত ব্যাখ্যাটিতে পরামর্শ অনুসরণ করে এটি সমাধান করেছি: https://medium.com/@jonfhancock/get-threading-right-with-diffutil-423378e126d2

সলিউশনটির ব্যাখ্যা দেওয়ার জন্য হ'ল বর্তমানটি যখন কোনও ডেকের দিকে চলছে তখন আপডেটগুলি ধাক্কা দেওয়া। ডিকটি তার পরে বর্তমানের সমাপ্তির পরে মুলতুবি থাকা আপডেটগুলি চালাতে পারে, অতএব পরবর্তী সমস্ত আপডেটগুলি পরিচালনা করে তবে অসামঞ্জস্যতা ত্রুটিগুলি এড়ানোও!

আশা করি এটি সাহায্য করবে কারণ এটি আমাকে আমার মাথা আঁচড়ান!


লিঙ্কের জন্য ধন্যবাদ!
কুলমাইন্ড

3

আমার তখনই সমস্যা হয়েছিল যখন:

আমি একটি খালি তালিকা দিয়ে অ্যাডাপ্টার তৈরি করেছি । তারপরে আমি আইটেম andুকিয়ে ডাকলাম notifyItemRangeInserted

সমাধান:

আমি এডাপ্টার তৈরি করে সমাধান করেছি কেবলমাত্র আমার কাছে প্রথম অংশের ডেটা রয়েছে এবং এখনই এটির সাথে এটি শুরু করে। পরবর্তী অংশটি sertedোকানো এবং notifyItemRangeInsertedকোনও সমস্যা ছাড়াই কল করা যেতে পারে ।


আমি মনে করি না কারণ এটি। আমার খালি তালিকার সাথে অনেকগুলি অ্যাডাপ্টার রয়েছে, তারপরে আইটেম যুক্ত হয়েছে notifyItemRangeInsertedতবে সেখানে কখনও এই ব্যতিক্রম হয়নি।
কুলমাইন্ড

3

আমার সমস্যাটি ছিল যে আমি পুনর্ব্যবহারযোগ্য দৃশ্যের জন্য ডেটা মডেলযুক্ত অ্যারে তালিকা উভয়টি সাফ করে দিলেও, আমি সেই পরিবর্তনের অ্যাডাপ্টারকে অবহিত করিনি, সুতরাং এতে পূর্ববর্তী মডেল থেকে বাসি ডেটা ছিল। যা দর্শকের অবস্থান সম্পর্কিত অবস্থান নিয়ে বিভ্রান্তির সৃষ্টি করে। এটি ঠিক করার জন্য সর্বদা অ্যাডাপ্টারকে অবহিত করুন যে ডেটা-সেটটি আবার আপডেট করার আগে পরিবর্তিত হয়েছে।


অথবা পরিবর্তে আইটেমটি সরানো থাকলে অবহিত করুন
রেমারিও

আমার মডেল কেন ধারক রেফারেন্স ব্যবহার করে তা
রেমারিও

3

আমার ক্ষেত্রে আমি mRecyclerView.post (নতুন রান্নেবল ...) দিয়ে একটি থ্রেডের অভ্যন্তরে ডেটা পরিবর্তন করছিলাম এবং পরে আবার ইউআই থ্রেডে ডেটা পরিবর্তন করেছি, যার ফলে অসঙ্গতি হয়েছিল caused


1
আপনার মতো অবস্থাও আমার, আপনারা কীভাবে সমাধান করেছেন? ধন্যবাদ
বদরখান

2

ত্রুটিটি আপনার পরিবর্তনগুলি যেটি আপনি জানিয়ে দিচ্ছেন তার সাথে সামঞ্জস্যপূর্ণ না হওয়ার কারণে ঘটতে পারে। আমার ক্ষেত্রে:

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

আমার অবশ্যই করণীয় ছিল:

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

2

আমার ক্ষেত্রে সমস্যাটি ছিল যে যখন সদ্য লোড হওয়া ডেটার পরিমাণ প্রাথমিক উপাত্তের তুলনায় কম থাকে তখন আমি নোটডেটসেট চেঞ্জড ব্যবহার করি। এই পদ্ধতির সাহায্য আমাকে:

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

notifyDataSetChangedনতুন ডেটা নির্ভর করে কেন ? আমি ভেবেছিলাম এটি পুরো তালিকাটি রিফ্রেশ করবে।
কুলমাইন্ড

2

আমি একই সমস্যা মধ্যে দৌড়ে।

আমার অ্যাপ্লিকেশনটি আমার পুনর্ব্যবহারযোগ্য ভিউযুক্ত একটি খণ্ড সহ নেভিগেশন উপাদানগুলি ব্যবহার করে। আমার তালিকাটি প্রথমবার টুকরোটি লোড হওয়ার সময় সূক্ষ্মভাবে প্রদর্শিত হয়েছিল ... তবে নেভিগেট করে এবং ফিরে এসে এই ত্রুটি ঘটেছে।

ভগ্নাংশের জীবনচক্রটি নেভিগেট করার সময় কেবলমাত্র ড্রেড্রয়েভিউয়ের মধ্য দিয়ে গিয়েছিল এবং ফিরে আসার পরে এটি অনক্রিটভিউতে শুরু হয়েছিল। যাইহোক, আমার অ্যাডাপ্টারটি খণ্ডের অনক্রিটে আরম্ভ হয়েছিল এবং ফিরে আসার সময় পুনরায় পুনর্নির্মাণ করা হয়নি।

ফিক্সটি অনক্রিটভিউতে অ্যাডাপ্টারটি শুরু করার ছিল।

আশা করি এটি কারও সাহায্য করবে।


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

আমি একই সমস্যা পেয়েছি এবং আমি পড়েছি যে কেবল স্যামসাং ফোনে এটি ঘটেছিল ... তবে বাস্তবতা দেখায় যে এটি অনেক ব্র্যান্ডে ঘটে।

পরীক্ষার পরে আমি বুঝতে পারি যে এটি কেবল তখনই ঘটে যখন আপনি দ্রুত পুনর্ব্যবহারযোগ্য ভিউ স্ক্রোল করেন এবং তারপরে আপনি পিছনে বাটন বা আপ বোতামটি দিয়ে ফিরে যান। সুতরাং আমি উপরের বোতামটি ভিতরে রেখে নীচে স্নিপেটে অনব্যাকড করেছি:

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

এই সমাধানের সাহায্যে আপনি কেবল অ্যাডাপ্টারে একটি নতুন অ্যারেলিস্ট এবং রিসাইকেলারভিউতে নতুন অ্যাডাপ্টার লোড করুন এবং তারপরে আপনি ক্রিয়াকলাপ শেষ করেন।

আশা করি এটি কাউকে সাহায্য করবে


0

আমি এই ত্রুটিটি পেয়েছি কারণ আমি ভুল করে দু'বার "notifyItemInsert" কল করছিলাম।


0

আমার ক্ষেত্রে তালিকায় আমার 5000 টিরও বেশি আইটেম রয়েছে। আমার সমস্যাটি ছিল যে পুনর্ব্যবহারযোগ্য ভিউ স্ক্রোল করার সময়, "মাই কাস্টম অ্যাড আইটেমস" পদ্ধতিটি তালিকায় পরিবর্তন আনার সময় কখনও কখনও "অনব্যান্ডভিউহোল্ডার" কল করা হয়।

আমার সমাধানটি হ'ল তথ্য তালিকার পরিবর্তনকারী সমস্ত পদ্ধতিতে "সিঙ্ক্রোনাইজড (সিঙ্কঅবজেক্ট) {}" যুক্ত করা। এই সময়ে যে কোনও সময়ে কেবল একটি পদ্ধতি এই তালিকাটি পড়তে পারে।


0

আমার ক্ষেত্রে, অ্যাডাপ্টারের ডেটা পরিবর্তিত হয়েছে। এবং আমি এই পরিবর্তনগুলির জন্য ভুলভাবে notifyItemInsert () ব্যবহার করেছি। আমি যখন notifIteChanged ব্যবহার করি তখন ত্রুটিটি চলে যায়।


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একই ক্রাশ উত্পাদন করে।
সিংহেলমেসি

এটি কিছু পরিস্থিতির জন্য উপযুক্ত। হতে পারে আপনি আপনার ডেটাसेटটি ব্যাকগ্রাউন্ড থ্রেড এবং ইউআই থ্রেড উভয় ক্ষেত্রেই আপডেট করেছেন, এটিও অসঙ্গতি সৃষ্টি করবে। আপনি যদি কেবলমাত্র ইউআই থ্রেডে ডেটাসেট আপডেট করেন তবে এটি কার্যকর হবে।
অ্যারন কও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.