Cant realtime update recycleView whith realm - android

Sorry for my english. I have list objects, it list contains switch btn. When user change some switch i neeed it update in db. I
But when i try change swith, i have error:
java.lang.IllegalStateException: Cannot modify managed objects outside of a write transaction.
I can not understand how create adapter, who can update realtime data
My adapter:
public class DocumentTypeAdapterDB extends RealmRecyclerViewAdapter<DocType, DocumentTypeAdapterDB.ViewHolder> {
RealmList<DocType> docTypes;
public DocumentTypeAdapterDB(#Nullable RealmList<DocType> docTypes, Context context) {
super(docTypes, true);
this.docTypes = docTypes;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_doc_type, null);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutView.setLayoutParams(lp);
ViewHolder rcv = new ViewHolder(layoutView);
return rcv;
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final DocType docType = docTypes.get(position);
holder.switch_item.setText(docType.name);
//check box
holder.switch_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!holder.switch_item.isChecked()) {
docType.is_check = false;
} else {
docType.is_check = true;
}
}
});
}
#Override
public int getItemCount() {
return docTypes.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
SwitchCompat switch_item;
public ViewHolder(View itemView) {
super(itemView);
switch_item = (SwitchCompat) itemView.findViewById(R.id.switch_item);
}
public void clearAnimation()
{ itemView.clearAnimation(); }
}
}
DocType
public class DocType extends RealmObject{
public boolean is_check;
public String name;
//getter and setter
}

You need transaction to modify RealmObjects.
So, you should get Realm instance that docTypes belongs to and then:
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
docType.is_check = holder.switch_item.isChecked();
}
});

Related

Inflate multiple layout in FirestoreRecyclerAdapter [duplicate]

