Loading more data in recyclerview on scroll - android-recyclerview

I am getting Json data in list which has like 100 of items. I am passing this list to the recyclerview adapter. But i want to pass only 10 items at first. after 10 items when user scrolls the list it should load more data from the list.I have Implemented the scroll listeners and other adapter.I am not sure how to pass 10 items from the json list to adapter.
ScrollListener
public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {
LinearLayoutManager layoutManager;
/**
* Supporting only LinearLayoutManager for now.
*
* #param layoutManager
*/
public PaginationScrollListener(LinearLayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0
&& totalItemCount >= getTotalPageCount()) {
loadMoreItems();
}
}
}
protected abstract void loadMoreItems();
public abstract int getTotalPageCount();
public abstract boolean isLastPage();
public abstract boolean isLoading();
}
Adapter
public class PaginationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int ITEM = 0;
private static final int LOADING = 1;
private List<Movie> movies;
private Context context;
private boolean isLoadingAdded = false;
public PaginationAdapter(Context context) {
this.context = context;
movies = new ArrayList<>();
}
public List<Movie> getMovies() {
return movies;
}
public void setMovies(List<Movie> movies) {
this.movies = movies;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case ITEM:
viewHolder = getViewHolder(parent, inflater);
break;
case LOADING:
View v2 = inflater.inflate(R.layout.item_progress, parent, false);
viewHolder = new LoadingVH(v2);
break;
}
return viewHolder;
}
#NonNull
private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
RecyclerView.ViewHolder viewHolder;
View v1 = inflater.inflate(R.layout.item_list, parent, false);
viewHolder = new MovieVH(v1);
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Movie movie = movies.get(position);
switch (getItemViewType(position)) {
case ITEM:
MovieVH movieVH = (MovieVH) holder;
movieVH.textView.setText(movie.getTitle());
break;
case LOADING:
break;
}
}
#Override
public int getItemCount() {
return movies == null ? 0 : movies.size();
}
#Override
public int getItemViewType(int position) {
return (position == movies.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
}
public void add(Movie mc) {
movies.add(mc);
notifyItemInserted(movies.size() - 1);
}
public void addAll(List<Movie> mcList) {
for (Movie mc : mcList) {
add(mc);
}
}
public void remove(Movie city) {
int position = movies.indexOf(city);
if (position > -1) {
movies.remove(position);
notifyItemRemoved(position);
}
}
public void clear() {
isLoadingAdded = false;
while (getItemCount() > 0) {
remove(getItem(0));
}
}
public boolean isEmpty() {
return getItemCount() == 0;
}
public void addLoadingFooter() {
isLoadingAdded = true;
add(new Movie());
}
public void removeLoadingFooter() {
isLoadingAdded = false;
int position = movies.size() - 1;
Movie item = getItem(position);
if (item != null) {
movies.remove(position);
notifyItemRemoved(position);
}
}
public Movie getItem(int position) {
return movies.get(position);
}
public MovieVH(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.item_text);
}
}
protected class LoadingVH extends RecyclerView.ViewHolder {
public LoadingVH(View itemView) {
super(itemView);
}
}
}
**Getting Api response **
private void callApi() {
apiInterfacePages = ApiClient.getRetrofit().create(APIInterface.class);
Call<CamerasItem> camerasCall = apiInterfacePages.getCameras();
camerasCall.enqueue(new Callback<CamerasItem>() {
#Override
public void onResponse(Call<CamerasItem> call, Response<CamerasItem> response) {
CamerasItem camerasItem = response.body();
itemList = new ArrayList<>();
itemList = camerasItem.getItems();
Log.i("Item", "" + getChannel().getName());
for (int i = 0; i < itemList.size(); i++) {
if (itemList.get(i).getCategory().equals(getChannel().getName())){
if (!itemList.get(i).getUrlMjpeg().endsWith("=mediaRedirect")) {
String videoUrl = itemList.get(i).getUrlMjpeg();
String imageUrl = itemList.get(i).getThumbnail();
String name = itemList.get(i).getName();
String city = itemList.get(i).getCity();
String flag = itemList.get(i).getFlag();
String country= itemList.get(i).getCountry();
modelList.add(new MyModel(videoUrl, imageUrl, name, city, flag,country));
}
}
}
#Override
public void onFailure(Call<CamerasItem> call, Throwable t) {
Log.i("Item", "" + t.getMessage());
}
});
}
So now how to pass to 10 items to recyclerview for the first time and 10 items at each scroll.

You have to set Progressbar inside the activity's xml where Recyclerview is defined.
and loadThumbnail is a function to download thumbnail. it just gives a little delay to scroll down. Now the complete code for the adapter class is as following
public class CamerasAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<MyModel> list;
private Activity mActivity;
private static final int TYPE_VIDEO = 0, TYPE_ADD = 1;
private static final int PAGE_LIMIT = 5;
private int mCurrentLimit = PAGE_LIMIT;
private boolean mIsLoading;
RelativeLayout mLoaderProgress;
public CamerasAdapter(FragmentActivity activity, RelativeLayout loaderLayout) {
mActivity = activity;
mLoaderProgress = loaderLayout;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.li_web_cam_view, viewGroup, false);
return new CamsViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int i) {
if (mCurrentLimit == (i + 1) && mCurrentLimit <= list.size() && !mIsLoading) {
mLoaderProgress.setVisibility(View.VISIBLE);
mIsLoading = true;
loadThumbnail(0, i + 1);
} else {
//do nothing
}
((CamsViewHolder) viewHolder).onBindData(mActivity, list.get(i), i);
((CamsViewHolder) viewHolder).emptyView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
itemClickListner.onClick(i, ((CamsViewHolder) viewHolder).tvCamName, list.get(i));
}
});
}
private void loadThumbnail(final int count, int position) {
try {
if (count > 2 || position >= list.size()) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mIsLoading = false;
mCurrentLimit = mCurrentLimit + PAGE_LIMIT;
notifyItemChanged(position - count);
mLoaderProgress.setVisibility(View.GONE);
return;
}
}, 2000);
} else {
if (list.get(position) == null) {
loadThumbnail(count, position + 1);
} else {
Glide.with(mActivity).load(list.get(position).getImage_url()).downloadOnly(new SimpleTarget<File>() {
#Override
public void onResourceReady(File resource, GlideAnimation<? super File> glideAnimation) {
loadThumbnail((count + 1), (position + 1));
}
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
loadThumbnail((count + 1), (position + 1));
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
mLoaderProgress.setVisibility(View.GONE);
mIsLoading = false;
}
}
#Override
public int getItemCount() {
return mCurrentLimit <= list.size() ? mCurrentLimit : list.size();
}
public void setData(List<MyModel> dataList) {
this.list = dataList;
notifyDataSetChanged();
}
ItemClickListner itemClickListner;
public void setListener(ItemClickListner listener) {
itemClickListner = listener;
}
ProgressLoadListener progressLoadListener;
public void setProgressLoadListener(ProgressLoadListener listener) {
progressLoadListener = listener;
}
}
code for xml file
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="match_parent"
android:layout_above="#+id/loader_progress_bar_layout"
android:background="#f5f5f5"
android:layout_gravity="center" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:id="#+id/loader_progress_bar_layout"
android:visibility="gone"
android:background="#fff"
>
<ProgressBar
android:id="#+id/progress_bar_loader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center" />
</RelativeLayout>
initialize Recyclerview with adapter
public class Main2Activity extends AppCompatActivity {
RecyclerView recyclerView;
RelativeLayout layoutProgressBar;
CamerasAdapter adapter;
List<Item> itemList;
LinearLayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
layoutProgressBar = findViewById(R.id.loader_progress_bar_layout);
recyclerView = findViewById(R.id.recycler_view);
adapter = new CamerasAdapter(getActivity(), loaderLayout);
mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(adapter);
adapter.setProgressLoadListener(new ProgressLoadListener() {
#Override
public void loadProgressBar() {
layoutProgressBar.setVisibility(View.VISIBLE);
}
});
adapter.setData(setAdaperData());
}
public List<MyModel> setAdaperData(){
List<MyModel> modelList = new ArrayList<>();
/*addItemsto list*/
return modelList;
}
}

