Reputation: 63
I'm implementing a RecyclerView to show a list of Transactions. In one of its two ViewHolders, there is a button to delete transaction. The problem is, after clicking the button, nothing happened to the RecyclerView. I'm using Realm and MVP pattern, and have tried all solutions I could find, but nothing seems to work.
Here's TransactionListActivity, where the RecyclerView will be shown:
public class TransactionListActivity extends BaseActivity implements TransactionListView {
private static final String TAG = "TransactionListActivity";
@Inject
TransactionListPresenterInterface<TransactionListView> mPresenter;
TransactionListAdapter transactionListAdapter;
@BindView(R.id.transaction_list_recyclerview)
RecyclerView transactionListRecyclerView;
@Override
public void onPrepareTransactionListAdapter() {
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
transactionListRecyclerView.setLayoutManager(layoutManager);
List<TransactionListItem> transactionListItems = mPresenter.getAllTransactionItems();
transactionListAdapter = new TransactionListAdapter(this, transactionListItems);
transactionListAdapter.setOnDeleteTransactionClickListener(this::onDeleteTransaction);
transactionListRecyclerView.setAdapter(transactionListAdapter);
}
@Override
public void onDeleteTransaction(String id) {
mPresenter.onDeleteTransactionClick(String id);
}
@Override
public void refresh() {
transactionListAdapter.notifyDataSetChanged();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transaction_list);
getActivityComponent().inject(this);
setUnBinder(ButterKnife.bind(this));
ButterKnife.bind(this);
mPresenter.onAttach(this);
onPrepareTransactionListAdapter();
}
Here's my adapter:
public class TransactionListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "TransactionListAdapter";
private Context context;
public List<TransactionListItem> transactionListItems;
private OnDeleteTransactionClickListener mOnDeleteTransactionClickListener;
public TransactionListAdapter(Context context, List<TransactionListItem> transactionListItems) {
this.context = context;
this.transactionListItems = transactionListItems;
}
class TransactionItemViewHolder extends RecyclerView.ViewHolder {
...
@BindView(R.id.delete_transaction_button)
Button deleteTransactionButton;
...
public TransactionItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
class TransactionDateViewHolder extends RecyclerView.ViewHolder {
...
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch(viewType) {
case TransactionListItem.TYPE_DATE:
//inflate TransactionDateViewHolder here
case TransactionListItem.TYPE_TRANSACTION:
//inflate TransactionItemViewHolder here
}
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
switch(viewHolder.getItemViewType()) {
case TransactionListItem.TYPE_TRANSACTION:
ProductStockRecord productStockRecord = (ProductStockRecord) transactionListItems.get(position);
TransactionItemViewHolder transactionItemViewHolder = (TransactionItemViewHolder) viewHolder;
// populate view with data here
((TransactionItemViewHolder) viewHolder).deleteTransactionButton.setOnClickListener(v -> {
if (mOnDeleteTransactionClickListener != null) {
mOnDeleteTransactionClickListener.onDeleteTransactionClick(productStockRecord.getId());
}
});
break;
case TransactionListItem.TYPE_DATE:
//populate view with data here
break;
}
}
@Override
public int getItemCount() {
return transactionListItems.size();
}
@Override
public int getItemViewType(int position) { return transactionListItems.get(position).getType(); }
public void setOnDeleteTransactionClickListener(final OnDeleteTransactionClickListener onDeleteTransactionClickListener) {
mOnDeleteTransactionClickListener = onDeleteTransactionClickListener;
}
public interface OnDeleteTransactionClickListener {
void onDeleteTransactionClick(String id);
}
}
And here's my presenter:
public class TransactionListPresenter<V extends TransactionListView> extends BasePresenter<V> implements TransactionListPresenterInterface<V>, RealmDataManager.OnTransactionCallback {
private static final String TAG = "TransaxListPresenter";
@Inject
public TransactionListPresenter(final RealmDataManager realmDataManager) { super(realmDataManager); }
@Override
public List<TransactionListItem> getAllTransactionItems() {
List<ProductStockRecord> productStockRecordList = getRealmDataManager().getAllProductStockRecords();
List<TransactionListItem> transactionListItems = new ArrayList<>();
// preprocess transactions here
return transactionListItems;
}
@Override
public void onDeleteTransactionClick(String id) {
getRealmDataManager().deleteProductStockRecord(id, this);
getView().refresh();
Log.d(TAG,"deleteTransaction() performed");
}
}
Here's the updated (and working) version of RealmService, and all codes above have been fixed accordingly:
public void deleteProductStockRecord(final String id, final OnTransactionCallback onTransactionCallback) {
mRealm.executeTransactionAsync(realm -> {
ProductStockRecord productStockRecord = realm.where(ProductStockRecord.class).equalTo("id", id).findFirst();
productStockRecord.deleteFromRealm();
}, () -> {
if (onTransactionCallback != null) {
onTransactionCallback.onRealmSuccess();
}
}, error -> {
if (onTransactionCallback != null) {
onTransactionCallback.onRealmError(error);
}
});
}
I believe I make some mistakes somewhere in my adapter implementation. I would be really thankful if anyone could help me fix the problem, point my mistake, or point me in the right direction. Thanks in advance
Upvotes: 1
Views: 2530
Reputation: 522
In case you meant "recyclerview visibly does not change":
If you delete an item from a recyclerview, you can use mAdapter.notifyDataSetChanged();
. Doing this updates the contents of the visible recyclerview to the items in the list of the adapter at the moment of calling.
Upvotes: 0
Reputation: 499
I think the issue might be the reference to List<TransactionListItem>
is not updated in your adapter.
If you look at this code in your presenter:
@Override
public List<TransactionListItem> getAllTransactionItems() {
List<ProductStockRecord> productStockRecordList = getRealmDataManager().getAllProductStockRecords();
List<TransactionListItem> transactionListItems = new ArrayList<>();
// preprocess transactions here
return transactionListItems;
}
You're creating a new List<TransactionListItem>
which is what your adapter is pointing to. So in your onDeleteTransactionClick
method, you have to make sure you pass the updated list to your adapter before calling getView().refresh()
. Because otherwise, the list in the adapter won't change and you will see that the item is not being deleted.
Ideally though, I would recommend using something like DiffUtil
(or calculate manually) to get the position of the deleted item and call notifyItemRemoved
instead of refreshing the entire RecyclerView
.
Upvotes: 1