My Title is kind of hard to understand but basically when I add items into my database is should display it in a RecyclerView. Now in my RecyclerView I have two layouts but the problem is the first item of my database goes behind my first item in my other layout. So if I have 3 items in my database, it shows only 2 items from the database and the first item hides behind my first item in the RecyclerView which is a different layout that does not use the database at all.
This is my code:
FirebaseRecyclerOptions<Event> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Event>()
.setQuery(query1, Event.class).build();
AccAdapter = new FirebaseRecyclerAdapter<Event, RecyclerView.ViewHolder>(firebaseRecyclerOptions){
final static int TYPE_HEADER = 0;
final static int TYPE_ITEM = 1;
#Override
public int getItemViewType(int position) {
if (position == 0) return TYPE_HEADER;
return TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER){
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_add_items,
parent, false);
return new ProdudctHolder3(view);
} else {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_acc,
parent, false);
return new ProductHolder2(view);
}
}
#Override
protected void onBindViewHolder(final RecyclerView.ViewHolder holder, int position, final Event model) {
if (holder instanceof ProdudctHolder3){
((ProdudctHolder3) holder).addBackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(), AccAddItems.class ));
}
});
} else{
final ProductHolder2 productHolder2 = (ProductHolder2) holder;
productHolder2.mName.setText(model.getName());
productHolder2.view.setBackgroundResource(getBackgroundDrawable(Integer.valueOf(model.getProductAmount())));
productHolder2.mbackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.popup_edit_product);
SeekBar amountSeekBar = dialog.findViewById(R.id.amountSeekBar);
amountSeekBar.setMax(100);
amountSeekBar.setProgress(Integer.valueOf(model.getProductAmount()));
amountSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
progress = i;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
getRef(holder.getAdapterPosition()).child("productAmount").setValue(String.valueOf(progress));
dialog.dismiss();
}
});
dialog.show();
}
});
productHolder2.mbackground.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
final PopupMenu popupMenu = new PopupMenu(getActivity(), productHolder2.mbackground);
popupMenu.inflate(R.menu.menu_acc);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.deleteProduct:
getRef(productHolder2.getAdapterPosition()).removeValue();
popupMenu.dismiss();
return true;
default:
return false;
}
}
});
popupMenu.show();
return true;
}
});
}
}
};
mAccRecyclerViewRef.setAdapter(AccAdapter);
My two Product Holders
private class ProdudctHolder3 extends RecyclerView.ViewHolder{
private RelativeLayout addBackground;
public ProdudctHolder3(View itemView) {
super(itemView);
addBackground = itemView.findViewById(R.id.mBackground2);
}
}
private class ProductHolder2 extends RecyclerView.ViewHolder{
private TextView mName;
private RelativeLayout mbackground;
private View view;
public ProductHolder2(View itemView) {
super(itemView);
mName = itemView.findViewById(R.id.ItemName);
mbackground = itemView.findViewById(R.id.mBackground1);
view = itemView.findViewById(R.id.amountIndicator);
}
}
The ideal solution would have been to set two adapters on a single RecyclerView but unfortunatelly this is not possible.
However, you can make a single custom Adapter that handles two types of items. I will explain this by getting an example.
Let's assume you need to display objects of two types, humans and aliens. Your objects require completely different layouts and completely different ViewHolders. Please see the below code for the ViewHolders:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static class HumanViewHolder extends RecyclerView.ViewHolder {
public HumanViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Human human) {
//Display your human object
}
}
private static class AlienViewHolder extends RecyclerView.ViewHolder {
public AlienViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Alien alien) {
//Display your alien object
}
}
}
First you need to add two different constants to your adapter representing both type of views:
private static final int ITEM_TYPE_HUMAN;
private static final int ITEM_TYPE_ALIEN;
To keep things simple, let's also assume you store your objects in a list:
private List<Object> items = new ArrayList<>();
public MyAdapter(List<Object> items) {
this.items.addAll(items);
//Other stuff if needed
}
Now, the first you need to do, is to implement getItemViewType() method:
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof Human) {
return ITEM_TYPE_HUMAN;
} else {
return ITEM_TYPE_ALIEN;
}
}
Second, you need to use the item type inside the onCreateViewHolder() method like this:
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if (viewType == ITEM_TYPE_HUMAN) {
View view = layoutInflater.inflate(R.layout.item_human, parent, false);
return new HumanViewHolder(view);
} else {
View view = layoutInflater.inflate(R.layout.item_alien, parent, false);
return new AlienViewHolder(view);
}
}
In the end, you just need to bind the proper view holder like this:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
Object item = items.get(position);
if (viewHolder instanceof HumanViewHolder) {
((HumanViewHolder) viewHolder).bind((Human) item);
} else {
((AlienViewHolder) viewHolder).bind((Alien) item);
}
}
Why use the Firebase Recycler Adapter when you could easily make a custom one? If I understood well you want an item to be fixed at position 0 (header) while others will be added below the first one, right? If so, here is a solution I like to use:
public interface ViewType {
public int getViewType();
}
public interface ViewTypeDelegateAdapter {
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent);
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item);
}
public class ViewTypes {
public static int HEADER = 0
public static int ITEM = 1
}
public class ProductDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new ProductHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as ProductHolder).bind("test");
}
class ProductHolder extends RecyclerView.ViewHolder {
public ProductHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class HeaderDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new HeaderHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as HeaderHolder).bind("test");
}
class HeaderHolder extends RecyclerView.ViewHolder {
public HeaderHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class AccAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private Context context;
private List<ViewType> items;
private SparseArrayCompat<ViewTypeDelegateAdapter> delegateAdapters;
private ViewType headerItem;
public AccAdapter(Context context) {
this.context = context;
this.items = new ArrayList();
this.delegateAdapters = new SparseArrayCompat();
this.headerItem = new ViewType() {
#Override
public int getViewType() {
return ViewTypes.HEADER;
}
};
this.items.add(this.headerItem);
this.delegateAdapters.put(ViewTypes.HEADER, HeaderDelegateAdapter(R.id.test, this.context));
this.delegateAdapters.put(ViewTypes.ITEM, ProductDelegateAdapter(R.id.test, this.context));
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, Int viewType) {
return delegateAdapters.get(viewType).onCreateViewHolder(parent);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, Int position) {
delegateAdapters.get(getItemViewType(position)).onBindViewHolder(holder, items[position])
}
#Override
public Int getItemViewType(Int position) {
return items.get(position).getViewType();
}
#Override
public Int getItemCount() {
return items.getSize();
}
public void add(ViewType viewType) {
val initPosition = this.items.size - 1
this.items.add(item)
notifyItemRangeChanged(initPosition, this.items.size + 1)
}
}
public class Event implements ViewType {
private String id;
#Override
public int getViewType() {
return ViewTypes.ITEM;
}
}
Excuse me for some syntax errors, I've translated to Java from Kotlin to help you. Hope it helps!