Related

How to implement an Action on Item Click in Order to show the result in CardView of RecyclerView

I am very new to Android programming. I can't find a solution for my current problem which I've been trying to solve for days.
I want to click on item of populated Array List and get the position i.e. the searched word result in Cardview (neither ItemClickListener nor OnSuggestionListener did work here. Here is my code of MainActivity and I would be very thankful if somebody could help me out:
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
SearchAdapter adapter;
MaterialSearchBar materialSearchBar;
List<String> suggestList = new ArrayList<>();
Database database;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//init View
recyclerView = (RecyclerView) findViewById(R.id.recycler_search);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
materialSearchBar = (MaterialSearchBar) findViewById(R.id.search_bar);
database = new Database(this);
materialSearchBar.setHint("Search");
materialSearchBar.setCardViewElevation(10);
loadSuggestList();
materialSearchBar.addTextChangeListener (new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
List<String> suggest = new ArrayList<>();
for (String search : suggestList) {
if (search.toLowerCase().contains(materialSearchBar.getText().toLowerCase()))
suggest.add(search);
}
materialSearchBar.setLastSuggestions(suggest);
}
#Override
public void afterTextChanged(Editable s) {
}
});
materialSearchBar.setOnSearchActionListener (new MaterialSearchBar.OnSearchActionListener() {
#Override
public void onSearchStateChanged(boolean enabled) {
if (!enabled)
adapter = new SearchAdapter(getBaseContext(), database.getLughats());
recyclerView.setAdapter(adapter);
}
#Override
public void onSearchConfirmed(CharSequence text) {
startSearch(text.toString());
}
#Override
public void onButtonClicked(int buttonCode) {
}
});
adapter = new SearchAdapter(this, database.getLughats());
recyclerView.setAdapter(adapter);
}
private void startSearch(String text) {
adapter = new SearchAdapter(this, database.getLughatByWort(text));
recyclerView.setAdapter(adapter);
}
private void loadSuggestList() {
suggestList = database.getWorts();
materialSearchBar.setLastSuggestions(suggestList);
}
}```
Let me know if I should post here also my AdapterCode for the ViewHolder.
Thank you for your help in advance!
Here ist my AdapterCode:
class SearchViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
RecyclerItemClick itemClickListener;
public TextView wort, praeteritum, partizip2, artikelGrammatik, uebersetzung1, uebersetzung2;
public ImageButton button1, button2;
public SearchViewHolder(#NonNull View itemView) {
super(itemView);
wort = (TextView)itemView.findViewById(R.id.wort);
praeteritum = (TextView)itemView.findViewById(R.id.praeteritum);
partizip2 = (TextView)itemView.findViewById(R.id.partizip2);
artikelGrammatik = (TextView)itemView.findViewById(R.id.artikelGrammatik);
uebersetzung1 = (TextView)itemView.findViewById(R.id.uebersetzung1);
uebersetzung2 = (TextView)itemView.findViewById(R.id.uebersetzung2);
button1 = (ImageButton)itemView.findViewById(R.id.button_id_1);
button2 = (ImageButton) itemView.findViewById(R.id.button_id_2);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
this.itemClickListener.onItemClickListener(v, getLayoutPosition());
}
public void setItemClickListener(RecyclerItemClick ic) {
this.itemClickListener = ic;
}
}
public class SearchAdapter extends RecyclerView.Adapter<SearchViewHolder> {
private Context context;
private List<Lughat> lughats;
public SearchAdapter(Context context, List<Lughat> lughats) {
this.context = context;
this.lughats = lughats;
}
#NonNull
#Override
public SearchViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final View itemView = inflater.inflate(R.layout.layout_item, parent, false);
return new SearchViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final SearchViewHolder holder, final int position) {
holder.wort.setText(lughats.get(position).getWort());
holder.praeteritum.setText(lughats.get(position).getPraeteritum());
holder.partizip2.setText(lughats.get(position).getPartizip2());
holder.artikelGrammatik.setText(lughats.get(position).getArtikelGrammatik());
holder.uebersetzung1.setText(lughats.get(position).getUebersetzung1());
holder.uebersetzung2.setText(lughats.get(position).getUebersetzung2());
CharSequence praet;
praet = holder.praeteritum.getText();
if (praet.length() == 0) {
holder.praeteritum.setVisibility(View.GONE);
holder.button1.setVisibility(View.GONE);
} else {
holder.praeteritum.setVisibility(View.VISIBLE);
holder.button1.setVisibility(View.VISIBLE);
}
CharSequence part2;
part2 = holder.partizip2.getText();
if (part2.length() == 0) {
holder.partizip2.setVisibility(View.GONE);
} else {
holder.partizip2.setVisibility(View.VISIBLE);
}
CharSequence artGr;
artGr = holder.artikelGrammatik.getText();
if (artGr.length() == 0) {
holder.artikelGrammatik.setVisibility(View.GONE);
holder.button2.setVisibility(View.GONE);
} else {
holder.artikelGrammatik.setVisibility(View.VISIBLE);
holder.button2.setVisibility(View.VISIBLE);
}
CharSequence ueb2;
ueb2 = holder.uebersetzung2.getText();
if (ueb2.length() == 0) {
holder.uebersetzung2.setVisibility(View.GONE);
} else {
holder.uebersetzung2.setVisibility(View.VISIBLE);
}
holder.button1.setOnClickListener(new ToastMaker(context.getApplicationContext()));
holder.button2.setOnClickListener(new ToastMaker(context.getApplicationContext()));
holder.setItemClickListener(new RecyclerItemClick() {
#Override
public void onItemClickListener(View v, int position) {
Toast.makeText(context, "Begriff", Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
return lughats.size();
}
}
If I do it also with OnClickListener it does not work too, it does not call the method startSearch.
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CharSequence text = materialSearchBar.getText();
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG).show();
startSearch(text.toString());
}

how to confirm selected items in recyclerview item list and make selected on layout

i am preparing textview seat numbers list by using recyclerview grid layout manager. i can select the multiple items in the recyclerview list by red color. now i want to keep this seat item selected as red color when on cliking on confirm seat button. when i reopen the recyclerview list it should show the seat selected red color and other seat item in normal color.
confirm seat button clickconfrim seat button click
SelectionAdapter
'''
public class SelectionAdapter extends RecyclerView.Adapter<SelectionAdapter.MygridViewHolder> {
private Context applicationContext;
private ArrayList<Seatnos> list, selected;
public SelectionAdapter(Context applicationContext, ArrayList<Seatnos> list) {
this.applicationContext = applicationContext;
this.list = list;
this.selected = new ArrayList<>();
}
#NonNull
#Override
public MygridViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater=LayoutInflater.from(parent.getContext());
View view=layoutInflater.inflate(R.layout.list_layout_selection,parent,false);
return new MygridViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final MygridViewHolder holder, final int position) {
final Seatnos seatnos = list.get(position);
holder.textView.setText(String.valueOf(position));
holder.textView.setText(seatnos.getTextno());
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (selected.contains(seatnos)) {
selected.remove(seatnos);
unhighlightView(holder);
} else {
selected.add(seatnos);
highlightView(holder);
}
}
});
if (selected.contains(seatnos))
highlightView(holder);
else
unhighlightView(holder);
}
private void highlightView(MygridViewHolder holder) {
holder.itemView.setBackgroundColor(ContextCompat.getColor(applicationContext, R.color.red));
}
private void unhighlightView(MygridViewHolder holder) {
holder.itemView.setBackgroundColor(ContextCompat.getColor(applicationContext, android.R.color.transparent));
}
#Override
public int getItemCount() {
return list.size();
}
class MygridViewHolder extends RecyclerView.ViewHolder {
TextView textView;
MygridViewHolder(#NonNull View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.textViewsA);
}
}
public void addAll(ArrayList<Seatnos> list) {
clearAll(false);
this.list = list;
notifyDataSetChanged();
}
public void clearAll(boolean isNotify) {
list.clear();
selected.clear();
if (isNotify) notifyDataSetChanged();
}
public void clearSelected() {
selected.clear();
notifyDataSetChanged();
}
public void selectAll() {
selected.clear();
selected.addAll(list);
notifyDataSetChanged();
}
public ArrayList<Seatnos> getSelected() {
return selected;
}
}
'''
SeatSelectionactivity.java
'''
public class SeatSelectionActivity extends AppCompatActivity {
RecyclerView recyclerView;
Activity activity = SeatSelectionActivity.this;
Button btnGetSelected,btnreset;
FirebaseDatabase database;
DatabaseReference ref;
SelectionAdapter selectionAdapter;
ArrayList<Seatnos> list;
Update update;
ChildEventListener mChildListner;
ValueEventListener mValueEventListner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seat_selection);
btnGetSelected = (Button) findViewById(R.id.btconfirm);
recyclerView=(RecyclerView) findViewById(R.id.viewseat);
list = new ArrayList<>();
String uid = getIntent().getStringExtra(UpdateAdapter.USER_KEY);
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("updates").child(uid);
selectionAdapter=new SelectionAdapter(this, list);
RecyclerView.LayoutManager layoutManager=new GridLayoutManager(this,4);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
mValueEventListner = new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
Update update =dataSnapshot.getValue(Update.class);
update.setUid(dataSnapshot.getKey());
int seat= Integer.parseInt(update.getSeat());
ArrayList<String> array = new ArrayList<String>(seat);
for(long i=0; i<seat; i++) {
array.add(String.valueOf(i));
Seatnos seatnos = new Seatnos();
seatnos.setTextno(""+(i+1));
if(i==0){
seatnos.setChecked(true);
}
list.add(seatnos);
}
recyclerView.setAdapter(selectionAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
databaseReference.addValueEventListener(mValueEventListner);
}
public void reset(View view) {
}
public void bookconfirm(View view) {
if (selectionAdapter.getSelected().size() > 0) {
//ArrayList<Integer> mlist = new ArrayList<>();
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < selectionAdapter.getSelected().size(); i++) {
stringBuilder.append(selectionAdapter.getSelected().get(i).getTextno());
stringBuilder.append("\n");
}
Toast.makeText(activity, String.format("Selected %d items", selectionAdapter.getSelected().size()), Toast.LENGTH_SHORT).show();
showToast(stringBuilder.toString().trim());
} else {
showToast("No Selection");
}
};
public void selectAll(View v) {
selectionAdapter.selectAll();
}
public void deselectAll(View v) {
selectionAdapter.clearSelected();
}
public void doAction(View v) {
Toast.makeText(activity, String.format("Selected %d items", selectionAdapter.getSelected().size()), Toast.LENGTH_SHORT).show();
}
private void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
'''
model class
'''
public class Seatnos implements Serializable {
String textno;
String sid;
private boolean isChecked = false;
public Seatnos() {
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public Seatnos(String textno) {
this.textno = textno;
}
public String getTextno() {
return textno;
}
public void setTextno(String textno) {
this.textno = textno;
}
}
'''
You would use shared preferences to save the state of the selected item:
Do this in onBindViewHolder:
#Override
public void onBindViewHolder(#NonNull final MygridViewHolder holder, final int position) {
final Seatnos seatnos = list.get(position);
holder.textView.setText(String.valueOf(position));
holder.textView.setText(seatnos.getTextno());
//read from preferences
SharedPreferences pref = getSharedPreferences("item", MODE_PRIVATE);
String state = pref.getString(String.valueOf(position)+"state", "default");
if(state.equals("selected")){
//selected
highlightView(holder);
}else{
//not selected
unhighlightView(holder);
}
//on click
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (selected.contains(seatnos)) {
selected.remove(seatnos);
unhighlightView(holder);
//save state
SharedPreferences.Editor editor = getSharedPreferences("item", MODE_PRIVATE).edit();
editor.putString(String.valueOf(position)+"state", "not_selected");
editor.apply();
} else {
selected.add(seatnos);
highlightView(holder);
//save state
SharedPreferences.Editor editor = getSharedPreferences("item", MODE_PRIVATE).edit();
editor.putString(String.valueOf(position)+"state", "selected");
editor.apply();
}
}
});
......................
......................
......................
}
UPDATE:
Yes you should use the context passed to your adapter to access the shared prederences:
This:
getSharedPreferences("item", MODE_PRIVATE);
Becomes:
applicationContext.getSharedPreferences("item", MODE_PRIVATE);
This:
getSharedPreferences("item", MODE_PRIVATE).edit();
Becomes:
applicationContext.getSharedPreferences("item", MODE_PRIVATE).edit();

RecyclerView: incorrect binding when items are recycled

Each item in my RecyclerView consists of 4 EditTexts.
As long as no item is recycled, my app can change the text in any of these EditTexts.
However, as soon as items are recycled, only the first (I mean the leftmost) Edittext in the item can be updated correctly, whatever the selection.
Any idea of what could go wrong?
This is the top of the stack:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: be.ema.moles, PID: 8968
java.lang.NullPointerException: Attempt to invoke virtual method 'int androidx.recyclerview.widget.RecyclerView$ViewHolder.getAdapterPosition()' on a null object reference
at androidx.recyclerview.selection.StableIdKeyProvider.onDetached(StableIdKeyProvider.java:90)
at androidx.recyclerview.selection.StableIdKeyProvider$1.onChildViewDetachedFromWindow(StableIdKeyProvider.java:69)
at androidx.recyclerview.widget.RecyclerView.dispatchChildDetached(RecyclerView.java:7261)
at androidx.recyclerview.widget.RecyclerView.removeDetachedView(RecyclerView.java:4139)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.removeAndRecycleScrapInt(RecyclerView.java:8978)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:3997)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3652)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4194)
at android.view.View.layout(View.java:20672)
...
Here is the Fragment controlling the contents of the RecyclerView
public class MoleFragment extends Fragment {
RecyclerView moleRecycler = null;
TextView addBtn = null;
Cursor moleCursor = null;
static int moleAdapterPosition = 0;
static String moleId = "";
static String contactId = "";
static String rawContactId = "";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.moles_layout, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final Cursor moleCursor = readMoles();
moleRecycler = (RecyclerView) getActivity().findViewById(R.id.moles);
moleRecycler.setHasFixedSize(true);
moleRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
moleRecycler.setAdapter(new MolesCursorAdapter(getActivity(), moleCursor));
OnItemActivatedListener<Long> moleItemActivatedListener = new OnItemActivatedListener() {
#Override
public boolean onItemActivated(#NonNull ItemDetailsLookup.ItemDetails item, #NonNull MotionEvent e) {
moleAdapterPosition = item.getPosition();
moleCursor.moveToPosition(item.getPosition());
moleId = Long.toString(moleCursor.getLong(0));
return true;
}
};
SelectionTracker moleTracker = new SelectionTracker.Builder<Long>("selectedMoleId",
moleRecycler,
new StableIdKeyProvider(moleRecycler),
new MoleDetailsLookup(),
StorageStrategy.createLongStorage())
.withSelectionPredicate(SelectionPredicates.<Long>createSelectSingleAnything())
.withOnItemActivatedListener(moleItemActivatedListener)
.build();
return ;
}
public Cursor readMoles() {
String[] contactIds = getShownCustomer();
String selection = Data.RAW_CONTACT_ID + "=? AND " + Data.CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?";
String[] selectionArgs = new String[]{contactIds[0], contactIds[1], MOLE_MIME_TYPE};
return moleCursor = getActivity().getContentResolver().query(
Data.CONTENT_URI,
new String[] {
Data._ID,
Data.DATA1,
Data.DATA2,
Data.DATA3,
Data.DATA4},
selection,
selectionArgs,
null
);
}
/**
* Create a new instance of DetailsFragment, initialized to
* show the catches for customer 'contactId'.
*/
public static MoleFragment newInstance(String rawContactId, String contactId) {
MoleFragment f = new MoleFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putString("rawContactId", rawContactId);
args.putString("contactId", contactId);
f.setArguments(args);
return f;
}
public String[] getShownCustomer() {
rawContactId = getArguments().getString("rawContactId", "");
contactId = getArguments().getString("contactId", "");
String[] contactIds = new String[2];
contactIds[0] = getArguments().getString("rawContactId", "");
contactIds[1] = getArguments().getString("contactId", "");
return contactIds;
}
private class MoleDetailsLookup extends ItemDetailsLookup<Long> {
#Nullable
#Override
public ItemDetails<Long> getItemDetails(#NonNull MotionEvent event) {
View view = moleRecycler.findChildViewUnder(event.getX(), event.getY());
if (view != null) {
final RecyclerView.ViewHolder viewHolder = moleRecycler.getChildViewHolder(view);
if (viewHolder instanceof MolesCursorAdapter.ViewHolder) {
final MolesCursorAdapter.ViewHolder moleViewHolder = (MolesCursorAdapter.ViewHolder) viewHolder;
return new ItemDetailsLookup.ItemDetails<Long>() {
#Override
public int getPosition() {
return viewHolder.getAdapterPosition();
}
#Nullable
#Override
public Long getSelectionKey() {
return Long.valueOf(moleViewHolder.position);
}
};
}
}
return null;
}
}
}
And this is the RecyclerView.Adapater
public class MolesCursorAdapter extends RecyclerView.Adapter<MolesCursorAdapter.ViewHolder> {
private CursorAdapter mCursorAdapter;
private Context mContext;
private ViewHolder holder;
public MolesCursorAdapter(Context context, Cursor c) {
mContext = context;
mCursorAdapter = new CursorAdapter(mContext, c, 0) {
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View v = LayoutInflater.from(context).inflate(R.layout.moles, parent, false);
return v;
}
#Override
public void bindView(View view, final Context context, final Cursor cursor) {
String s = cursor.getString(1);
if (s != null) {
holder.startDate.setText(s.substring(6, 8) + "/" + s.substring(4, 6) + "/" + s.substring(0, 4));
} else {
holder.startDate.setText("");
}
s = cursor.getString(2);
if (s != null) {
s = s.substring(6,8) + "/" + s.substring(4,6) + "/" + s.substring(0,4);
holder.endDate.setText(s);
} else {
holder.endDate.setText("");
}
holder.round.setText(cursor.getString(3));
holder.moleType.setText(cursor.getString(4));
}
};
}
public class ViewHolder extends RecyclerView.ViewHolder implements TextWatcher {
public int position;
public EditText startDate;
public EditText endDate;
public EditText round;
public EditText moleType;
public TextView deleteBtn;
public ViewHolder(View itemView) {
super(itemView);
startDate = (EditText) itemView.findViewById(R.id.startDate);
endDate = (EditText) itemView.findViewById(R.id.endDate);
round = (EditText) itemView.findViewById(R.id.round);
moleType = (EditText) itemView.findViewById(R.id.moleType);
deleteBtn = (TextView) itemView.findViewById(R.id.deleteBtn);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
String value = s.toString();
ContentValues newValues = new ContentValues();
if (TextUtils.isDigitsOnly(s)) {
newValues.put(ContactsContract.Data.DATA3, value);
} else {
newValues.put(ContactsContract.Data.DATA4, value);
}
updateRepository(newValues);
}
}
#Override
public int getItemCount() {
return mCursorAdapter.getCount();
}
#Override
public long getItemId(int position) {
return Long.valueOf(position);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// Passing the binding operation to cursor loader
mCursorAdapter.getCursor().moveToPosition(position);
mCursorAdapter.bindView(holder.itemView, mContext, mCursorAdapter.getCursor());
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextWatcher tw = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
String value = s.toString();
ContentValues newValues = new ContentValues();
if (TextUtils.isDigitsOnly(s)) {
newValues.put(ContactsContract.Data.DATA3, value);
} else {
newValues.put(ContactsContract.Data.DATA4, value);
}
updateRepository(newValues);
}
};
View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
holder = new ViewHolder(v);
holder.startDate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
// business logic
}
});
holder.endDate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
// business logic
}
});
holder.round.addTextChangedListener(tw);
holder.moleType.addTextChangedListener(tw);
holder.deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String selectionClause = ContactsContract.Data._ID + "=?";
String[] selectionArgs = new String[] {mCursorAdapter.getCursor().getString(0)};
int rowsDeleted = mContext.getContentResolver().delete(
ContactsContract.Data.CONTENT_URI,
selectionClause,
selectionArgs
);
}
});
return holder;
}
}
Instead of adding a ClickListener on each View in the ViewHolder in the onCreateViewHolder method, I have added a unique tag on each View. This unique tag is used in a general (I mean at Class level) ClickListener to perform the business logic:
public class MolesCursorAdapter3 extends RecyclerView.Adapter<MolesCursorAdapter3.MolesViewHolder> {
private CursorAdapter mCursorAdapter;
private Context mContext;
public ConstraintLayout holder;
public EditText startDate;
public EditText endDate;
public EditText round;
public EditText moleType;
public TextView deleteBtn;
public class MolesViewHolder extends RecyclerView.ViewHolder implements TextWatcher, View.OnClickListener {
public int position;
public String vhMoledId = "";
public MolesViewHolder(ConstraintLayout itemView) {
super(itemView);
holder = itemView;
startDate = (EditText) itemView.findViewById(R.id.startDate);
startDate.setOnClickListener(this);
endDate = (EditText) itemView.findViewById(R.id.endDate);
endDate.setOnClickListener(this);
round = (EditText) itemView.findViewById(R.id.round);
round.addTextChangedListener(this);
moleType = (EditText) itemView.findViewById(R.id.moleType);
moleType.addTextChangedListener(this);
deleteBtn = (TextView) itemView.findViewById(R.id.deleteBtn);
deleteBtn.setOnClickListener(this);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
String value = s.toString();
ContentValues newValues = new ContentValues();
if (TextUtils.isDigitsOnly(s)) {
newValues.put(ContactsContract.Data.DATA3, value);
} else {
newValues.put(ContactsContract.Data.DATA4, value);
}
updateRepository(newValues, vhMoledId);
}
#Override
public void onClick(final View v) {
String tag = (String) v.getTag();
String viewTag = tag.substring(0, 3);
final String moleId = tag.substring(3);
switch (viewTag) {
case "del":
// business logic
break;
case "sta":
ConstraintLayout vh = (ConstraintLayout) v.getParent();
endDate = vh.findViewWithTag("end" + moleId);
// business logic
break;
case "end":
vh = (ConstraintLayout) v.getParent();
startDate = vh.findViewWithTag("sta" + moleId);
// business logic
break;
}
}
}
public MolesCursorAdapter3(Context context, Cursor c) {
mContext = context;
mCursorAdapter = new CursorAdapter(mContext, c, 0) {
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View v = LayoutInflater.from(context).inflate(R.layout.moles, parent, false);
return v;
}
#Override
public void bindView(View itemView, final Context context, final Cursor cursor) {
ConstraintLayout vh = (ConstraintLayout) itemView;
String moleId = cursor.getString(0);
startDate = (EditText) vh.findViewById(R.id.startDate);
startDate.setTag("sta" + moleId);
endDate = (EditText) vh.findViewById(R.id.endDate);
endDate.setTag("end" + moleId);
round = (EditText) vh.findViewById(R.id.round);
moleType = (EditText) vh.findViewById(R.id.moleType);
deleteBtn = (TextView) vh.findViewById(R.id.deleteBtn);
deleteBtn.setTag("del" + moleId);
String s = cursor.getString(1);
if (s != null) {
startDate.setText(s.substring(6, 8) + "/" + s.substring(4, 6) + "/" + s.substring(0, 4));
} else {
startDate.setText("");
}
s = cursor.getString(2);
if (s != null) {
s = s.substring(6,8) + "/" + s.substring(4,6) + "/" + s.substring(0,4);
endDate.setText(s);
} else {
endDate.setText("");
}
round.setText(cursor.getString(3));
moleType.setText(cursor.getString(4));
}
};
}
#Override
public MolesCursorAdapter3.MolesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ConstraintLayout molesLayout = (ConstraintLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.moles, parent, false);
MolesViewHolder vh = new MolesViewHolder(molesLayout);
return vh;
}
#Override
public void onBindViewHolder(#NonNull MolesViewHolder holder, int position) {
// Passing the binding operation to cursor loader
mCursorAdapter.getCursor().moveToPosition(position);
mCursorAdapter.bindView(holder.itemView, mContext, mCursorAdapter.getCursor());
holder.vhMoledId = mCursorAdapter.getCursor().getString(0);
holder.position = position;
}
#Override
public int getItemCount() {
return mCursorAdapter.getCount();
}
#Override
public long getItemId(int position) {
return Long.valueOf(position);
}
public void updateRepository(ContentValues newValues, String moleId) {
final String selection = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.Data._ID + " = ?";
final String[] selectionArgs = new String[]{MOLE_MIME_TYPE, moleId};
int rowsUpdated = mContext.getContentResolver().update(
ContactsContract.Data.CONTENT_URI,
newValues,
selection,
selectionArgs
);
}
}

Single radio button check uncheck issue in recyclerview

I'm unable to play with Radio Button which is in Recyclerview. Please, check below images to get the problem.
1. First Image
2. Second Image
3. Third Image
4. Fourth Image
What is the problem?
First Image show when this screen initially comes first time. When I select anyone option it will be highlighted in green colour and appropriate radio button get checked that is shown in Second Image.
When I want to select another option, it unchecked the previous selection but not checking the new one i.e shown in Third Image.
When I again click, It get checked which is wrong. It should unchecked previous selection and checked new selection on first click only. i.e shown in Fourth Image.
My Adapter class is like below.
public class PaymentOptionsAdapter extends RecyclerView.Adapter<PaymentOptionsAdapter.ViewHolder> {
Context context;
List<String> listOfPaymentOptions;
int mCheckedPostion = -1;
private boolean isChecked = false;
public PaymentOptionsAdapter(Context context, List<String> listOfPaymentOptions) {
this.context = context;
this.listOfPaymentOptions = listOfPaymentOptions;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_payment_options, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.txtOption.setText(listOfPaymentOptions.get(position));
if (mCheckedPostion == position) {
holder.txtOption.setTextColor(context.getResources().getColor(R.color.green_txt));
holder.radioSelect.setChecked(true);
if (position == 0) {
new AppShare(context).setPaymentOption(context.getString(R.string.cod));
} else if (position == 1) {
new AppShare(context).setPaymentOption(context.getString(R.string.payu));
} else if (position == 2) {
new AppShare(context).setPaymentOption(context.getString(R.string.online));
}
} else {
holder.txtOption.setTextColor(context.getResources().getColor(R.color.black));
holder.radioSelect.setChecked(false);
}
holder.layoutContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isChecked) {
notifyItemChanged(mCheckedPostion);
mCheckedPostion = position;
notifyItemChanged(mCheckedPostion);
isChecked = true;
} else {
notifyItemChanged(mCheckedPostion);
mCheckedPostion = -1;
notifyItemChanged(position);
isChecked = false;
new AppShare(context).setPaymentOption(null);
}
}
});
holder.radioSelect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isChecked) {
notifyItemChanged(mCheckedPostion);
mCheckedPostion = position;
notifyItemChanged(mCheckedPostion);
isChecked = true;
} else {
notifyItemChanged(mCheckedPostion);
mCheckedPostion = -1;
notifyItemChanged(position);
isChecked = false;
new AppShare(context).setPaymentOption(null);
}
}
});
}
#Override
public int getItemCount() {
return listOfPaymentOptions.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
RelativeLayout layoutContainer;
TextView txtOption;
RadioButton radioSelect;
public ViewHolder(View itemView) {
super(itemView);
layoutContainer = (RelativeLayout) itemView.findViewById(R.id.layoutContainer);
txtOption = (TextView) itemView.findViewById(R.id.txtOption);
radioSelect = (RadioButton) itemView.findViewById(R.id.radioSelect);
txtOption.setTypeface(FontUtils.getInstance(context).getRobotoTypeFace());
}
}
}
row_payment_options.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/card_view_height"
android:background="#color/white"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/layoutContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtOption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingLeft="#dimen/large_margin"
android:text="TextView"
android:textColor="#color/black"
android:textSize="#dimen/text_title" />
<RadioButton
android:id="#+id/radioSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:checked="false"
android:paddingRight="#dimen/large_margin" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_alignParentBottom="true"
android:layout_marginLeft="#dimen/large_margin"
android:layout_marginRight="#dimen/x_large_margin"
android:layout_toLeftOf="#+id/radioSelect"
android:background="#color/gray_border" />
</RelativeLayout>
</RelativeLayout>
In your adapter first add local RadioButton:
private RadioButton lastCheckedRadio;
and change your onBindViewHolder like this and it should work
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.txtOption.setText(listOfPaymentOptions.get(position));
holder.radioSelect.setTag(new Integer(position));
if(position == 0 && holder.radioSelect.isChecked())
{
lastCheckedRadio = holder.radioSelect;
mCheckedPostion = 0;
}
holder.layoutContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
int clickedPos = ((Integer)holder.radioSelect.getTag()).intValue();
if(mCheckedPostion!=position)
{
if(lastCheckedRadio != null)
{
lastCheckedRadio.setChecked(false);
}
lastCheckedRadio = holder.radioSelect;
lastCheckedRadio.setChecked(true);
mCheckedPostion = clickedPos;
if (position == 0) {
new AppShare(context).setPaymentOption(context.getString(R.string.cod));
} else if (position == 1) {
new AppShare(context).setPaymentOption(context.getString(R.string.payu));
} else if (position == 2) {
new AppShare(context).setPaymentOption(context.getString(R.string.online));
}
}
else
lastCheckedRadio = holder.radioSelect;
}
});
holder.radioSelect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int clickedPos = ((Integer)holder.radioSelect.getTag()).intValue();
if(holder.radioSelect.isChecked())
{
if(lastCheckedRadio != null)
{
lastCheckedRadio.setChecked(false);
holder.layoutContainer.setFocusable(false);
}
lastCheckedRadio = holder.radioSelect;
lastCheckedRadio.setChecked(true);
mCheckedPostion = clickedPos;
if (position == 0) {
new AppShare(context).setPaymentOption(context.getString(R.string.cod));
} else if (position == 1) {
new AppShare(context).setPaymentOption(context.getString(R.string.payu));
} else if (position == 2) {
new AppShare(context).setPaymentOption(context.getString(R.string.online));
}
}
else
lastCheckedRadio = holder.radioSelect;
}
});
}
I changed my Adapter class like below. Working fine. You can check subrahmanyam boyapati's answer on This Link.
public class PaymentOptionsAdapter extends RecyclerView.Adapter<PaymentOptionsAdapter.ViewHolder> {
Context context;
List<String> listOfPaymentOptions;
private int lastCheckedPosition = -1;
public PaymentOptionsAdapter(Context context, List<String> listOfPaymentOptions) {
this.context = context;
this.listOfPaymentOptions = listOfPaymentOptions;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_payment_options, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.txtOption.setText(listOfPaymentOptions.get(position));
holder.radioSelect.setChecked(position == lastCheckedPosition);
if (lastCheckedPosition == position) {
holder.txtOption.setTextColor(context.getResources().getColor(R.color.green_txt));
holder.radioSelect.setChecked(true);
if (position == 0) {
new AppShare(context).setPaymentOption(context.getString(R.string.cod));
} else if (position == 1) {
new AppShare(context).setPaymentOption(context.getString(R.string.payu));
} else if (position == 2) {
new AppShare(context).setPaymentOption(context.getString(R.string.online));
} else {
new AppShare(context).setPaymentOption(null);
}
} else {
holder.txtOption.setTextColor(context.getResources().getColor(R.color.black));
holder.radioSelect.setChecked(false);
}
}
#Override
public int getItemCount() {
return listOfPaymentOptions.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
RelativeLayout layoutContainer;
TextView txtOption;
RadioButton radioSelect;
public ViewHolder(View itemView) {
super(itemView);
layoutContainer = (RelativeLayout) itemView.findViewById(R.id.layoutContainer);
txtOption = (TextView) itemView.findViewById(R.id.txtOption);
radioSelect = (RadioButton) itemView.findViewById(R.id.radioSelect);
txtOption.setTypeface(FontUtils.getInstance(context).getRobotoTypeFace());
layoutContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
lastCheckedPosition = getAdapterPosition();
notifyItemRangeChanged(0, listOfPaymentOptions.size());
}
});
radioSelect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
lastCheckedPosition = getAdapterPosition();
notifyItemRangeChanged(0, listOfPaymentOptions.size());
}
});
}
}
}

Recyclerview initially not scrolling smoothly while loading data from web service

I'm using recycler view as a single child inside the swipe refresh layout. Initially, its not scrolling smoothly while loading data from webservice both upwards and downwards. But after first scroll, it scrolls smoothly. How to make it scroll smoothly at very first scroll itself.
private RecyclerView newsFeedList;
newsFeedList = (RecyclerView) view.findViewById(R.id.rv_feed_list);
newsFeedList.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
llm.setOrientation(LinearLayoutManager.VERTICAL);
newsFeedList.setLayoutManager(llm);
newsFeedAdapter = new NewsFeedAdapter(getActivity(), new ArrayList<NewsFeedParser.NewsFeed>(), newsFeedList);
newsFeedList.setAdapter(newsFeedAdapter);
and updated recyclerview after getting response from web service by calling below method:
private void parseDataToNewsFeed(String response, boolean isLoadMore) {
Gson gson = new Gson();
NewsFeedParser newsFeedParser = gson.fromJson(response, NewsFeedParser.class);
if (newsFeedParser.data != null && newsFeedParser.data.size() > 0) {
if (isLoadMore) {
newsFeedAdapter.removeProgress(newsFeedAdapter.getItemCount());
newsFeedAdapter.addList(newsFeedParser.data);
} else {
currentPageCount = 1;
newsFeedAdapter.updateList(newsFeedParser.data);
}
} else {
newsFeedAdapter.updateList(newsFeedParser.data);
txtNoResult.setText(getString(R.string.no_clubs_socities_subscribed));
txtNoResult.setVisibility(View.VISIBLE);
}
}
Adaper class:
public class NewsFeedAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final DisplayImageOptions options;
private Context context;
private ArrayList<NewsFeedParser.NewsFeed> itemList;
private int lastVisibleItem, totalItemCount, visibleThreshold = 2;
private boolean loading;
public OnLoadMoreListener onLoadMoreListener;
private OnItemClickListener itemClickListener;
// private ImageLoader mImageLoader;
private final int VIEW_ITEM = 1;
private final int VIEW_PROG = 0;
private long mLastClickTimeListViewItem = 0;
public NewsFeedAdapter(Context context, ArrayList<NewsFeedParser.NewsFeed> itemList, RecyclerView recyclerView) {
this.context = context;
this.itemList = itemList;
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_default_news)
.showImageForEmptyUri(R.drawable.ic_default_news)
.showImageOnFail(R.drawable.ic_default_news)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
});
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh;
if (viewType == VIEW_ITEM) {
View itemView = LayoutInflater.from(context).inflate(R.layout.fragment_news_feed_trending_list_item, parent, false);
vh = new NewsFeedViewHolder(itemView);
} else {
View progView = LayoutInflater.from(context).inflate(R.layout.view_refresh_footer, parent, false);
vh = new ProgressViewHolder(progView);
}
return vh;
}
#Override
public int getItemViewType(int position) {
return itemList.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}
#Override
public int getItemCount() {
return itemList.size();
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof NewsFeedViewHolder) {
final NewsFeedParser.NewsFeed singleItem = itemList.get(position);
((NewsFeedViewHolder) holder).txtNews.setText(Html.fromHtml(singleItem.title));
((NewsFeedViewHolder) holder).txtDays.setText(DateConversion.getStatusTiming(context, singleItem.modified));
((NewsFeedViewHolder) holder).imgNewsPhoto.setImageResource(R.drawable.ic_default_news);
if (singleItem.featured_image != null) {
if (singleItem.featured_image.attachment_meta != null) {
if (singleItem.featured_image.attachment_meta.sizes != null) {
if (singleItem.featured_image.attachment_meta.sizes.thumbnail != null) {
if (!TextUtils.isNullOrEmpty(singleItem.featured_image.attachment_meta.sizes.thumbnail.url)) {
ImageLoader.getInstance().displayImage(singleItem.featured_image.attachment_meta.sizes.thumbnail.url, ((NewsFeedViewHolder) holder).imgNewsPhoto, options);
} else {
if (!TextUtils.isNullOrEmpty(singleItem.featured_image.source)) {
ImageLoader.getInstance().displayImage(singleItem.featured_image.source, ((NewsFeedViewHolder) holder).imgNewsPhoto, options);
}
}
}
}
}
}
if (singleItem.read_status == 0) {
((NewsFeedViewHolder) holder).rlFeedItem.setBackgroundColor(ContextCompat.getColor(context, R.color.clr_news_feed_item_bg));
} else {
((NewsFeedViewHolder) holder).rlFeedItem.setBackgroundColor(ContextCompat.getColor(context, R.color.transparent));
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTimeListViewItem < 1000) {
return;
}
mLastClickTimeListViewItem = SystemClock.elapsedRealtime();
if (itemClickListener != null) {
itemClickListener.onItemClick(singleItem);
singleItem.read_status = 1;
notifyItemChanged(position);
}
}
});
} else {
((ProgressViewHolder) holder).progressBar.setLinearProgress(true);
}
}
public void addList(ArrayList<NewsFeedParser.NewsFeed> items) {
if (items == null) {
this.itemList.add(null);
} else {
for (NewsFeedParser.NewsFeed item : items) {
this.itemList.add(item);
}
}
notifyDataSetChanged();
}
public void updateList(ArrayList<NewsFeedParser.NewsFeed> items) {
if (items != null) {
this.itemList = items;
}
notifyDataSetChanged();
}
public void removeProgress(int itemCount) {
this.itemList.remove(itemCount - 1);
notifyItemRemoved(itemCount);
}
public static class NewsFeedViewHolder extends RecyclerView.ViewHolder {
USUTextView txtNews, txtDays;
ImageView imgNewsPhoto;
RelativeLayout rlFeedItem;
public NewsFeedViewHolder(View itemView) {
super(itemView);
txtNews = (USUTextView) itemView.findViewById(R.id.txt_news);
txtDays = (USUTextView) itemView.findViewById(R.id.txt_days);
imgNewsPhoto = (ImageView) itemView.findViewById(R.id.img_news_photo);
rlFeedItem = (RelativeLayout) itemView.findViewById(R.id.rl_feed_list_item);
}
}
public static class ProgressViewHolder extends RecyclerView.ViewHolder {
public ProgressWheel progressBar;
public ProgressViewHolder(View progView) {
super(progView);
progressBar = (ProgressWheel) progView.findViewById(R.id.progress_bar);
}
}
public void setLoaded() {
loading = false;
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setOnItemClickListener(OnItemClickListener recyclerClickListener) {
this.itemClickListener = recyclerClickListener;
}
public interface OnItemClickListener {
void onItemClick(NewsFeedParser.NewsFeed item);
}
}
Please suggest me any idea.....