I've added swipe to my app, to delete specified note. For couple of days, I've facing problem with displaying data after swipe. For clarify: Let's say, we have two items in recycler view. Whenever we swipe one of them, the second one should be visible, but it's not until I'll re-run the app. How I may solve it?
Main Activity
public class MainActivity extends AppCompatActivity implements MemoAdapter.OnNoteListener {
private static final String TAG = "MainActivity";
//Vars
private ArrayList<Note> mNotes = new ArrayList<>();
private MemoRepository mRepository;
private MemoAdapter mMemoAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRepository = new MemoRepository(this);
Toolbar toolbar = (Toolbar) findViewById(R.id.memoToolbar);
setSupportActionBar(toolbar);
setTitle("My memos");
initRecyclerView();
}
//This method would be called after getting result from memo_content such as new memo, or edited existing memo.
@Override
protected void onResume() {
super.onResume();
getMemos();
}
private void getMemos(){
mRepository.getAllMemos().observe(this, new Observer<List<Note>>() {
@Override
public void onChanged(List<Note> notes) {
if (mNotes.size() > 0){
notes.clear();
}
if (notes != null){
mNotes.addAll(notes);
mMemoAdapter.watchMemoChanges((ArrayList<Note>) notes);
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.icon_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.addNewNote:
Toast.makeText(this, "Click!", Toast.LENGTH_SHORT).show();
startActivity(new Intent(this, memo_content.class));
break;
case R.id.deleteAllNotes:
Toast.makeText(this, "Delete!", Toast.LENGTH_SHORT).show();
mRepository.deleteAllMemos();
break;
}
return super.onOptionsItemSelected(item);
}
private void initRecyclerView(){
//UI
RecyclerView mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
mMemoAdapter = new MemoAdapter(mNotes, this);
new ItemTouchHelper(itemTouch).attachToRecyclerView(mRecyclerView);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mMemoAdapter);
}
@Override
public void onMemoClick(int position) {
Intent intent = new Intent(this, memo_content.class);
intent.putExtra("memo_content", mNotes.get(position));
startActivity(intent);
}
private ItemTouchHelper.SimpleCallback itemTouch = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.START | ItemTouchHelper.LEFT) {
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
mRepository.deleteMemo(mNotes.get(viewHolder.getAdapterPosition()));
Log.d(TAG, "onSwiped: "+mNotes.get(viewHolder.getAdapterPosition()));
}
};
}
Adapter
public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.MemoViewHolder> {
private ArrayList<Note> mNotes;
private OnNoteListener mListener;
public class MemoViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView title, timestamp;
private MemoViewHolder(@NonNull final View itemView) {
super(itemView);
this.title = (TextView) itemView.findViewById(R.id.title);
this.timestamp = (TextView) itemView.findViewById(R.id.timestamp);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
mListener.onMemoClick(getAdapterPosition());
}
}
public MemoAdapter(ArrayList<Note> notes, OnNoteListener listener) {
this.mNotes = notes;
this.mListener = listener;
}
@NonNull
@Override
public MemoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_memo, parent, false);
return new MemoViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MemoViewHolder holder, int position) {
holder.title.setText(mNotes.get(position).getTitle());
holder.timestamp.setText(mNotes.get(position).getTimestamp());
}
public void watchMemoChanges(ArrayList<Note> notes){
this.mNotes = notes;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return mNotes.size();
}
public interface OnNoteListener{
void onMemoClick(int position);
}
Short answer:
You need to remove the statement notes.clear()
when you receive a change in the LiveData
list from the database via the observer.
Detailed answer
When you first run your app, it will show all right list because the condition if (mNotes.size() > 0)
is not met, and so the received list won't be cleared via notes.clear()
, so the RecyclerView
will display the right data.
But when you delete a note, then when the observer is triggered again with the new list, the condition if (mNotes.size() > 0)
will be met, so you will clear the list that is coming from the database before feeding the adapter with it, so the RecyclerView
will be free of data.
So to solve this please replace notes.clear();
with mNotes.clear();
So the right code will be:
private void getMemos(){
mRepository.getAllMemos().observe(this, new Observer<List<Note>>() {
@Override
public void onChanged(List<Note> notes) {
if (mNotes.size() > 0){
mNotes.clear();
}
if (notes != null){
mNotes.addAll(notes);
mMemoAdapter.watchMemoChanges((ArrayList<Note>) notes);
}
}
});
}
Wish that help you out. I didn't examine the rest of code, please let me know if there is another issue to help more