FirebaseRecyclerAdapter doesn't recognize first layout as a position

My Title is kind of hard to understand but basically when I add items into my database is should display it in a RecyclerView. Now in my RecyclerView I have two layouts but the problem is the first item of my database goes behind my first item in my other layout. So if I have 3 items in my database, it shows only 2 items from the database and the first item hides behind my first item in the RecyclerView which is a different layout that does not use the database at all.
This is my code:
FirebaseRecyclerOptions<Event> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Event>()
.setQuery(query1, Event.class).build();
AccAdapter = new FirebaseRecyclerAdapter<Event, RecyclerView.ViewHolder>(firebaseRecyclerOptions){
final static int TYPE_HEADER = 0;
final static int TYPE_ITEM = 1;
#Override
public int getItemViewType(int position) {
if (position == 0) return TYPE_HEADER;
return TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER){
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_add_items,
parent, false);
return new ProdudctHolder3(view);
} else {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_acc,
parent, false);
return new ProductHolder2(view);
}
}
#Override
protected void onBindViewHolder(final RecyclerView.ViewHolder holder, int position, final Event model) {
if (holder instanceof ProdudctHolder3){
((ProdudctHolder3) holder).addBackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(), AccAddItems.class ));
}
});
} else{
final ProductHolder2 productHolder2 = (ProductHolder2) holder;
productHolder2.mName.setText(model.getName());
productHolder2.view.setBackgroundResource(getBackgroundDrawable(Integer.valueOf(model.getProductAmount())));
productHolder2.mbackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.popup_edit_product);
SeekBar amountSeekBar = dialog.findViewById(R.id.amountSeekBar);
amountSeekBar.setMax(100);
amountSeekBar.setProgress(Integer.valueOf(model.getProductAmount()));
amountSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
progress = i;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
getRef(holder.getAdapterPosition()).child("productAmount").setValue(String.valueOf(progress));
dialog.dismiss();
}
});
dialog.show();
}
});
productHolder2.mbackground.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
final PopupMenu popupMenu = new PopupMenu(getActivity(), productHolder2.mbackground);
popupMenu.inflate(R.menu.menu_acc);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.deleteProduct:
getRef(productHolder2.getAdapterPosition()).removeValue();
popupMenu.dismiss();
return true;
default:
return false;
}
}
});
popupMenu.show();
return true;
}
});
}
}
};
mAccRecyclerViewRef.setAdapter(AccAdapter);
My two Product Holders
private class ProdudctHolder3 extends RecyclerView.ViewHolder{
private RelativeLayout addBackground;
public ProdudctHolder3(View itemView) {
super(itemView);
addBackground = itemView.findViewById(R.id.mBackground2);
}
}
private class ProductHolder2 extends RecyclerView.ViewHolder{
private TextView mName;
private RelativeLayout mbackground;
private View view;
public ProductHolder2(View itemView) {
super(itemView);
mName = itemView.findViewById(R.id.ItemName);
mbackground = itemView.findViewById(R.id.mBackground1);
view = itemView.findViewById(R.id.amountIndicator);
}
}
The ideal solution would have been to set two adapters on a single RecyclerView but unfortunatelly this is not possible.
However, you can make a single custom Adapter that handles two types of items. I will explain this by getting an example.
Let's assume you need to display objects of two types, humans and aliens. Your objects require completely different layouts and completely different ViewHolders. Please see the below code for the ViewHolders:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static class HumanViewHolder extends RecyclerView.ViewHolder {
public HumanViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Human human) {
//Display your human object
}
}
private static class AlienViewHolder extends RecyclerView.ViewHolder {
public AlienViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Alien alien) {
//Display your alien object
}
}
}
First you need to add two different constants to your adapter representing both type of views:
private static final int ITEM_TYPE_HUMAN;
private static final int ITEM_TYPE_ALIEN;
To keep things simple, let's also assume you store your objects in a list:
private List<Object> items = new ArrayList<>();
public MyAdapter(List<Object> items) {
this.items.addAll(items);
//Other stuff if needed
}
Now, the first you need to do, is to implement getItemViewType() method:
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof Human) {
return ITEM_TYPE_HUMAN;
} else {
return ITEM_TYPE_ALIEN;
}
}
Second, you need to use the item type inside the onCreateViewHolder() method like this:
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if (viewType == ITEM_TYPE_HUMAN) {
View view = layoutInflater.inflate(R.layout.item_human, parent, false);
return new HumanViewHolder(view);
} else {
View view = layoutInflater.inflate(R.layout.item_alien, parent, false);
return new AlienViewHolder(view);
}
}
In the end, you just need to bind the proper view holder like this:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
Object item = items.get(position);
if (viewHolder instanceof HumanViewHolder) {
((HumanViewHolder) viewHolder).bind((Human) item);
} else {
((AlienViewHolder) viewHolder).bind((Alien) item);
}
}
Why use the Firebase Recycler Adapter when you could easily make a custom one? If I understood well you want an item to be fixed at position 0 (header) while others will be added below the first one, right? If so, here is a solution I like to use:
public interface ViewType {
public int getViewType();
}
public interface ViewTypeDelegateAdapter {
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent);
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item);
}
public class ViewTypes {
public static int HEADER = 0
public static int ITEM = 1
}
public class ProductDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new ProductHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as ProductHolder).bind("test");
}
class ProductHolder extends RecyclerView.ViewHolder {
public ProductHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class HeaderDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new HeaderHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as HeaderHolder).bind("test");
}
class HeaderHolder extends RecyclerView.ViewHolder {
public HeaderHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class AccAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private Context context;
private List<ViewType> items;
private SparseArrayCompat<ViewTypeDelegateAdapter> delegateAdapters;
private ViewType headerItem;
public AccAdapter(Context context) {
this.context = context;
this.items = new ArrayList();
this.delegateAdapters = new SparseArrayCompat();
this.headerItem = new ViewType() {
#Override
public int getViewType() {
return ViewTypes.HEADER;
}
};
this.items.add(this.headerItem);
this.delegateAdapters.put(ViewTypes.HEADER, HeaderDelegateAdapter(R.id.test, this.context));
this.delegateAdapters.put(ViewTypes.ITEM, ProductDelegateAdapter(R.id.test, this.context));
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, Int viewType) {
return delegateAdapters.get(viewType).onCreateViewHolder(parent);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, Int position) {
delegateAdapters.get(getItemViewType(position)).onBindViewHolder(holder, items[position])
}
#Override
public Int getItemViewType(Int position) {
return items.get(position).getViewType();
}
#Override
public Int getItemCount() {
return items.getSize();
}
public void add(ViewType viewType) {
val initPosition = this.items.size - 1
this.items.add(item)
notifyItemRangeChanged(initPosition, this.items.size + 1)
}
}
public class Event implements ViewType {
private String id;
#Override
public int getViewType() {
return ViewTypes.ITEM;
}
}
Excuse me for some syntax errors, I've translated to Java from Kotlin to help you. Hope it helps!

