Android recyclerview adapter notifyItemMoved crashes - java

I have a recyclerview list and I want to be able to move those items. When I use notifyDataSetChanged() it works but, but if I use notifyItemMoved(fromPosition, toPosition) it doesn't and app crashes.
Here is stacktrace:
java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView$Recycler.unscrapView(androidx.recyclerview.widget.RecyclerView$ViewHolder)' on a null object reference
at androidx.recyclerview.widget.RecyclerView$ViewHolder.unScrap(RecyclerView.java:11235)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6166)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:561)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:625)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:812)
at android.view.View.layout(View.java:23167)
at android.view.ViewGroup.layout(ViewGroup.java:6412)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3724)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3183)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2153)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8761)
2023-01-11 16:11:07.234 12095-12095/ab.cde.simplenotepad E/AndroidRuntime: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1120)
at android.view.Choreographer.doCallbacks(Choreographer.java:926)
at android.view.Choreographer.doFrame(Choreographer.java:859)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1105)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:241)
at android.os.Looper.loop(Looper.java:358)
at android.app.ActivityThread.main(ActivityThread.java:8006)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1009)
Here is my code:
MyFragment.java
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
initAds(view);
requireActivity().setTitle(getString(R.string.my_notes));
this.view = view;
notesList = db.getAllNotes();
configureRecyclerView(view, notesList);
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
notesList = db.getAllNotes();
if (fromPosition < toPosition) { // jeśli notka idzie w prawo albo w dół
db.updateOrder(notesList.get(toPosition).getNoteOrder(), notesList.get(fromPosition).getId());
for (int i = fromPosition; i <= toPosition - 1; i++) {
db.updateOrder(notesList.get(i).getNoteOrder(), notesList.get(i + 1).getId());
}
}
else if (fromPosition > toPosition) { // jeśli notka idzie w lewo albo w górę
db.updateOrder(notesList.get(toPosition).getNoteOrder(), notesList.get(fromPosition).getId());
for (int i = fromPosition; i >= toPosition + 1; i--) {
db.updateOrder(notesList.get(i).getNoteOrder(), notesList.get(i - 1).getId());
}
}
Collections.swap(notesList, fromPosition, toPosition);
/* HERE IS THE PROBLEM */
Objects.requireNonNull(recyclerView.getAdapter()).notifyItemMoved(fromPosition, toPosition);
return true;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
#Override
public int getSwipeDirs(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
return 0;
}
#Override
public void onSelectedChanged(#Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
Objects.requireNonNull(viewHolder).itemView.setAlpha(0.5f);
}
}
#Override
public void clearView(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(1f);
Parcelable recylerViewState = Objects.requireNonNull(recyclerView.getLayoutManager()).onSaveInstanceState();
notesList = db.getAllNotes();
configureRecyclerView(view, notesList);
recyclerView.getLayoutManager().onRestoreInstanceState(recylerViewState);
}
};
new ItemTouchHelper(simpleCallback).attachToRecyclerView(noteRecyclerView);
swipeContainer = view.findViewById(R.id.swipeContainer);
swipeContainer.setOnRefreshListener(() -> {
notesList.clear();
notesList.addAll(db.getAllNotes());
swipeContainer.setRefreshing(false);
});
}
private void configureRecyclerView(View view, List<Note> notes) {
noteRecyclerView = view.findViewById(R.id.recyclerview);
noteRecyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
startPostponedEnterTransition();
noteRecyclerView.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
noteRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
lastPosition = dy;
}
});
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), Integer.parseInt(colsNumber));
noteRecyclerView.setLayoutManager(gridLayoutManager);
NoteAdapter noteDataAdapter = new NoteAdapter(notes, getContext(), (ActivityMain) getActivity(), bottomNavHeight, Integer.parseInt(colsNumber), this);
noteRecyclerView.setAdapter(noteDataAdapter);
if(sp.getInt("scroll_main", 0) != 0) {
noteRecyclerView.post(new Runnable() {
#Override
public void run() {
noteRecyclerView.scrollBy(0, sp.getInt("scroll_main", 0));
}
});
}
}
Any help will be appreciated.
EDIT but maybe the problem can be in clearView() I don't know
Thank you in advance!

I found a solution. Simply I removed overrided getItemViewType() from my recyclerview adapter.

Related

Recycler View List Sort position saving notepad app

In my program I added code to move the list items around but for example if I move shopping list above Test 123 and fully close the app the positioning resets to the original instead of the updated location I cannot figure out for the life of me what to do.
Code for click drag in mainactivity.java
//Click drag Notes feature *****************************************************
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.START | ItemTouchHelper.END, 0) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
int fromPosition = viewHolder.getBindingAdapterPosition();
int toPosition = target.getBindingAdapterPosition();
Collections.swap(notesList, fromPosition, toPosition);
Objects.requireNonNull(recyclerView.getAdapter()).notifyItemMoved(fromPosition, toPosition);
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
}
#Override //This forces arrangement up or down not any direction
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlags, 0);
}
};
//******************************************* Click Drag Notes ***************************************
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
ItemTouchHelper helper = new ItemTouchHelper(callback);
helper.attachToRecyclerView(recyclerView);
//
notesList = new ArrayList<>();
databaseClass = new
DatabaseClass(this);
fetchAllNotesFromDatabase();
recyclerView.setLayoutManager(new
LinearLayoutManager(this));
adapter = new
Adapter(this, MainActivity.this, notesList);
recyclerView.setAdapter(adapter);
}
Adapter Code
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_layout, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, #SuppressLint("RecyclerView") int position) {
holder.title.setText(notesList.get(position).getTitle());
holder.description.setText(notesList.get(position).getDescription());
holder.layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, UpdateNotesActivity.class);
intent.putExtra("title", notesList.get(position).getTitle());
intent.putExtra("description", notesList.get(position).getDescription());
intent.putExtra("id", notesList.get(position).getId());
activity.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return notesList.size();
}
#Override
public Filter getFilter() {
return exampleFilter;
}
private Filter exampleFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Model> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(newList);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Model item : newList) {
if (item.getTitle().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
notesList.clear();
notesList.addAll((List) results.values);
notifyDataSetChanged();
}
};
public class MyViewHolder extends RecyclerView.ViewHolder {
private static final String TAG = "MyViewHolder";
TextView title, description, textView;
ImageButton imageButton;
RelativeLayout layout;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
description = itemView.findViewById(R.id.description);
layout = itemView.findViewById(R.id.note_layout);
}
}
public List<Model> getList() {
return notesList;
}
public void removeItem(int position) {
notesList.remove(position);
notifyItemRemoved(position);
}
public void restoreItem(Model item, int position) {
notesList.add(position, item);
notifyItemInserted(position);
}
}

