滚动到下一页时单击时出错

Getting Error On Click When Scrolled To Next Page

我已成功获取 posts,在前 10 posts,我也获取了 post 内容,但是当我向下滚动以加载更多 posts 时,我也可以看到带有特色图片的 posts,但是当我点击那些 posts 时,我得到了这个错误:现在距离我找到答案已经超过 2 周了,请帮助

 Caused by: java.lang.IndexOutOfBoundsException: Index: 11, Size: 10
        at java.util.ArrayList.get(ArrayList.java:437)
        at com.punjabidharti.myapplication.PostDetails.onCreate(PostDetails.java:30)

这是我的帖子详情activity:

 Intent i = getIntent();
    int position = i.getExtras().getInt("itemPosition");

    Log.e("PostDetails ", "title is " + MainActivity.mListPost.get(position).getTitle().getRendered());

    this.title = (TextView) findViewById(R.id.title);

    title.setText(Html.fromHtml(MainActivity.mListPost.get(position).getTitle().getRendered()));



    String data = String.valueOf((Html.fromHtml(MainActivity.mListPost.get(position).getContent().getRendered())));

    WebView webview = (WebView)this.findViewById(R.id.postwebview);
    webview.getSettings().setJavaScriptEnabled(true);
    webview.loadData(data, "text/html; charset=utf-8", "UTF-8");

这是适配器:

 private ArrayList<Model> dataset;
private Context mContext;
int total_types;





public RecyclerViewAdapter(ArrayList<Model> mlist, Context context) {
    this.dataset = mlist;
    this.mContext = context;
    total_types = dataset.size();
}

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



public static class ImageTypeViewHolder extends RecyclerView.ViewHolder{


    TextView title, subtitle;
    ImageView imageView;


    public ImageTypeViewHolder(View itemView) {
        super(itemView);

        this.title = (TextView)  itemView.findViewById(R.id.title);
        this.subtitle = (TextView) itemView.findViewById(R.id.subtitle);
        //at the moment, it is displaying an icon for all posts
        this.imageView = (ImageView) itemView.findViewById(R.id.Icon);
    }
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from( parent.getContext()).inflate(R.layout.postdetails, parent, false);
    return new ImageTypeViewHolder(view) ;
}



@Override
public int getItemViewType(int position) {

    return position;
}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
    final Model object = dataset.get(position);

    ( (ImageTypeViewHolder) holder).title.setText( object.title );
    ( (ImageTypeViewHolder) holder).subtitle.setText( object.subtitle );
    Glide.with(mContext)
            .load(object.Image)
            .dontAnimate()
            .placeholder(R.drawable.icon)
            .into(((ImageTypeViewHolder) holder).imageView);
    ( (ImageTypeViewHolder) holder).title.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(mContext, PostDetails.class);
            intent.putExtra("itemPosition", position);
            mContext.startActivity(intent);
        }
    });
    ( (ImageTypeViewHolder) holder).subtitle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(mContext, PostDetails.class);
            intent.putExtra("itemPosition", position);
            mContext.startActivity(intent);
        }
    });
    ( (ImageTypeViewHolder) holder).imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(mContext, PostDetails.class);
            intent.putExtra("itemPosition", position);
            mContext.startActivity(intent);
        }
    });



    /// dataset.get(position)
}



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

这是我的 MainActivity:

recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    progressBar = (ProgressBar) findViewById(R.id.progressbar);
    mLayoutManager = new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false);
    recyclerView.setLayoutManager(mLayoutManager);
    list = new ArrayList<Model>();

    getRetrofit();
    adapter = new RecyclerViewAdapter( list, MainActivity.this);
    recyclerView.setAdapter(adapter);




    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (dy > 0) { //check for scroll down
                visibleItemCount = mLayoutManager.getChildCount();
                totalItemCount = mLayoutManager.getItemCount();
                pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

                if (loading) {
                    if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                        loading = false;
                        Log.v("...", "Last Item Wow !");
                        // Do pagination.. i.e. fetch new data
                        getRetrofit();
                        adapter = new RecyclerViewAdapter( list, MainActivity.this);
                        recyclerView.setAdapter(adapter);

                    }
                }
            }
        }
    });