remove database item and update view on click

I am trying to remove item from database onClick of a button(defined as delbutton) here.
My Adapter looks like(I have included definitions and removed onBindViewHolder for brevity), and the onclick method is inside ViewHolder.
public class PlacesAdapter extends RecyclerView.Adapter<PlacesAdapter.ViewHolder> {
private static final String TAG = "PlaceAdapter";
List<PlaceSaved> items;
PlaceDatabase db;
public PlacesAdapter(List<PlaceSaved> items, PlaceDatabase db) {
this.items = items;
this.db = db;
}
#Override
public PlacesAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.places_list_item, parent, false);
return new ViewHolder(view);
}
#Override
public int getItemCount() {
return items.size();
}
public class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
public TextView name;
public TextView time;
public TextView longi;
public ImageButton delbutton;
public CardView cview;
public ViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.secondLine);
time = itemView.findViewById(R.id.firstLine);
longi = itemView.findViewById(R.id.longitude);
delbutton = itemView.findViewById(R.id.delicon);
cview = itemView.findViewById(R.id.place_view);
itemView.setOnClickListener(this);
delbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Log.e("What", "Get"+getAdapterPosition());
removeItem(getAdapterPosition());
}
});
}
#Override
public void onClick(View view) {
// Clicked postion
int position = getAdapterPosition();
PlaceSaved place = items.get(position);
// Here is the data Do your stuff
Log.e("Will WORK", place.getLongi());
}
}
private void removeItem(int position){
db.databaseInterface().delete(items.get(position));
items.remove(position);
notifyItemRemoved(position);
}
}
Now on clicking delbutton, I am getting the error:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
I know, I need to invoke runOnUIThread somehow, but inside ViewHolder, I cant define it. How can I solve this problem?
create new Thread Executors class like below
public class AppExecutors {
private final Executor mDiskIO;
private AppExecutors(Executor diskIO) {
this.mDiskIO = diskIO;
}
public AppExecutors() {
this(Executors.newSingleThreadExecutor());
}
public Executor diskIO() {
return mDiskIO;
}
}
use that class like this way..make return type of delete interface int type , to check successfully delete item.
private void removeItem(int position) {
new AppExecutors().diskIO().execute(new Runnable() {
#Override
public void run() {
if(db.databaseInterface().delete(items.get(position)) > 0 ){
runOnUiThread(new Runnable() {
#Override
public void run() {
items.remove(position);
notifyItemRemoved(position);
}
});
}
}
});
}

