please read before marking it as a duplicate! :)
I converted a listview to recyclerview in my app. But the problem is that it just doesnt update when I call any notify methods. I read that i should call these methods on the Ui Thread. but even that isn't working. The data list has the item added to it but it doesnt get shown on UI.
Here's the code.
Adapter:
public class CustomViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Activity activity;
ArrayList<Leg> data;
public CustomViewAdapter(Activity a, ArrayList<Leg> d) {
super();
activity = a;
data = d;
}
#Override
public int getItemCount() {
return data.size();
}
#Override
public int getItemViewType(int position) {
Leg tempValues = data.get(position);
return tempValues.getLegType();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 1:
//...type 1
case 2:
//...type 2
default:
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_leg, parent, false);
return new LegViewHolder1(v);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Leg tempValues = data.get(position);
//.... Simple view logic that correctly displays
}
class LegViewHolder2 extends RecyclerView.ViewHolder {
//... Holder of another type
}
class LegViewHolder1 extends RecyclerView.ViewHolder {
#InjectView(R.id.leg_add_button)
RelativeLayout legAddIcon;
public AddLegViewHolder(View v) {
super(v);
ButterKnife.inject(this, v);
legAddIcon.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Add Debug", "AddIcon clicked");
Leg leg = new Leg();
leg.setLegType(Constants.LEG);
data.add((data.size() - 1), leg);
refreshList("add", (data.size() - 1)); /// was using notify previously here
}
});
}
}
public void refreshList(final String type, final int position) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (type.equals("update")) {
notifyItemChanged(position);
} else if (type.equals("remove")) {
notifyItemRemoved(position);
} else if (type.equals("add")) {
notifyItemInserted(position);
}
}
});
}
}
Here's the Activity:
public class LegActivity extends BaseActivity {
CustomViewAdapter adapter;
LoadTask loadTask = null;
ArrayList<Leg> legsList;
#InjectView(R.id.leg_list)
RecyclerView legList;
#Override
public void onCreate(Bundle savedInstanceState) {
//...boiler plate code
legList.setHasFixedSize(true);
legList.setLayoutManager(new LinearLayoutManager(this));
loadTask = new LoadTask(this);
loadTask.execute();
}
class LoadTask extends RoboAsyncTask<Boolean> {
protected LoadTask(Context context) {
super(context);
}
#Override
protected void onPreExecute() {
// show loader
}
#Override
public Boolean call() throws Exception {
//load some data the send boolean for success
}
#Override
protected void onSuccess(Boolean success) {
//checking for success and loading data to legslist.
adapter = new CustomViewAdapter(LegActivity.this, legsList);
legList.setAdapter(new AlphaInAnimationAdapter(adapter));
legList.setItemAnimator(new SlideInLeftAnimator());
}
#Override
protected void onException(Exception e) {
// other code....
}
}
}
The problem is that the object is added to the actual legList when i click on the add button. I verified that but the notify notifyItemInserted doesnt seem to work. I tried running that on the UI thread but even that didnt seem to work.
Any suggestions? I followed the android recyclerview sample. Maybe i have used the RunOnUiThread incorrectly?
Also if you spot any syntax errors due to name changes, that isnt the problem, on Android Studio the code is error free.
I will take a shot and say it's because of this custom animating adapter:
legList.setAdapter(new AlphaInAnimationAdapter(adapter));
Try it this way:
adapter = new AlphaInAnimationAdapter(new CustomViewAdapter(LegActivity.this, legsList));
legList.setAdapter(adapter);
Related
I want to set an on-click event for a particular item in a row of endless recyclerview. I wrote on-click inside the adapter and implemented to the activity by using the interface.But my issue is that the on-click function is not working.
I have tried with the row position but it is not working.
public interface ViewOnMapAdapterListener {
void viewOnMapOnClick(ModelTripHistoryDetails data);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
try {
if (position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
if (getItemViewType(position) == TYPE_LIST) {
((TripHolder) holder).bindData(tripDetailsList.get(position), position, viewOnMapAdapterListener);
}
} catch (ArrayIndexOutOfBoundsException ex) {
} catch (ParseException e) {
e.printStackTrace();
}
//No else part needed as load holder doesn't bind any data
}
void bindData(final ModelTripHistoryDetails tripDetais, final int position, final AdapterTripHistory.ViewOnMapAdapterListener viewOnMapAdapterListener) throws ParseException {
try {
setDatas(tripDetais);
tvViewOnMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewOnMapAdapterListener.viewOnMapOnClick(tripDetais);
}
});
} catch (Exception e) {
}
}
Activity
private void initView() {
tripDetailsList = new ArrayList<>();
rvTripHistory = (RecyclerView) findViewById(R.id.rvTripHistory);
context = this;
adapterTripHistory = new AdapterTripHistory(this, tripDetailsList, new AdapterTripHistory.ViewOnMapAdapterListener() {
#Override
public void viewOnMapOnClick(ModelTripHistoryDetails data) {
Toast.makeText(TripHistoryActivity.this,"clicked",Toast.LENGTH_SHORT).show();
}
});
adapterTripHistory.setLoadMoreListener(new AdapterTripHistory.OnLoadMoreListener() {
#Override
public void onLoadMore() {
rvTripHistory.post(new Runnable() {
#Override
public void run() {
index++;
loadMore(index);
}
});
//Calling loadMore function in Runnable to fix the
// java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling error
}
});
I will recommend you, to add logs inside every try-catch block. You are probably getting some exception inside setDatas(tripDetais) method and you never set listener to the view because of that exception.
As far as I know, you need to implement a Holder class that extends ViewHolder and implement View.OnClickListener(), something like this:
public static class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView someView;
OnYourListener onYourListener;
public Holder(#NonNull View itemView,OnYourListener onYourListener) {
super(itemView);
this.onYourListener = onYourListener;
someView = itemView.findViewById(R.id.some_view);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
onYourListener.onYourClicked(getAdapterPosition());
}
}
and pass the activity that implement the interface to the adapter as the listener.
your adapter constructor should look something like this:
public Adapter(Context context, ArrayList<somthing> arrayList, OnYourListener onYourListener) {
this.context = context;
this.ArrayList = ArrayList;
this.mOnYourListener = onYourListener;
}
and on createViewHolder you should pass the listener like so:
#Override
public Holder onCreateViewHolder(#ViewGroup viewGroup, int i) {
View layout = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.your_layout,null);
Holder holder =new Holder(layout,mOnYourListener);
return holder;
}
This way you can create a holder the way you want to and the onclick should work
My Recycler view is not updating after an item is removed.
This recyclerView is inside a fragment.
I have tried every method and nothing works.
Adapter declaration in fragment class
notificationsTabAdapter = new NotificationsTabAdapter(getContext(), R.id.notificationsRecyclerView,
notificationItemsList, cListner);
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(notificationsTabAdapter);
RecyclerViewAdapter:
public class NotificationsTabAdapter extends RecyclerView.Adapter<NotificationsTabAdapter.NotificationItemHolder> {
Boolean debug = false;
public static final String NOTIFICATION_ADAPTER = "NotificationAdapter";
private ArrayList<NotificationItemm> notificationItems;
private int layoutResID;
private int notificationposition;
private Context myContext;
public onNotificationItemClickListner mListner;
public interface onNotificationItemClickListner {
void onNotificationItemDelete(int position);
}
public NotificationsTabAdapter(Context context, int resource, ArrayList<NotificationItemm> notificationList,
onNotificationItemClickListner listner) {
myContext = context;
layoutResID = resource;
notificationItems = notificationList;
notificationposition = 0;
this.mListner = listner;
}
#NonNull
#Override
public NotificationItemHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.notifications_tab_item, viewGroup, false);
NotificationsTabAdapter.NotificationItemHolder evh = new NotificationsTabAdapter.NotificationItemHolder(view, mListner);
return evh;
}
#Override
public void onBindViewHolder(#NonNull final NotificationItemHolder notificationItemHolder, final int position) {
final NotificationItemm currentItem = notificationItems.get(position);
notificationItemHolder.mNotificationTextView.setText(currentItem.getNotification_name());
notificationItemHolder.mNotificationURL = currentItem.getNotification_link();
notificationItemHolder.mNotificationDate = currentItem.getNotification_date();
notificationItemHolder.mNotificationRT = currentItem.getNotification_rT();
notificationItemHolder.mNotificaionHolderLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
//to delete the notification
notificationItemHolder.imageDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteNotification(currentItem);
mListner.onNotificationItemDelete(position);
}
});
}
#Override
public int getItemCount() {
return notificationItems.size();
}
//Delete from View
public void deleteNotification(NotificationItemm todelete) {
int notificationPosition = notificationItems.indexOf(todelete);
notificationItems.remove(notificationPosition);
notifyItemRemoved(notificationPosition);
notifyItemChanged(notificationPosition);
notifyDataSetChanged();
notifyItemRemoved(notificationPosition);
notifyItemChanged(notificationPosition);
if (notificationItems.isEmpty()) {
}
}
/**
* VIEW HOLDER =================================================================================
**/
public class NotificationItemHolder extends RecyclerView.ViewHolder {
RelativeLayout mNotificaionHolderLayout;
RelativeLayout notificationParentRelative;
ImageView imageDelete;
TextView mNotificationTextView;
String mNotificationURL;
String mNotificationDate;
String mNotificationRT;
public NotificationItemHolder(#NonNull View itemView, onNotificationItemClickListner listner) {
super(itemView);
mNotificationTextView = itemView.findViewById(R.id.NotificationTextView);
mNotificaionHolderLayout = itemView.findViewById(R.id.notification__item_container);
imageDelete = itemView.findViewById(R.id.notification_delete_image);
notificationParentRelative = itemView.findViewById(R.id.rlNotificLayout);
mNotificationRT = null;
mNotificationURL = null;
mNotificationDate = null;
}
}
}
When I debug the project, I can see that the item is actually removing from the ArrayList.But not updating in recycled view.
After deletion, if the recyclerview is scrolled, the deleted item is removed from the recyclerview.But not without scrolling.
Try this.Hope will work for you.
notificationItemHolder.imageDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
notificationItems.remove(position);
notifyDataSetChanged();
}
In your NotificationsTabAdapter make the following changes
NotificationsTabAdapterListener notificationsTabAdapterListener;
public interface NotificationsTabAdapterListener { // create an interface
void onItemsDeleted(int position); // create callback function
}
public NotificationsTabAdapter(Context context, int resource, ArrayList<NotificationItemm> notificationList,
NotificationsTabAdapterListener notificationsTabAdapterListener) {
myContext = context;
layoutResID = resource;
notificationItems = notificationList;
notificationposition = 0;
this.notificationsTabAdapterListener = notificationsTabAdapterListener;
}
notificationItemHolder.imageDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//perform normal remove operation here
notificationItems.remove(position);
notificationsTabAdapterListener.onItemsDeleted(position);
}
});
And Implement NotificationsTabAdapterListener in you fragment and in override method use the following code
#Override
public void onItemsDeleted(final int position) {
notificationsTabAdapter.notifyDataSetChanged();
recyclerView.post(new Runnable() {
#Override
public void run() {
recyclerView.smoothScrollToPosition(position);
}
});
}
Try this to your delete functionality
public void deleteNotification(NotificationItemm todelete) {
notificationItems.remove(todelete);
notifyDataSetChanged();
}
As workaround you can call a method in the FragmentClass, which loads the new list (with item removed) in your adapter. Call this method from your Adapter
public void MethodInFragmentClass(NotificationItemm todelete)
{
/*
... delete item
*/
notificationsTabAdapter = new NotificationsTabAdapter(getContext(), R.id.notificationsRecyclerView,
notificationDeletedItemsList, cListner);
recyclerView.setAdapter(notificationsTabAdapter);
}
Use a callback like this in your adapter :
private ICallback mICallback;
public interface ICallback {
void deleteItem(int position);
}
public SettingRecyclerViewAdapter(SettingMediator settingMediator, ICallback ICallback) {
mICallback = ICallback;
mSettingMediator = settingMediator;
}
And in your faragment notifydatasetchange and update recyclerview like this :
public class YourFragment implements SettingContract.View, SettingRecyclerViewAdapter.ICallback {
.
.
.
#Override
public void deleteItem(int position) {
//delete item from your list here
mSettingRecyclerViewAdapter = new SettingRecyclerViewAdapter(yourList, this);
mRecyclerView.setAdapter(mSettingRecyclerViewAdapter);
mSettingRecyclerViewAdapter.notifyDataSetChanged();
}
}
Try this:
notificationItemHolder.imageDelete.setTag(holder);
notificationItemHolder.imageDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NotificationItemHolder viewholder = (NotificationItemHolder) v.getTag();
notificationItems.remove(viewholder.getAdapterPosition());
notifyDataSetChanged();
}
});
You have to parse the position which is getting from onclick listener in Adapter class to Interface method(onitemClicked())
Then, Implement the interface class to Fragment class and will remove the position which we have on Interface method using [ listname.remove(position)) ]
Eventually, update recyclerview UI using adaptername.notifyDataSetChanged();
Step 1 :create interface class
public interface RecyclerviewItemClickListener {
void onitemClicked(View v, int position);
}
Step 2: pass position to the interface method in adapter class
notificationItemHolder.imageDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteNotification(currentItem);
//use interface method & pass the position of the list to fragment for update UI .
recyclerviewItemClickListener.onitemClicked(v,position);
}
});
step 3 : implement the interface class & method in fragment
#Override
public void onitemClicked(View v, int position) {
Listname.remove(Listname.get(position));
RecyclerviewAdaptername.notifyDataSetChanged();
}
I have the following Code:
public static FirestoreRecyclerAdapter adapter;
private void loadList() {
Query query = db.collection("x").document(firebase_user_uid).collection("x");
FirestoreRecyclerOptions<Note> response = new FirestoreRecyclerOptions.Builder<Note>()
.setQuery(query, Note.class)
.build();
adapter = new FirestoreRecyclerAdapter<Note, NoteViewHolder>(response) {
#Override
protected void onBindViewHolder(NoteViewHolder holder, int position, Note model) {
final Note note = notesList.get(position);
holder.title.setText(note.getTitle());
holder.content.setText(note.getContent());
if (note.getNote_image_url() != null) {
Glide.with(MainActivity.this).load(note.getNote_image_url()).into(holder.bg_note_image);
holder.bg_note_image.setVisibility(View.VISIBLE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateNote(note);
}
});
}
#Override
public NoteViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_note_view, parent, false);
return new NoteViewHolder(view);
}
#Override
public void onError(FirebaseFirestoreException e) {
Log.e("error", e.getMessage());
}
#Override
public int getItemCount() {
return notesList.size();
}
public void removeItem(int position) {
notesList.remove(position);
// notify the item removed by position
// to perform recycler view delete animations
// NOTE: don't call notifyDataSetChanged()
notifyItemRemoved(position);
}
public void restoreItem(Note item, int position) {
notesList.add(position, item);
// notify item added by position
notifyItemInserted(position);
}
};
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);
}
SO, a simple FirestoreRecyclerAdapter. But now I need to call the removeItemMethod inside the adapter. But how to do this?
I tried something like this, but all that didn't work.
public void deleteItem(int position) {
adapter.removeItem(position);
}
I am sitting so long on this Problem. I hope anywhere is a solution to my Problem.
Thanks in advance.
~mb
You get this message because the original FirestoreRecyclerAdapter does not have this method. You should create a separate class extending FirestoreRecyclerAdapter and use it when creating an adapter.
public class MyAdapter extends FirestoreRecyclerAdapter<Note, NoteViewHolder> {
public List<Notes> notesList;
public MyAdapter(List<Notes> notes, FirestoreRecyclerOptions<Note> response) {
super(response);
notesList = notes;
}
#Override
protected void onBindViewHolder(NoteViewHolder holder, int position,
Note model) {
final Note note = notesList.get(position);
holder.title.setText(note.getTitle());
holder.content.setText(note.getContent());
if (note.getNote_image_url() != null) {
Glide.with(MainActivity.this).load(note.getNote_image_url()).into(holder.bg_note_image);
holder.bg_note_image.setVisibility(View.VISIBLE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateNote(note);
}
});
}
#Override
public NoteViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_note_view, parent, false);
return new NoteViewHolder(view);
}
#Override
public void onError(FirebaseFirestoreException e) {
Log.e("error", e.getMessage());
}
#Override
public int getItemCount() {
return notesList.size();
}
public void removeItem(int position) {
notesList.remove(position);
// notify the item removed by position
// to perform recycler view delete animations
// NOTE: don't call notifyDataSetChanged()
notifyItemRemoved(position);
}
public void restoreItem(Note item, int position) {
notesList.add(position, item);
// notify item added by position
notifyItemInserted(position);
}
}
Something like this. And when you create an adapter :
public static MyAdapter adapter;
And initialising it:
adapter = new MyAdapter(response)
Also, it is not a good idea to keep an adapter static.
Edit: pass the items - notesList - in the constructor.
My RecyclerView(rvPredictionIndex) item includes ImageView, EditText and Button, when Button is clicked the Text inside EditText will be uploaded on server and when ImageView is clicked, the New Activity will be called and the position of that Item will be passed to new activity using Intent().
I am using DataBinding so View() is not used here (or any other way of using View() than i don't know).
Here is RecyclerView Adapter code....
public class PredictionItemAdapter extends RecyclerView.Adapter<PredictionItemAdapter.MyViewHolder> {
private List<PredictionItems> mPredictionItemsList;
private Context mContext;
private int predictionId;
private String etAnswer;
public class MyViewHolder extends RecyclerView.ViewHolder {
// ImageView ivPredictionImage;
// CustomTextView txtPredictionQuestion;
PredictionItemBinding predictionItemBinding;
public MyViewHolder(PredictionItemBinding predictionItemBinding) {
super(predictionItemBinding.getRoot());
this.predictionItemBinding = predictionItemBinding;
// ivPredictionImage = (ImageView) itemView.findViewById(R.id.ivPredictionImage);
// txtPredictionQuestion = (CustomTextView) itemView.findViewById(R.id.txtPredictionQuestion);
}
}
public PredictionItemAdapter(Context context, List<PredictionItems> mPredictionItemsList) {
this.mPredictionItemsList = mPredictionItemsList;
this.mContext = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.prediction_item, parent, false);
// return new MyViewHolder(view);
PredictionItemBinding predictionItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.prediction_item, parent, false);
return new MyViewHolder(predictionItemBinding);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
// PredictionItems predictionItems = mPredictionItemsList.get(position);
// Picasso.with(mContext).load(predictionItems.getImage()).into(holder.ivPredictionImage);
// holder.txtPredictionQuestion.setText(predictionItems.getQuestion());
final PredictionItems predictionItems = mPredictionItemsList.get(position);
PredictionViewModel predictionViewModel = new PredictionViewModel(predictionItems);
predictionViewModel.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
#Override
public void onPropertyChanged(Observable sender, int propertyId) {
if (propertyId == 1) {
etAnswer = holder.predictionItemBinding.editText.getText().toString();
predictionId = mPredictionItemsList.get(position).getId();
if (etAnswer.equals("")) {
Utility.showToastShort(mContext, "Please input answer");
} else {
callUpdatePredictionAnswerApi(predictionId, etAnswer);
// Toast.makeText(mContext, "submjit of " + holder.getAdapterPosition), Toast.LENGTH_SHORT).show();
}
}
else if (propertyId == 2){
//Here i want to start activity and pass data with intent
}
}
});
holder.predictionItemBinding.setPredictionVM(predictionViewModel);
}
#Override
public int getItemCount() {
return mPredictionItemsList.size();
}
}
I have already opened new activity on ItemClick of recyclerView but when i tried to click the EditText for input something, it will redirect me to the new activity, so that's why i want to start new activity on ImageView click..
here is my RecyclerViewItem Click...
private void rvPredictionIndexClick() {
rvPredictionIndex.addOnItemTouchListener(new RecyclerTouchListener(mContext, rvPredictionIndex, new RecyclerTouchListener.ClickListener() {
#Override
public void onClick(View view, int position) {
String preId = mPredictionItemsList.get(position).getId().toString();
Intent i = new Intent(mContext, PredictionInfoActivity.class);
String posi = ((String.valueOf(position)));
i.putExtra("predictionId", posi);
startActivity(i);
}
#Override
public void onLongClick(View view, int position) {
}
}));
}
Create Class DataBindingAdapter
and paste
#BindingAdapter("android:onClick")
public static void setOnClickListener(View view, final Runnable runnable) {
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runnable.run();
}
});
}
than go to your ViewModel class
and paste
public void onSubmitClicked() {
Log.e("onButtonSubmit", "onButtonSubmit");
notifyPropertyChanged(1);
}
public void onImageClicked() {
Log.e("onImageClicked", "onImageClicked");
notifyPropertyChanged(2);
}
than go to your item.xml file and call
android:onClick="#{predictionVM::onSubmitClicked}"
in your Button,
and
android:onClick="#{predictionVM.onImageClicked}
in your imaggView,
than go to your ItemAdapterClass
and inside onCreateViewHolder
predictionViewModel.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
#Override
public void onPropertyChanged(Observable sender, int propertyId) {
if (propertyId == 1) {
//do your stuff
}
else if (propertyId == 2) {
// do your stuff
}
The most elegant and frankly adequate solution would be not to do anything inside adapter!
I wrote an article about adapters, have a look RecyclerView Adapters
Straightforward: add a callback to your adapter and perform everything inside calling sight (fragment etc)
I have a Adapter which implements ListAdapter,
I have a one button on item of list, when I click on that button, that item is deleted from data, after deleting that item from list I want to refresh the List,
notifyDataSetChanged() method is not available in ListAdapter
Edited:
public class ShoppingListAdapter implements ListAdapter {
ArrayList<ProductInfoDTO> data;
private LayoutInflater inflater = null;
Context context;
Activity activity;
String TAG = getClass().getSimpleName();
DBQuery mDBQuery;
public ShoppingListAdapter(Context context, ArrayList<ProductInfoDTO> data) {
this.context = context;
this.data = data;
activity = (Activity) context;
inflater = ((Activity) context).getLayoutInflater();
mDBQuery = new DBQuery(context);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
MyCartItemView view = null;
if (convertView == null) {
view = new MyCartItemView(activity, data.get(position));
} else {
view = (MyCartItemView) convertView;
}
view.setPosition(position);
Button delete;
delete = (Button) view.findViewById(R.id.delete);
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "delete clicked", Toast.LENGTH_SHORT)
.show();
// delete from database
mDBQuery.DeleteCartData(data.get(position).cart_id);
// delete from data
data.remove(data.get(position));
// now I want to refresh the list here
}
});
return view;
}
#Override
public int getViewTypeCount() {
return data.size();
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public boolean isEmpty() {
return false;
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
#Override
public boolean areAllItemsEnabled() {
return true;
}
#Override
public boolean isEnabled(int position) {
return true;
}
}
Instead of using ListAdapter extend your Adapter with BaseAdapter. Then you get to use notifyDataSetChanged.
Edit:
Refer below.
https://stackoverflow.com/a/13431786/1995735
Try use
public class ShoppingListAdapter extends BaseAdapter {
// add unimplemented methods...
}
instead of public class ShoppingListAdapter implements ListAdapter{}. If there is error, let us know what does the error say.
Try this code..
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "delete clicked", Toast.LENGTH_SHORT)
.show();
// delete from database
mDBQuery.DeleteCartData(data.get(position).cart_id);
// delete from data
data.remove(data.get(position));
your_listview.invalidateViews(); //refresh the list here
}
});
That particular method calls a DataSetObserver. You can recreate the same method very easily. You should reference the Source code for BaseAdapter to see the implementation of ListAdapter Interface. you Can find it here at grepcode. you should also include an add(object) method in your code to make it more responsive and reusable.
implementing DataSetObserver
public class YourClass extends Something implements ListAdapter{
private final DataSetObservable mObservable = new DataSetObservable();
#Override
public void registerDataSetObserver(DataSetObserver observer) {
mObservable.registerObserver(observer);
}
#Override
public void unregisterDataSetObserver(DataSetObserver observer) {
mObservable.unregisterObserver(observer);
}
public void notifyDataSetChanged(){
mObservable.notifyChanged();
}
public void notifyDataSetInvalidated(){
mObservable.notifyInvalidated();
}
adding an add method
public void add(YourDataType object){ data.add(object);}
The real fun begins making it a real adapter that is filterable which you should look at the grepcode for ArrayAdapter and see everything that involves. One of the best things about android is the open source. So when in doubt read. The variables are self explanatory and the notes are top notch.