java.lang.IndexOutOfBoundsException When Displaying Multiple Data in RecyclerView

I have 3 parts of data displayed in one RecyclerView:
storyList
yukulList
homeList
When I've tried to display only storyList or yukulList or homeList data in RecyclerView, it works. But when I've tried to display more than one data, for example: storyList && yukulList or storyList && yukulList && homeList, it will show
java.lang.IndexOutOfBoundsException.
I've tried to add notifyDataSetChanged() but it can't works.
ShowFavouriteList.java
public class ShowFavouriteList extends AppCompatActivity implements AdapterFavList.FavListener {
private RecyclerView recyclerView;
private TextView noFavtsTV;
AppPreferences appPreferences;
private SearchView searchView;
private AdapterFavList yAdapterFavlist;
private AdapterFavList mAdapterFavlist;
private AdapterFavList tAdapterFavlist;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_favourite_list);
SwipeRefreshLayout pullToRefresh = findViewById(R.id.pullToRefresh);
pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
finish();
startActivity(getIntent());
}
});
//toolbar logo and desc
Toolbar topToolBar = (Toolbar) findViewById(R.id.toolbarTidur);
setSupportActionBar(topToolBar); //munculkan menu ke toolbar
getSupportActionBar().setDisplayHomeAsUpEnabled(true); //this line shows back button
recyclerView = findViewById(R.id.recycler_view);
noFavtsTV = findViewById(R.id.no_favt_text);
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("MyPref", 0);
SharedPreferences sPTuru = getApplicationContext().getSharedPreferences("MyTuru", 0);
SharedPreferences sPHome = getApplicationContext().getSharedPreferences("MyHome", 0);
PreferenceMenejer preferenceMenejer = new PreferenceMenejer(sharedPreferences, sPTuru, sPHome);
appPreferences = new AppPreferences(preferenceMenejer);
fetchData();
} // Oncreate
private void fetchData() {
List<Story> storyList = appPreferences.getFavouriteCardList();
List<YukulModel> yukulList = appPreferences.getFavouriteYukul();
List<HomeModel> homeList = appPreferences.getFavouriteHome();
if(storyList != null && storyList.size() > 0) {
showNoFavtText(false);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
tAdapterFavlist = new AdapterFavList(this, storyList, yukulList, homeList, this, appPreferences);
recyclerView.setAdapter(tAdapterFavlist);
tAdapterFavlist.notifyDataSetChanged();
}
if(yukulList != null && yukulList.size() > 0) {
showNoFavtText(false);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
yAdapterFavlist = new AdapterFavList(this, storyList, yukulList, homeList, this, appPreferences);
recyclerView.setAdapter(yAdapterFavlist);
yAdapterFavlist.notifyDataSetChanged();
}
if(homeList != null && homeList.size() > 0) {
showNoFavtText(false);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
mAdapterFavlist = new AdapterFavList(this, storyList, yukulList, homeList, this, appPreferences);
recyclerView.setAdapter(mAdapterFavlist);
mAdapterFavlist.notifyDataSetChanged();
}
}
#Override
public void onItemKlik(RecyclerView.ViewHolder viewHolder, HomeModel modelField, int position) {
// Tidur List
List<HomeModel> modelList = appPreferences.getFavouriteHome();
HomeModel click = modelList.get(position);
Toast.makeText(getApplicationContext(), "Selected: " + click.getName(), Toast.LENGTH_LONG).show();
int id = Integer.parseInt(click.getIdStory());
if (id == 0) {
startActivity(new Intent(this, DoaPagi.class));
} else if (id == 1) {
startActivity(new Intent(this, DoaSore.class));
} else if (id == 2) {
startActivity(new Intent(this, DoaWc.class));
} else if (id == 3) {
startActivity(new Intent(this, DoaMasjid.class));
} else if (id == 4) {
startActivity(new Intent(this, DzikirShalat.class));
} else if (id == 5) {
startActivity(new Intent(this, ChildYukul.class));
} else if (id == 6) {
startActivity(new Intent(this, DoaPakaian.class));
} else if (id == 7) {
startActivity(new Intent(this, ChildTidur.class));
}
}
#Override
public void onItemTuru(RecyclerView.ViewHolder viewHolder, Story tField, int position) {
// Tidur List
List<Story> storyList = appPreferences.getFavouriteCardList();
Story clic = storyList.get(position);
int idTuru = Integer.parseInt(clic.getIdStory());
if (idTuru == 0) {
startActivity(new Intent(this, DoaMauTidur.class));
} else if (idTuru == 1) {
startActivity(new Intent(this, DoaBangunt.class));
} else if (idTuru == 2) {
startActivity(new Intent(this, DoaJimak.class));
}
}
#Override
public void onItemYukul(RecyclerView.ViewHolder viewHolder, YukulModel yField, int position) {
// Tidur List
}
private void showNoFavtText(boolean show) {
noFavtsTV.setVisibility(show ? View.VISIBLE : View.GONE); //jika data yang ditampilkan tidak ada, maka show noFavsTv
recyclerView.setVisibility(show ? View.GONE : View.VISIBLE); //jika data yang ditampilkan tidak ada, maka don't show rV
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_fav, menu);
getMenuInflater().inflate(R.menu.menu_main, menu);
// Associate searchable_tidur configuration with the SearchView
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search_fav).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setMaxWidth(Integer.MAX_VALUE);
// listening to search query text change
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// filter recycler view when query submitted
mAdapterFavlist.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String query) {
// filter recycler view when text is changed
mAdapterFavlist.getFilter().filter(query);
return false;
}
});
return true;
}
// Agar back button pada halaman induk settings berfungsi
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.search_fav) {
return true;
}
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
AdapterFavList.java
public class AdapterFavList extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {
public static final String ACTION_LIKE_IMAGE_CLICKED = "action_like_image_button";
final int VIEW_TYPE_TIDUR = 0;
final int VIEW_TYPE_YUKUL = 1;
final int VIEW_TYPE_HOME = 2;
private Context context;
private AppPreferences appPreferences;
private List<Story> storyList;
private List<YukulModel> yukulList;
private List<HomeModel> homeList;
private List<HomeModel> homeListFiltered;
private List<Object> collection = new ArrayList<Object>();
private FavListener listener;
private int changedItemPosition;
private boolean isLiked;
public AdapterFavList(Context context, List<Story> storyList, List<YukulModel> yukulList, List<HomeModel> homeList, FavListener listener, AppPreferences appPreferences) {
this.context = context;
this.storyList = storyList;
this.yukulList = yukulList;
this.homeListFiltered = homeList;
this.listener = listener;
this.appPreferences = appPreferences;
addData();
}
public void addData() {
storyList = appPreferences.getFavouriteCardList();
yukulList = appPreferences.getFavouriteYukul();
homeList = appPreferences.getFavouriteHome();
if(storyList != null && storyList.size() > 0) {
collection.addAll(storyList);
}
if(yukulList != null && yukulList.size() > 0) {
collection.addAll(yukulList);
}
if(homeList != null && homeList.size() > 0) {
collection.addAll(homeListFiltered);
}
}
public interface FavListener {
void onItemKlik(RecyclerView.ViewHolder viewHolder, HomeModel modelField, int position);
void onItemTuru(RecyclerView.ViewHolder viewHolder, Story tField, int position);
void onItemYukul(RecyclerView.ViewHolder viewHolder, YukulModel yField, int position);
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if(viewType == VIEW_TYPE_TIDUR) {
return new tidurViewHolder(LayoutInflater.from(context).inflate(R.layout.item_story_favourite_list, parent, false));
}
if(viewType == VIEW_TYPE_YUKUL) {
return new yukulViewHolder(LayoutInflater.from(context).inflate(R.layout.item_favourite_yukul, parent, false));
}
if(viewType == VIEW_TYPE_HOME) {
return new homeViewHolder(LayoutInflater.from(context).inflate(R.layout.item_fav_home, parent, false));
}
return null;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Object item = collection.get(position);
if(holder instanceof tidurViewHolder){
((tidurViewHolder) holder).bind(storyList.get(position));
((tidurViewHolder) holder).setViewData((Story) item, holder.getAdapterPosition());
}
if(holder instanceof yukulViewHolder){
((yukulViewHolder) holder).bind(yukulList.get(position));
((yukulViewHolder) holder).viewDataYukul((YukulModel) item, holder.getAdapterPosition());
}
if(holder instanceof homeViewHolder){
((homeViewHolder) holder).bind(homeList.get(position));
((homeViewHolder) holder).viewDataHome((HomeModel) item, holder.getAdapterPosition());
}
}
#Override
public int getItemCount() {
return collection.size();
}
#Override
public int getItemViewType(int position){
Object item = collection.get(position);
if(item instanceof Story) {
return VIEW_TYPE_TIDUR;
}
if(item instanceof YukulModel){
return VIEW_TYPE_YUKUL;
}
if(item instanceof HomeModel){
return VIEW_TYPE_HOME;
}
return -1;
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
List<HomeModel> homeList = appPreferences.getFavouriteHome();
if (charString.isEmpty()) {
homeListFiltered = homeList;
}
else {
List<HomeModel> filteredList = new ArrayList<>();
for (HomeModel row : homeList) {
if ( row.getName().toLowerCase().contains(charString.toLowerCase()) ) {
filteredList.add(row);
}
}
homeListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = homeListFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
homeListFiltered = (ArrayList<HomeModel>) filterResults.values;
notifyDataSetChanged();
}
};
} //Filter
public void tidurPutHeart(boolean isChecked, Story tidurstory) {
SharedPreferences tidursharedPreferences = context.getSharedPreferences("Turu", Activity.MODE_PRIVATE);
SharedPreferences.Editor tidureditor = tidursharedPreferences.edit();
tidureditor.putBoolean(tidurstory.getIdStory(), isChecked);
tidureditor.commit();
}
public void yukulPutHeart(boolean isChecked, YukulModel yukulstory) {
SharedPreferences yukulsharedPreferences = context.getSharedPreferences("Yukul", Activity.MODE_PRIVATE);
SharedPreferences.Editor yukuleditor = yukulsharedPreferences.edit();
yukuleditor.putBoolean(yukulstory.getIdStory(), isChecked);
yukuleditor.commit();
}
public void homePutHeart(boolean isChecked, HomeModel homestory) {
SharedPreferences homesharedPreferences = context.getSharedPreferences("Home", Activity.MODE_PRIVATE);
SharedPreferences.Editor homeeditor = homesharedPreferences.edit();
homeeditor.putBoolean(homestory.getIdStory(), isChecked);
homeeditor.commit();
}
//ViewHolder
public class tidurViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
private CheckBox likeCheckBox;
public tidurViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.text_view);
likeCheckBox = itemView.findViewById(R.id.like_button_cb);
} // itemView
public void bind(final Story item) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemTuru(tidurViewHolder.this, item, position);
}
}
}
});
}
public void setViewData(final Story story, final int adapterPosition) {
textView.setText(story.getName());
if (story.getIsLiked() == 1) {
likeCheckBox.setChecked(false);
}
else {
likeCheckBox.setChecked(true);
}
likeCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
changedItemPosition = adapterPosition;
if (buttonView.isPressed()) {
if (isChecked) {
tidurPutHeart(isChecked, story);
appPreferences.saveFavouriteCard(story);
}
else {
isLiked = false;
tidurPutHeart(isChecked, story);
appPreferences.deleteCard(story.getIdStory());
// updateLikes();
Toast.makeText(context, "Removed", Toast.LENGTH_SHORT).show();
if(collection.size() == 0) {
((Activity)context).finish();
context.startActivity(((Activity) context).getIntent());
}
}
}
}
});
} //setviewdata
public void updateLikes() {
if (!isLiked && storyList.get(changedItemPosition).getIsLiked() == 0) { //jika like dicabut (pada posisi hati yang sedang merah) di halaman favourite list
storyList.get(changedItemPosition).setIsLiked(0); //maka cabut juga warna merah di halaman favourite list
notifyItemRangeChanged(getAdapterPosition(), collection.size());
collection.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());
}
} //updateLikes
} //tidurViewholder
//homeViewHolder
public class homeViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
private CheckBox likeCheckBox;
public homeViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.text_view);
likeCheckBox = itemView.findViewById(R.id.like_button_cb);
} // itemView
public void bind(final HomeModel item) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemKlik(homeViewHolder.this, item, position);
}
}
}
});
}
public void viewDataHome(final HomeModel story, final int adapterPosition) {
textView.setText(story.getName());
if (story.getIsLiked() == 1) {
likeCheckBox.setChecked(false);
}
else {
likeCheckBox.setChecked(true);
}
likeCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
changedItemPosition = adapterPosition;
if (buttonView.isPressed()) {
if (isChecked) {
homePutHeart(isChecked, story);
appPreferences.saveFavouriteHome(story);
}
else {
isLiked = false;
homePutHeart(isChecked, story);
appPreferences.deleteCardHome(story.getIdStory());
// updateLikesHome();
Toast.makeText(context, "Removed", Toast.LENGTH_SHORT).show();
if(collection.size() == 0) {
((Activity)context).finish();
context.startActivity(((Activity) context).getIntent());
}
}
}
}
});
} //setviewdata
public void updateLikesHome() {
if (!isLiked && homeList.get(changedItemPosition).getIsLiked() == 0) { //jika like dicabut (pada posisi hati yang sedang merah) di halaman favourite list
homeList.get(changedItemPosition).setIsLiked(0); //maka cabut juga warna merah di halaman favourite list
notifyItemRangeChanged(getAdapterPosition(), collection.size());
collection.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());
}
} //updateLikes
} //homeviewholder
public class yukulViewHolder extends RecyclerView.ViewHolder {
private TextView textView;
private CheckBox likeCheckBox;
public yukulViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.text_view);
likeCheckBox = itemView.findViewById(R.id.like_button_cb);
} //itemview
public void bind(final YukulModel item) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemYukul(yukulViewHolder.this, item, position);
}
}
}
});
}
public void viewDataYukul(final YukulModel yukulId, final int adapterPosition) {
textView.setText(yukulId.getName());
if (yukulId.getIsLiked() == 1) {
likeCheckBox.setChecked(false);
}
else {
likeCheckBox.setChecked(true);
}
likeCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
changedItemPosition = adapterPosition;
if (buttonView.isPressed()) {
if (isChecked) {
yukulPutHeart(isChecked, yukulId);
appPreferences.saveFavouriteYukul(yukulId);
}
else {
isLiked = false;
yukulPutHeart(isChecked, yukulId);
appPreferences.deleteCardYukul(yukulId.getIdStory());
// updateLikeYukul();
Toast.makeText(context, "Removed", Toast.LENGTH_SHORT).show();
if(collection.size() == 0) {
((Activity)context).finish();
context.startActivity(((Activity) context).getIntent());
}
}
}
}
});
} //viewdatayukul
public void updateLikeYukul() {
if (!isLiked && yukulList.get(changedItemPosition).getIsLiked() == 0) { //jika like dicabut (pada posisi hati yang sedang merah) di halaman favourite list
yukulList.get(changedItemPosition).setIsLiked(0); //maka cabut juga warna merah di halaman favourite list
notifyItemRangeChanged(getAdapterPosition(), collection.size());
collection.remove(getAdapterPosition());
notifyItemRemoved(getAdapterPosition());
}
} //updateLikes
} //yukulviewholder
} //HomeAdapter
Logcat
2019-07-20 09:54:52.822 6902-6902/com.seadlab.doadandzikir E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.seadlab.doadandzikir, PID: 6902
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.get(ArrayList.java:437)
at com.seadlab.doadandzikir.FavouriteList.AdapterFavList.onBindViewHolder(AdapterFavList.java:124)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6482)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6515)
at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5458)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5724)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5563)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5559)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2229)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1556)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1516)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:608)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3693)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3410)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3962)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:610)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:132)
at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42)
at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1361)
at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:869)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:753)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2792)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2319)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
2019-07-20 09:54:52.825 6902-6902/com.seadlab.doadandzikir E/AndroidRuntime: at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:696)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Try to remove this recyclerView.setHasFixedSize(true) or pass FALSE to it. passing TRUE to this method means your adapter's object content will not change, but here your changing the adapter content by performing a QUERY SEARCH on the adapter's content.
In your adapter, the collection list is the only list that's safe to access using position. Trying to call yukulList.get(position) is guaranteed to eventually throw an exception.
All of these lines in onBindViewHolder() are unsafe and should be changed:
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
// ...
((tidurViewHolder) holder).bind(storyList.get(position));
// ...
((yukulViewHolder) holder).bind(yukulList.get(position));
// ...
((homeViewHolder) holder).bind(homeList.get(position));
// ...
}
You can access the "view type" value that you've returned from getItemViewType() by calling holder.getItemViewType(), and you can use that to determine the right type of view holder and item to use:
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Object item = collection.get(position);
int adapterPosition = holder.getAdapterPosition();
if (holder.getItemViewType() == VIEW_TYPE_TIDUR){
Story story = (Story) item;
tidurViewHolder vh = (tidurViewHolder) holder;
vh.bind(story);
vh.setViewData(story, adapterPosition);
} else if (holder.getItemViewType() == VIEW_TYPE_YUKUL){
YukulModel yukul = (YukulModel) item;
yukulViewHolder vh = (yukulViewHolder) holder;
vh.bind(yukul);
vh.viewDataYukul(yukul, adapterPosition);
} else if (holder.getItemViewType() == VIEW_TYPE_HOME){
HomeModel home = (HomeModel) item;
homeViewHolder vh = (homeViewHolder) holder;
vh.bind(home);
vh.viewDataHome(home, adapterPosition);
}
}
Note also that there's no need to actually pass holder.getAdapterPosition() into e.g. setViewData(), since you can simply call getAdapterPosition() from within the tidurViewHolder method.
And I would also say that you could combine your bind() and setViewData() calls into one, which would leave you with this:
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Object item = collection.get(position);
if (holder.getItemViewType() == VIEW_TYPE_TIDUR){
((tidurViewHolder) holder).bind((Story) item);
} else if (holder.getItemViewType() == VIEW_TYPE_YUKUL){
((yukulViewHolder) holder).bind((YukulModel) item);
} else if (holder.getItemViewType() == VIEW_TYPE_HOME){
((homeViewHolder) holder).bind((HomeModel) item);
}
}
Try using three different recycler view, one for each data, and in the main layout set each recycler view with height = 0dp and weight 0.3, this going to make then each one has the same height and it'll fit perfectly in any screen