Perform click event on RecyclerView's item by "Position" [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am in RecyclerView's Adapter.
From onBindViewHolder() I am able to perform onClick event for RecyclerView's row (ViewHolder's Item).
Is it possible to call onClick() by using Position ?
You can do something like this
Adapter:
public class OffersAdapter extends RecyclerView.Adapter<OffersAdapter.ViewHolder> {
private List<Offer> mDataset;
private OffersListner mListener;
public OffersAdapter(List<Offer> response) {
mDataset = response;
}
public void setListener(OffersListner listener) {
mListener = listener;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row_offers, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final int pos = getItemViewType(position);
holder.mLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.onOfferChoice(mDataset.get(pos));
}
});
}
#Override
public int getItemCount() {
return mDataset.size();
}
public interface OffersListner {
void onOfferChoice(Offer offer);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.item_offers_layout)
LinearLayout mLayout;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
Activity:
public class OffersSelectActivity extends BaseEventActivity implements OffersAdapter.OffersListner {
.
.
.
private void setOffers(List<Offer> offers) {
OffersAdapter mAdapter = new OffersAdapter(offers);
mAdapter.setListener(this);
mOffers.setHasFixedSize(true);
mOffers.setLayoutManager(new LinearLayoutManager(this));
mOffers.setAdapter(mAdapter);
}
#Override
public void onOfferChoice(Offer offer) {
Intent intent = new Intent(this, OfferActivity.class);
intent.putExtra(Constants.EXTRA_OFFER_ID, offer.id);
intent.putExtra(Constants.EXTRA_OFFER_NAME, offer.name);
startActivity(intent);
}
}
Here is example :
public class NavigationDrawerAdapter extends RecyclerView.Adapter<NavigationDrawerAdapter.MyViewHolder> {
List<Pojo_menu> data;
public NavigationDrawerAdapter(Context mContext, List<Pojo_menu> data) {
this.data = data;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView title, tv_count;
RelativeLayout mRelativeLayout;
private SparseBooleanArray selectedItems = new SparseBooleanArray();
public MyViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.item_name);
tv_count = (TextView) itemView.findViewById(R.id.tv_count);
mRelativeLayout = (RelativeLayout) itemView.findViewById(R.id.my_nav_menu);
}
}
public NavigationDrawerAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.nav_drawer_row, parent, false);
return new NavigationDrawerAdapter.MyViewHolder(itemView);
}
public void onBindViewHolder(NavigationDrawerAdapter.MyViewHolder holder, int position) {
Pojo_menu current = data.get(position);
String count = current.getCount();
holder.tv_count.setText(count);
holder.title.setText(current.getName());
holder.title.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
#Override
public int getItemCount() {
return data.size();
}
}
Just set onClickListener to the holder
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setOnClickListner(new View.OnClickListener() {
#Override
public void onClick(View view) {
// to the thing you want refer to the position by holder.getAdapterPosition()
}
};)
}
It not recommended to use position directly since you have to declare it final. Therefore, when referring to the position inside onClick please use holder.getAdapterPosition() instead.