这是我在 mainactivity 中的改造:

 public void getRetrofit(){
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(baseURL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    RetrofitArrayApi service = retrofit.create(RetrofitArrayApi.class);
    String yourURl = yourURL.replace(baseURL,"");
    Call<List<WPPost>>  call = service.getPostInfo( yourURl);
    call.enqueue(new Callback<List<WPPost>>() {
        @Override
        public void onResponse(Call<List<WPPost>> call, Response<List<WPPost>> response) {
            Log.e("mainactivyt", " response "+ response.body());
            mListPost = response.body();
            progressBar.setVisibility(View.GONE);
            if (response.body() != null) {


                for (int i = 0; i < response.body().size(); i++ ) {




                    Log.e("size", list.size() + "");


                    System.out.println("The shortest word i is:" + i );




                    Log.e("main ", " title " + response.body().get(i).getTitle().getRendered() + " " +
                            response.body().get(i).getId());
                    String tempdetails = response.body().get(i).getExcerpt().getRendered().toString();
                    tempdetails = tempdetails.replace("<p>", "");
                    tempdetails = tempdetails.replace("</p>", "");
                    tempdetails = tempdetails.replace("[&hellip;]", "");
                    list.add(new Model(Model.IMAGE_TYPE, response.body().get(i).getTitle().getRendered(),
                            tempdetails,
                            response.body().get(i).getImages().getMedium()));


                    adapter.notifyDataSetChanged();




                }




                progressBar.setVisibility(View.GONE);
            } else {
                progressBar.setVisibility(View.GONE);
            }




        }
        @Override
        public void onFailure(Call<List<WPPost>> call, Throwable t) {
        }
    });
}

最后:

 public static List<WPPost> getList(){
    return  mListPost;
}

请帮忙,我找到答案已经两周多了,拜托

我也试过这个方法:

还有这个What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?

我想问题出在您的 MainActivity 上,您在其中尝试使用

获取列表项
Log.e("PostDetails ", "title is " + MainActivity.mListPost.get(position).getTitle().getRendered());

在这种情况下,每次调用 Retrofit 时,您的 mList 都会刷新,这意味着,您的 RecyclerView 列表可能包含 10 个以上的元素,但您的列表将始终包含 10 个元素。因此,在您的情况下,当您单击列表的第 12 个(甚至可能是第 11 个)项时会发生崩溃,这是因为您的列表始终包含 10 个最近使用改造获取的项目。

要解决这个问题,你不应该每次都重新分配你的列表,而应该将新项目添加到列表中,或者你可以在意图中发送完整的对象而不是仅仅传递项目位置,因为它是主题改变。

发生这种情况是因为 MainActivity.mListPost 只有最新的响应,在您的情况下通常是 10 件商品,因为您一次需要 10 件商品。 但是,如果您看到传递给适配器的列表随着每次新调用而增加,因为您在列表中使用“添加”。 因此,您的适配器将随着对下一页的每个新 API 调用而增长,但是您的 MainActivity.mListPost 只会获取最新的 10 个项目。 请确保像更新适配器列表一样更新您的 MainActivity.mListPost。

代码告诉您正在将点击项目位置传递给下一个 Activity 并使用来自上一个 activity 的这个位置访问模型对象,为什么不直接使用 bundle.putParcelable() 将对象传递给意图对象 ?

为什么要覆盖 getItemViewType(int position),因为您没有在 Adapter 中使用多视图类型?。在 getRetrofit() 方法中你调用了 adapter.notifyDataSetChanged(); 虽然你没有完全替换你的列表,你只是将新项目添加到 list ,所以 notifyItemRangeInserted() 应该在这里使用。我制作了示例项目只是为了解决您的问题。让我们看看:-

    public class RecyclerViewTestActivity extends AppCompatActivity {

    private MyAdapter adapter;
    private boolean loading = false;
    int pastVisiblesItems, visibleItemCount, totalItemCount;
    LinearLayoutManager mLayoutManager;
    String baseURL = "https://my.backend.url";
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(baseURL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    RetrofitArrayApi service = retrofit.create(RetrofitArrayApi.class);
    String yourURl = yourURL.replace(baseURL,"");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view_test);

        RecyclerView recyclerView = findViewById(R.id.recycler_view);
        mLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(mLayoutManager);
        adapter = new MyAdapter(new ArrayList<>());
        recyclerView.setAdapter(adapter);


        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (dy > 0) { //check for scroll down
                    visibleItemCount = mLayoutManager.getChildCount();
                    totalItemCount = mLayoutManager.getItemCount();
                    pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

                    if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {

                        Log.d("tisha==>>","Is loading = "+loading);
                        // Do pagination.. i.e. fetch new data

                        if (!loading){
                            adapter.showHideProgress(true);
                            loading = true;
                            getRetrofit();
                        }
                    }
                }
            }
        });
        getRetrofit();
    }
          void getRetrofit(){

        // fetching data from remote server.....
        try {
            List<Model> list = new ArrayList<>();
            
            Call<List<WPPost>>  call = service.getPostInfo( yourURl);
            call.enqueue(new Callback<List<WPPost>>() {
                @Override
                public void onResponse(Call<List<WPPost>> call, Response<List<WPPost>> response) {
                    Log.d("==>>", " response "+ response.body());
                    mListPost = response.body();
                    progressBar.setVisibility(View.GONE);
                    if (response.body() != null) {

                        for (int i = 0; i < response.body().size(); i++ ) {

                            Log.d("==>>", list.size() + "");

                            Log.d("==>>", " title " + response.body().get(i).getTitle().getRendered() + " " +
                                    response.body().get(i).getId());
                            String tempdetails = response.body().get(i).getExcerpt().getRendered().toString();
                            tempdetails = tempdetails.replace("<p>", "");
                            tempdetails = tempdetails.replace("</p>", "");
                            tempdetails = tempdetails.replace("[&hellip;]", "");
                            list.add(new Model(Model.IMAGE_TYPE, response.body().get(i).getTitle().getRendered(),
                                    tempdetails,
                                    response.body().get(i).getImages().getMedium()));

                        }
                        if (loading){
                            loading = false;
                            adapter.showHideProgress(false);
                        }
                        adapter.addItemsToList(list);
                        progressBar.setVisibility(View.GONE);
                    } else {
                        progressBar.setVisibility(View.GONE);
                    }
                }
                @Override
                public void onFailure(Call<List<WPPost>> call, Throwable t) {
                }
            });

        }catch (Exception exception){
            Log.d("tisha==>>"," "+exception.getLocalizedMessage());
        }
    }