Pagination does not find the current position

I recently created a recyclerview with an Api, using retrofit.
I made a paging using OnScrollListener, and it's working. But when I click on some file it does not find the position of it, how can I solve this error?
I looked here in the forum about it and did not find anything related to retrofit. I just want to select the file and send it to another activity, to send the right id.
public class AcervoFragment extends Fragment {
private Retrofit retrofit;
private RecyclerView recyclerView;
private AcervoAdaptador acervoAdaptador;
private ProgressBar progressBar2;
private List<Lancamentos> listaLancamentos = new ArrayList<>();
private int pagina;
private boolean aptoCarregar;
public AcervoFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_acervo, container, false);
recyclerView = view.findViewById(R.id.recyclerViewAcervo);
acervoAdaptador = new AcervoAdaptador(getActivity());
recyclerView.setAdapter(acervoAdaptador);
recyclerView.setHasFixedSize(true);
final GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 3);
recyclerView.setLayoutManager(layoutManager);
retrofit = new Retrofit.Builder()
.baseUrl("api")
.addConverterFactory(GsonConverterFactory.create())
.build();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
int visibleItemCount = layoutManager.getChildCount();
int totalIntemCount = layoutManager.getItemCount();
int pastVisibleItems = layoutManager.findFirstVisibleItemPosition();
if (aptoCarregar) {
if ((visibleItemCount + pastVisibleItems) >= totalIntemCount) {
Log.i("TAG", "Carregando");
aptoCarregar = false;
pagina += 1;
obterDados(pagina);
}
}
}
}
});
aptoCarregar = true;
pagina = 1;
obterDados(pagina);
return view;
}
public void obterDados(int pagina) {
AcervoService service = retrofit.create(AcervoService.class);
Call<UltimosLancados> ultimosLancadosCall = service.obterAcervo(pagina);
ultimosLancadosCall.enqueue(new Callback<UltimosLancados>() {
#Override
public void onResponse(Call<UltimosLancados> call, Response<UltimosLancados> response) {
aptoCarregar = true;
if (response.isSuccessful()) {
UltimosLancados ultimosLancados = response.body();
final ArrayList<Lancamentos> listaAcervo = ultimosLancados.getDados();
//progressBar2.setVisibility(View.GONE);
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Lancamentos p = listaAcervo.get(position);
String aString = Integer.toString(p.getId());
int aInt = Integer.parseInt(aString);
Intent i = new Intent(getActivity().getApplicationContext(), PerfilActivity.class);
i.putExtra("ID", aInt);
startActivity(i);
}
#Override
public void onLongItemClick(View view, int position) {
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
}));
acervoAdaptador.adicionarItem(listaAcervo);
} else {
Log.e("TAG", "onResponse" + response.errorBody());
}
}
#Override
public void onFailure(Call<UltimosLancados> call, Throwable t) {
aptoCarregar = true;
Log.e("TAG", "onFailure" + t.getMessage());
}
});
}
}
07-26 20:02:29.382 21112-21112/site.exemplo.project E/InputEventReceiver: Exception dispatching input event.
07-26 20:02:29.382 21112-21112/site.exemplo.project E/MessageQueue-JNI: Exception in MessageQueue callback: handleReceiveCallback
07-26 20:02:29.392 21112-21112/site.exemplo.project E/MessageQueue-JNI: java.lang.IndexOutOfBoundsException: Invalid index 45, size is 40
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at site.exemplo.project.AcervoFragment$2$1.onItemClick(AcervoFragment.java:108)
at site.exemplo.project.RecyclerItemClickListener.onInterceptTouchEvent(RecyclerItemClickListener.java:26)
at android.support.v7.widget.RecyclerView.dispatchOnItemTouch(RecyclerView.java:2916)
at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:3044)
at android.view.View.dispatchTouchEvent(View.java:8808)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2569)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2239)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2581)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2254)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2607)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1779)
at android.app.Activity.dispatchTouchEvent(Activity.java:2846)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2568)
at android.view.View.dispatchPointerEvent(View.java:9003)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4209)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4072)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3627)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3680)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3646)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3763)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3654)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3820)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3627)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3680)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3646)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3654)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3627)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5910)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5884)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5855)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6000)
at android.view.InputEventReceiver.dispatchInputEven

