i have successfully get posts and on first 10 posts, i get post content also, but when i scroll down to load more posts, i can see posts with featured image as well, but when i click on those posts i get this error: now its over 2 weeks since i am finding the answer, please help
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)
this is my PostDetails 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");
this is Adapter:
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;
}
and this is my 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);
}
}
}
}
});
and this is my retrofit in 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("[…]", "");
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) {
}
});
}
and in end :
public static List<WPPost> getList(){
return mListPost;
}
please help, now its over 2 weeks since i am finding the answer, please
i have tried this method also : How to handle pagination/load more in Retrofit 2.0?
also this one What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
Code tells you are passing click item position to next Activity and accessing model object using this position from previous activity, why don't you pass object directly using bundle.putParcelable()
to Intent object ?
Why are you overriding getItemViewType(int position)
as you are not using multiple view type in Adapter ?. And inside getRetrofit()
method you called adapter.notifyDataSetChanged();
though you not completely replacing your list, you just add new items to list , so notifyItemRangeInserted()
should be used here. I have made sample project just to address your issue. Let's have a look :-
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("[…]", "");
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">
Get Parcelable Model Class in NextActivity like below. Inside onCreate() of Target Activity put below code:
Bundle bundle = getIntent().getBundleExtra("my_bundle");
Model model = bundle.getParcelable("my_key");
if (model != null){
Log.d("tisha==>>","Title = "+model.title);
}