Removing item from RecyclerView

I am having trouble removing items from RecyclerView. When I click on delete, the item is removed from RecyclerView, but comes back when I open the app again. I'm hoping it is just a minor issue that someone here can point out or direct me to what area to troubleshoot. The removeItem(String item) in bold is what I think is the issue. You can't see it in this post, but it is "not used".
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
private List<Grocery> mListData;
private SQLGroceryHelper helper;
RecyclerViewAdapter adapter;
//Adapter's Constructor//
public RecyclerViewAdapter(List<Grocery> mDataList) {
this.mListData = mDataList;
}
//Provide a reference to the views for each contact item//
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView rowItem;
ImageButton purchasedButton;
ImageButton deleteButton;
LinearLayout linearLayout;
public MyViewHolder(View itemView) {
super(itemView);
linearLayout = (LinearLayout) itemView.findViewById(R.id.recycler_row);
rowItem = (TextView) itemView.findViewById(R.id.item_field1);
purchasedButton = (ImageButton) itemView.findViewById(R.id.item_purchased);
deleteButton = (ImageButton) itemView.findViewById(R.id.delete_item);
}
}
//Inflate the view based on the viewtype provided//
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//Create a new view by inflating the row item xml//
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false);
//Set the view to the ViewHolder//
MyViewHolder holder = new MyViewHolder(row);
return holder;
}
//Display data at the specified position//
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.rowItem.setText(mListData.get(position).getTextItem());
holder.purchasedButton.setOnClickListener(new View.OnClickListener() {
//Ignore this click for now//
#Override
public void onClick(View v) {
removeItem(position);
}
});
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
removeItem(position);
}
});
}
public void **removeItem**(String item) {
int position = mListData.indexOf(item);
if (position != -1) {
mListData.remove(item);
notifyItemRemoved(position);
}
}
public void removeItem(int position) {
mListData.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
if (mListData == null) {
return 0;
}
return mListData.size();
}
}
You are removing the data from local object, mListData I guess the original data object remains intact. Remove the data item from the original data object as well
Declare a interface
public interface AdapterCommunication{
void removeStringItem(int position);
}
then in your adapter
private AdapterCommunication mListener;
public void setOnClickListener(AdapterCommunication listener){
mListener = listener;
}
Then from your activity where you initialize the adapter
RecyclerViewAdapter adapter = new RecyclerViewAdapter(list);
adapter.setOnClickListener(new AdapterCommunication{
public void removeStringItem(int position){
list.remove(position);
adapter.notifyDataSetChanged();
}
});
In your adaper,
holder.deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListener.remove(position);
}
});

Categories

Resources