App gets crashed randomly while scrolling expandable list view

I've been recyclerview in my app and on scrolling it gets crashed, not under any certain use case..it just gets crashed randomly. Below is my adapter and View Holder code.
class CustomListView_Base_Adapter extends BaseExpandableListAdapter {
Context context;
private LayoutInflater inflater = null;
public CustomListView_Base_Adapter(Context context) {
this.inflater = LayoutInflater.from(context);
this.context = context;
}
#Override
public int getGroupCount() {
return dataforSubcategoryItem.size();
}
#Override
public int getChildrenCount(int groupPosition) {
return 1;
}
#Override
public Object getGroup(int groupPosition) {
return dataforSubcategoryItem.get(groupPosition);
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return dataforSubcategoryItem.get(groupPosition);
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View resultView = convertView;
final ViewHolder holder;
if (resultView == null) {
resultView = inflater.inflate(R.layout.add_subcategory_list_item, null); //TODO change layout id
holder = new ViewHolder(resultView);
resultView.setTag(holder);
} else {
holder = (ViewHolder) resultView.getTag();
}
final SubcategoryItemBean beanObj = (SubcategoryItemBean) getGroup(groupPosition);
holder.tvColumnTitle.setText(beanObj.getName());
holder.checkBox.setOnCheckedChangeListener(null);
CustomWatcher oldWatcher = (CustomWatcher) holder.etInput.getTag();
if (oldWatcher != null)
holder.etInput.removeTextChangedListener(oldWatcher);
if (beanObj.isColumnSelected()) {
holder.checkBox.setChecked(true);
holder.etInput.setText(dataforSubcategoryItem.get(groupPosition).getLabel());
holder.etInput.setEnabled(true);
listView.expandGroup(groupPosition);
} else {
holder.checkBox.setChecked(false);
holder.etInput.setText("");
holder.etInput.setEnabled(false);
listView.collapseGroup(groupPosition);
}
CustomWatcher newWatcher = new CustomWatcher(groupPosition, holder.etInput);
holder.etInput.setTag(newWatcher);
holder.etInput.addTextChangedListener(newWatcher);
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
dataforSubcategoryItem.get(groupPosition).setColumnSelected(true);
} else {
dataforSubcategoryItem.get(groupPosition).setColumnSelected(false);
}
notifyDataSetChanged();
}
});
return resultView;
}
#Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
View resultView = convertView;
final ViewHolder holder;
if (resultView == null) {
resultView = inflater.inflate(R.layout.child_list_item, null); //TODO change layout id
holder = new ViewHolder(resultView, context);
resultView.setTag(holder);
} else {
holder = (ViewHolder) resultView.getTag();
}
final SubcategoryItemBean beanObj = (SubcategoryItemBean) getChild(groupPosition, childPosition);
CustomWatcher oldWatcher = (CustomWatcher) holder.defaultValues.getTag();
if (oldWatcher != null)
holder.defaultValues.removeTextChangedListener(oldWatcher);
holder.radiogroup.setOnCheckedChangeListener(null);
holder.defaultValues.setText(beanObj.getValue());
if (beanObj.getInput_type().equalsIgnoreCase(getString(R.string.column_type_text))) {
holder.defaultValues.setInputType(InputType.TYPE_CLASS_TEXT);
holder.defaultValues.setHint("Enter Default Value");
holder.rbText.setChecked(true);
} else if (beanObj.getInput_type().equalsIgnoreCase(getString(R.string.column_type_number))) {
holder.defaultValues.setInputType(InputType.TYPE_CLASS_NUMBER);
holder.defaultValues.setHint("Enter Default Value");
holder.rbNumber.setChecked(true);
} else if (beanObj.getInput_type().equalsIgnoreCase(getString(R.string.column_type_radiobutton))) {
holder.defaultValues.setInputType(InputType.TYPE_CLASS_TEXT);
holder.defaultValues.setHint("Enter comma separated values");
holder.rbRadioButton.setChecked(true);
} else if (beanObj.getInput_type().equalsIgnoreCase(getString(R.string.column_type_checkbox))) {
holder.rbCheckbox.setChecked(true);
holder.defaultValues.setHint("Enter comma separated values");
holder.defaultValues.setInputType(InputType.TYPE_CLASS_TEXT);
} else {
holder.rbDropdown.setChecked(true);
holder.defaultValues.setHint("Enter comma separated values");
holder.defaultValues.setInputType(InputType.TYPE_CLASS_TEXT);
}
holder.radiogroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, #IdRes int checkedId) {
RadioButton button = (RadioButton) group.findViewById(group.getCheckedRadioButtonId());
dataforSubcategoryItem.get(groupPosition).setInput_type(button.getText().toString());
holder.defaultValues.setText("");
notifyDataSetChanged();
}
});
CustomWatcher newWatcher = new CustomWatcher(groupPosition, holder.defaultValues);
holder.defaultValues.setTag(newWatcher);
holder.defaultValues.addTextChangedListener(newWatcher);
return resultView;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
private class CustomWatcher implements TextWatcher {
private int position;
private EditText editText;
private CustomWatcher(int position, EditText editText) {
this.position = position;
this.editText = editText;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
if (editText.getId() == R.id.addCategory_chooseItem_EditText) {
dataforSubcategoryItem.get(position).setLabel(editable.toString().trim());
System.out.println("CustomWatcher.onTextChanged label" + editable.toString());
}
if (editText.getId() == R.id.defaultValues_addSubCategory_chooseItem) {
dataforSubcategoryItem.get(position).setValue(editable.toString().trim());
System.out.println("CustomWatcher.afterTextChanged default value " + editable.toString());
}
}
}
}
class ViewHolder {
CheckBox checkBox;
TextView tvColumnTitle;
EditText etInput;
RadioGroup radiogroup;
RadioButton rbText, rbNumber, rbRadioButton, rbCheckbox, rbDropdown;
EditText defaultValues;
LinearLayout columnDetailsLayout;
public ViewHolder(View view) {
checkBox = (CheckBox) view.findViewById(R.id.addCategory_chooseItem_Checkbox);
tvColumnTitle = (TextView) view.findViewById(R.id.addCategory_chooseItem_TextView);
etInput = (EditText) view.findViewById(R.id.addCategory_chooseItem_EditText);
}
public ViewHolder(View view, Context context) {
columnDetailsLayout = (LinearLayout) view.findViewById(R.id.columnDetailsLayout);
radiogroup = (RadioGroup) view.findViewById(R.id.radiogroup_addSubCategory_chooseItem);
rbText = (RadioButton) view.findViewById(R.id.rbText_addSubCategory_chooseItem);
rbNumber = (RadioButton) view.findViewById(R.id.rbNumber_addSubCategory_chooseItem);
rbRadioButton = (RadioButton) view.findViewById(R.id.rbRadioButton_addSubCategory_chooseItem);
rbCheckbox = (RadioButton) view.findViewById(R.id.rbCheckbox_addSubCategory_chooseItem);
rbDropdown = (RadioButton) view.findViewById(R.id.rbDropdown_addSubCategory_chooseItem);
defaultValues = (EditText) view.findViewById(R.id.defaultValues_addSubCategory_chooseItem);
rbText.setChecked(true);
}
}
This is the output:
This is the error I'm getting after app gets crashed
E/AndroidRuntime: FATAL EXCEPTION: main
Process: global.edios.inventorymanagementtabletapp, PID: 2927
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.drawable.Drawable.setBounds(android.graphics.Rect)' on a null object reference
at android.widget.ExpandableListView.drawDivider(ExpandableListView.java:536)
at android.widget.ListView.dispatchDraw(ListView.java:3288)
at android.widget.ExpandableListView.dispatchDraw(ExpandableListView.java:353)
at android.view.View.draw(View.java:15234)
at android.widget.AbsListView.draw(AbsListView.java:4110)
at android.view.View.updateDisplayListIfDirty(View.java:14167)
at android.view.View.getDisplayList(View.java:14189)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368)
at android.view.View.updateDisplayListIfDirty(View.java:14127)
at android.view.View.getDisplayList(View.java:14189)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368)
at android.view.View.updateDisplayListIfDirty(View.java:14127)
at android.view.View.getDisplayList(View.java:14189)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368)
at android.view.View.updateDisplayListIfDirty(View.java:14127)
at android.view.View.getDisplayList(View.java:14189)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3389)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3368)
at android.view.View.updateDisplayListIfDirty(View.java:14127)
at android.view.View.getDisplayList(View.java:14189)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2530)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2352)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1982)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Please help. Thanks.
This crash has occurred due to Expandable List View and invoking Text Watcher.
and using multiple Text Watcher's for both parent and child item.
Plus you even change Radio Group.
Try Changing text Watcher with Something else
Heyy, the app was crashed due to divider used in expandable view .. i removed the divider from expandable list and added a custom view instead of divider in
<ExpandableListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/layout_SelectAll"
android:background="#color/colorWhite"
android:divider="#null"
android:groupIndicator="#null"
android:paddingBottom="70dp"
/>
Problem solved :)