// Customize Model Class as per your requirement-----------------
class Model implements Parcelable {
    String title;
    String subTitle;
    String imageUrl;
    Model(String title, String subTitle, String imageUrl){
        this.title = title;
        this.subTitle = subTitle;
        this.imageUrl = imageUrl;
    }

    protected Model(Parcel in) {
        title = in.readString();
        subTitle = in.readString();
        imageUrl = in.readString();
    }

    public static final Creator<Model> CREATOR = new Creator<Model>() {
        @Override
        public Model createFromParcel(Parcel in) {
            return new Model(in);
        }

        @Override
        public Model[] newArray(int size) {
            return new Model[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(title);
        dest.writeString(subTitle);
        dest.writeString(imageUrl);
    }
}
class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    List<Model> modelList;
    int viewTypeData = 0,viewTypeProgress = 1;
    MyAdapter(List<Model> list){
        modelList = list;
    }
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
mContext = parent.getContext();
        if (viewType == viewTypeData){
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item_view,parent,false);
            return new MyDataHolder(view);
        }else {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item_loading,parent,false);
            return new MyProgressHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        Model model = modelList.get(position);
        if (holder instanceof MyDataHolder){
            ((MyDataHolder)holder).showModel(model);
        }else
            ((MyProgressHolder)holder).show();
    }

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

    @Override
    public int getItemViewType(int position){
        if (modelList.get(position).title.equals("progress"))
            return viewTypeProgress;
        else
            return viewTypeData;
    }
    void showHideProgress(boolean shouldShowProgress){
        if (shouldShowProgress){
            modelList.add(new Model("progress","",""));
            notifyItemInserted(modelList.size()-1);
        }else {
            Log.d("tisha==>>","Size before removal = "+modelList.size());
            modelList.remove(modelList.size()-1);
            notifyItemRemoved(modelList.size()-1);
            Log.d("tisha==>>","Size after removal = "+modelList.size());
        }
    }
    void addItemsToList(List<Model> newItems){
        if (modelList.isEmpty()){
            modelList.addAll(newItems);
            notifyDataSetChanged();
            Log.d("tisha==>>","First time List size = "+modelList.size());
        }else {
            int lastItemPosition = modelList.size() -1;
            Log.d("tisha==>>","Old list size = "+modelList.size()+ "Last Item position= "+lastItemPosition);
            modelList.addAll(newItems);
            Log.d("tisha==>>","Update List size = "+modelList.size());
            notifyItemRangeInserted(lastItemPosition,newItems.size());
        }
    }
    static class MyDataHolder extends RecyclerView.ViewHolder{
        TextView titleView,subTitleView;
        ImageView imageView;LinearLayout rootView;
        // Use Glide to load image to image view 
        public MyDataHolder(@NonNull View itemView) {
            super(itemView);
            titleView = itemView.findViewById(R.id.recycler_item_title_tv);
            subTitleView = 
itemView.findViewById(R.id.recycler_item_subtitle_tv);
            imageView = itemView.findViewById(R.id.recycler_img_view);
rootView = itemView.findViewById(R.id.recycler_item_root_view);
            rootView.setOnClickListener(v -> {
                Bundle bundle = new Bundle();
                
bundle.putParcelable("my_key",modelList.get(getAdapterPosition()));
                Intent intent = new Intent(mContext, DetialsActivity.class);
                intent.putExtra("my_bundle",bundle);
                mContext.startActivity(intent);
            });
        }
        void showModel(Model model){
            titleView.setText(model.title);
            subTitleView.setText(model.subTitle);
        }
    }
    static class MyProgressHolder extends RecyclerView.ViewHolder{
        ProgressBar progressBar;
        public MyProgressHolder(@NonNull View itemView) {
            super(itemView);
            progressBar = itemView.findViewById(R.id.recycler_item_progress);
        }
        void show(){
            progressBar.setVisibility(View.VISIBLE);
        }
    }
}

recycler_item_view.xml

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/recycler_item_root_view">
<ImageView
    android:id="@+id/recycler_img_view"
    android:layout_width="50dp"
    android:layout_height="50dp"/>
<LinearLayout
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_weight="1"
    android:layout_gravity="center_vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/recycler_item_title_tv"
        android:gravity="center">
    </TextView>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/recycler_item_subtitle_tv"
        android:gravity="start">
    </TextView>
</LinearLayout>

recycler_item_loading.xml

<ProgressBar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/recycler_item_progress"
android:indeterminate="true">

在 NextActivity 中获取 Parcelable 模型 Class,如下所示。在 Target Activity 的 onCreate() 内部放置以下代码:

    Bundle bundle = getIntent().getBundleExtra("my_bundle");
    Model model = bundle.getParcelable("my_key");
    if (model != null){
        Log.d("tisha==>>","Title = "+model.title);
    }