ClassCastException in Android RecyclerAdapter

I'm having a very difficult time understanding why I'm getting a ClassCastException in my RecyclerAdapter class. I have set it up to accept two different types of views, one for regular feed items and the other for native advertisements. What is going wrong?
In my main activity, I call my constructor as follows:
feedItems = new ArrayList<>();
List<Feed> adItems = new ArrayList<>();
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
marketFeedRecyclerAdapter = new MarketFeedRecyclerAdapter(this, feedItems, new ImageLoader(new FeedItemFileCache(this)), adItems);
I get a complaint at this line in my RecyclerAdapter class, with the stack trace to follow:
bindAdItemView((AdViewHolder) viewHolder);
My stack trace:
java.lang.ClassCastException:
com.elgami.utility.LoadingRowRecyclerAdapter$LoadingViewHolder cannot be cast to com.elgami.market.MarketFeedRecyclerAdapter$AdViewHolder
at com.elgami.market.MarketFeedRecyclerAdapter.onBindViewHolder(MarketFeedRecyclerAdapter.java:80)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5768)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5801)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5037)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4913)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2029)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3260)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3069)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3518)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:598)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
at android.view.View.layout(View.java:16636)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2678)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2171)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1931)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at an
The following is my RecyclerAdapter class:
public class MarketFeedRecyclerAdapter extends LoadingRowRecyclerAdapter {
private static final int VIEW_TYPE_MARKET_FEED = 0;
private static final int VIEW_TYPE_AD = 1;
private final Context context;
private final List<Feed> feedItems;
private final ImageLoader feedItemImageLoader;
private FeedItemClickListener feedItemClickListener;
private boolean isLongPressed = false;
public MarketFeedRecyclerAdapter(Context context, List<Feed> feedItems, ImageLoader feedItemImageLoader, List<Feed> adItems) {
this.context = context;
this.feedItems = feedItems;
this.feedItemImageLoader = feedItemImageLoader;
this.feedItems.addAll(adItems);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_MARKET_FEED:
return new MarketFeedViewHolder(new FeedItemView(context));
case VIEW_TYPE_AD:
return new AdViewHolder(new MarketFeedAdItemView(context));
}
return super.onCreateViewHolder(parent, viewType);
}
// Differentiate between feedItem views and nativeAds
#Override
public int getViewType(int position) {
int viewType = VIEW_TYPE_MARKET_FEED;
if ((position % 25 == 0)) {
viewType = VIEW_TYPE_AD;
}
return viewType;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (getViewType(position) == VIEW_TYPE_MARKET_FEED) {
bindMarketFeedItemView((MarketFeedViewHolder) viewHolder, position - position / 6);
} else {
bindAdItemView((AdViewHolder) viewHolder);
}
}
// For Ad Objects
private void bindAdItemView(AdViewHolder viewHolder) {
showNativeAd(viewHolder);
}
private void bindMarketFeedItemView(MarketFeedViewHolder viewHolder, int position) {
final FeedItemView feedItemView = viewHolder.feedItemView;
final Feed feedDesign = feedItems.get(position);
// TODO we can probably conditionally show or hide these based on the type of feed item, same as in FeedActivitySingle
feedItemView.showOrHideEditButton(false);
feedItemView.showOrHideBuyButton(true);
feedItemView.showOrHideFlipButton(feedDesign.getDesign().getCompressedBackImage() != null);
feedItemView.showOrHidePriceText(true);
// Set the results into TextViews
feedItemView.setProductPriceText(String.valueOf(feedDesign.getDesign().getPrice()));
feedItemView.setDownloadsText(String.valueOf(feedDesign.getDesign().getDownloadCount()));
feedItemView.setLikesText(String.valueOf(feedDesign.getDesign().getLikesCount()));
feedItemView.setUsernameText(feedDesign.getDesign().getAuthor().getUsername());
feedItemView.setTimestampText(feedDesign.getTimestampText());
feedItemView.getSaveImage().setImageResource(feedDesign.isInPersonalGallery() ? R.drawable.ic_action_saved : R.drawable.ic_not_saved);
feedItemView.getLikeImage().setImageResource(feedDesign.isLiked() ? R.drawable.ic_action_like_feed_full : R.drawable.ic_action_like_feed);
feedItemView.getTrashImage().setVisibility(ParseHelper.isCurrentUser(feedDesign.getDesign().getAuthor().getObjectId()) ? View.VISIBLE : View.GONE);
feedItemView.getFeedSocialShareImage().setVisibility(View.VISIBLE);
switch(feedDesign.getDisplayedSide()) {
case FRONT:
feedItemImageLoader.DisplayImage(feedDesign.getDesign().getCompressedImage().getUrl(), feedItemView.getImage(), feedItemView.getProgressBar());
break;
case BACK:
feedItemImageLoader.DisplayImage(feedDesign.getDesign().getCompressedBackImage().getUrl(), feedItemView.getImage(), feedItemView.getProgressBar());
break;
}
if(feedDesign.getDesign().getAuthor().getProfilePicture() != null) {
feedItemImageLoader.DisplayImage(feedDesign.getDesign().getAuthor().getProfilePicture().getUrl(), feedItemView.getProfilePicture(), null); // TODO should this use profilePictureFileCache?
} else {
viewHolder.feedItemView.getProfilePicture().setImageResource(R.drawable.ic_anonymous);
}
SetCommentViews(feedItemView, feedDesign.getComments());
SetClickListeners(feedItemView, feedDesign, position);
}
#Override
protected int getContentDataSize() {
return feedItems.size();
}
class MarketFeedViewHolder extends RecyclerView.ViewHolder {
FeedItemView feedItemView;
public MarketFeedViewHolder(FeedItemView view) {
super(view);
this.feedItemView = view;
}
}
class AdViewHolder extends RecyclerView.ViewHolder {
MarketFeedAdItemView adItemView;
public AdViewHolder(MarketFeedAdItemView view) {
super(view);
this.adItemView = view;
}
}
private NativeAd nativeAd;
private AdChoicesView adChoicesView;
private void showNativeAd(AdViewHolder viewHolder){
AdSettings.addTestDevice("a6ffb7bec7af13f768f033dbfea042df");
nativeAd = new NativeAd(context, "846223392142435_1025413774223395");
nativeAd.setAdListener(new AdListener() {
#Override
public void onError(Ad ad, AdError adError) {
}
#Override
public void onAdLoaded(Ad ad) {
final MarketFeedAdItemView adItemView = viewHolder.adItemView;
// Setting the Text
adItemView.nativeAdSocialContext.setText(nativeAd.getAdSocialContext());
adItemView.nativeAdCallToAction.setText(nativeAd.getAdCallToAction());
adItemView.nativeAdTitle.setText(nativeAd.getAdTitle());
adItemView.nativeAdBody.setText(nativeAd.getAdBody());
// Downloading and setting the ad icon
NativeAd.Image adIcon = nativeAd.getAdIcon();
NativeAd.downloadAndDisplayImage(adIcon, adItemView.nativeAdIcon);
// Download and setting the cover image
/*NativeAd.Image adCoverImage = nativeAd.getAdCoverImage();*/
adItemView.nativeAdMedia.setNativeAd(nativeAd);
// Add adChoices icon
if (adChoicesView == null) {
adChoicesView = new AdChoicesView(context, nativeAd, true);
adItemView.addView(adChoicesView, 0);
}
nativeAd.registerViewForInteraction(adItemView);
}
#Override
public void onAdClicked(Ad ad) {
}
});
nativeAd.loadAd();
}
}
My RecyclerAdapter extends the following class, which helps with loading more feedItems:
public abstract class LoadingRowRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int ROW_VIEW_TYPE_LOADING = 72398; // obscure number
private boolean mContainsLoadingRow;
protected abstract int getContentDataSize();
protected abstract int getViewType(int position);
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case ROW_VIEW_TYPE_LOADING:
return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.loading_row, parent, false));
}
throw new IllegalArgumentException("viewType is not ROW_VIEW_TYPE_LOADING. You must handle all other values of viewType (defined by getViewType) before calling super.");
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// empty
}
#Override
public final int getItemCount() {
return mContainsLoadingRow ? (getContentDataSize() + 1) : getContentDataSize();
}
#Override
public int getItemViewType(int position) {
return (position == getContentDataSize()) ? ROW_VIEW_TYPE_LOADING : getViewType(position);
}
/**
* Sets a boolean which is used by getItemCount and in turn getItemViewType to determine which view type the row should be (loading view vs. other view).
* Should only be called when there is more results to load in an upcoming api request (determined by calling fragment).
*/
public void toggleLoadingRowOn() {
mContainsLoadingRow = true;
}
/**
* Checks to see if a loading row exists by checking an instance boolean and removes the row / clears the boolean.
* This helps to 'replace' a loading row with a different row.
*/
public void toggleLoadingRowOff() {
if (mContainsLoadingRow) {
mContainsLoadingRow = false;
// removes the loading row explicitly instead of allowing it to be 'pushed' down when new user suggestion rows are added.
// this is only required to maintain consistency with the rest of the app.
int position = getContentDataSize();
if (position >= 0) {
notifyItemRemoved(position);
}
}
}
protected class LoadingViewHolder extends RecyclerView.ViewHolder {
public LoadingViewHolder(View v) {
super(v);
}
}
}
Finally, the class which determines the threshold for loading more items:
public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
private static final int VISIBLE_THRESHOLD = 5; // The minimum amount of items to have below your current scroll position before loading more
private LinearLayoutManager mLinearLayoutManager;
public abstract void onLoadMore();
public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
this.mLinearLayoutManager = linearLayoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int totalItemCount = mLinearLayoutManager.getItemCount();
int firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
int visibleItemCount = recyclerView.getChildCount();
int lastItemVisible = firstVisibleItem + visibleItemCount;
// once the last visible item is within VISIBLE_THRESHOLD from the bottom, we want to load more
if ((totalItemCount - lastItemVisible) <= VISIBLE_THRESHOLD) {
onLoadMore();
}
}
}
The problem in your code is there:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (getViewType(position) == VIEW_TYPE_MARKET_FEED) {
bindMarketFeedItemView((MarketFeedViewHolder) viewHolder, position - position / 6);
} else {
bindAdItemView((AdViewHolder) viewHolder);
}
}
You are checking for current row viewType (and that's good), but you can actually have 3 possible viewType: market, ad and loading.
So when this
#Override
public int getItemViewType(int position) {
return (position == getContentDataSize()) ? ROW_VIEW_TYPE_LOADING : getViewType(position);
}
return ROW_VIEW_TYPE_LOADING you are casting a LoadingViewHolder to AdViewHolder.
That cause the ClassCastException.
For solving that just change the onBindViewHolder method to either include all three possible view types or use an else if instead of else.
Hope this helps

Categories