Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I've recently learned of ListAdapter and applied to my RecyclerView. I followed a tutorial and the list of items (retrieved from a database via Retrofit) is displayed as expected. However, when I add a new item the list does not update unless I leave the activity and return. What am I missing here?

ViewModel

public class NoteViewModel extends ViewModel {

private static final String TAG = "NoteViewModel";
MutableLiveData<List<Note>> mutableLiveData;

public LiveData<List<Note>> getNoteList(String userID) {
    if (mutableLiveData == null) {
        mutableLiveData = new MutableLiveData<>();
    }
    initNoteList(userID);
    return mutableLiveData;
}

private void initNoteList(String userID) {
    List<Note> noteList = new ArrayList<>();
    Call<List<Note>> noteCall = APIClient.getUserService().retrieveUserNotes(userID);
    noteCall.enqueue(new Callback<List<Note>>() {
        @Override
        public void onResponse(Call<List<Note>> call, Response<List<Note>> response) {
            if (response.isSuccessful()) {
                if (response.body() != null) {
                    noteList.addAll(response.body());
                    mutableLiveData.setValue(noteList);
                    Log.d(TAG, "onResponse: " + noteList.size());
                } else {
                    Log.d(TAG, "onResponse: Retrieve Note List Body Error");
                }
            } else {
                Log.d(TAG, "onResponse: Response Fail");
            }
        }

        @Override
        public void onFailure(Call<List<Note>> call, Throwable t) {
            Log.d(TAG, "onFailure: Retrieve Note List Failure: " + t.getMessage());
        }
    });
}

ListAdapter

public class NoteListAdapter extends ListAdapter<Note, NoteListAdapter.NoteViewHolder> {

NoteClickListener noteClickListener;

public NoteListAdapter(@NonNull DiffUtil.ItemCallback<Note> diffCallback, NoteClickListener noteClickListener) {
    super(diffCallback);
    this.noteClickListener = noteClickListener;
}

@NonNull
@Override
public NoteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.note_item, parent, false);
    return new NoteViewHolder(v, noteClickListener);
}

@Override
public void onBindViewHolder(@NonNull NoteViewHolder holder, int position) {
    Note note = getItem(position);
    assert note != null;
    holder.bind(note);
}

public static class NoteViewHolder extends RecyclerView.ViewHolder {

    NoteClickListener noteClickListener;
    TextView noteTitle;

    public NoteViewHolder(View itemView, NoteClickListener noteClickListener) {
        super(itemView);
        this.noteClickListener = noteClickListener;
        noteTitle = itemView.findViewById(R.id.note_title);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                noteClickListener.onNoteClick(getAbsoluteAdapterPosition());
            }
        });

    public void bind(Note note) {
        noteTitle.setText(note.getTitle());
    }
}

public interface NoteClickListener {
    void onNoteClick(int position);
    void onNoteLongClick(int position);
}

Activity

public class NotesList extends AppCompatActivity {

private final String TAG = getClass().getSimpleName();
Toolbar toolbar;
FloatingActionButton addNote, deleteNote;
User user;
NoteListAdapter noteListAdapter;
NoteViewModel noteViewModel;
private static final int EDIT_NOTE = 10001;
private static final int SAVE_NOTE = 10002;
private boolean reloadNotes = false;
List<Note> noteList;
RecyclerView recyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notes_list);

    Intent notes = getIntent();
    user = (User) notes.getParcelableExtra("user");

    addNote = findViewById(R.id.fab_notes);
    deleteNote = findViewById(R.id.delete_notes);

    deleteNote.setVisibility(View.GONE);

    toolbar = findViewById(R.id.toolbar);
    toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24);
    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            NotesList.this.onBackPressed();
        }
    });

    if (getSupportActionBar() != null) {
        getSupportActionBar().hide();
    }

    addNote.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent newNote = new Intent(NotesList.this, CreateUserNote.class);
            newNote.putExtra("user", user);
            NotesList.this.startActivity(newNote);
        }
    });
    recyclerView = findViewById(R.id.notesRecyclerView);
    noteListAdapter = new NoteListAdapter(Note.itemCallback, new NoteListAdapter.NoteClickListener() {
        @Override
        public void onNoteClick(int position) {
            // TODO: Edit Note
            Toast.makeText(NotesList.this, noteListAdapter.getCurrentList().get(position).getTitle(), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onNoteLongClick(int position) {
            // TODO: Delete Note
        }
    });
    recyclerView.setAdapter(noteListAdapter);
    noteViewModel = new ViewModelProvider(this).get(NoteViewModel.class);
    noteViewModel.getNoteList(user.getUser_id()).observe(NotesList.this, new Observer<List<Note>>() {
        @Override
        public void onChanged(List<Note> notes) {
            noteListAdapter.submitList(notes);
        }
    });

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
259 views
Welcome To Ask or Share your Answers For Others

1 Answer

I found a workaround which is to call submitList() in onActivityResult() after adding a new item. However, I would like to know if this is good programming.

Here is what I added:

    @Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == SAVE_NOTE) {
        if (resultCode == CreateUserNote.RESULT_OK) {
            noteListAdapter.submitList(noteViewModel.getNoteList(user.getUser_id()).getValue());
        }
    }
}

Changed the following:

        addNote.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent newNote = new Intent(NotesList.this, CreateUserNote.class);
            newNote.putExtra("user", user);
            NotesList.this.startActivityForResult(newNote, SAVE_NOTE);
        }
    });

Create new item activity retrofit call:

 private void saveNote(String user_id, String title, String content) {
    Call<String> noteCall = APIClient.getUserService().addUserNote(user_id, title, content);
    noteCall.enqueue(new Callback<String>() {
        @Override
        public void onResponse(Call<String> call, Response<String> response) {
            if (response.isSuccessful()) {
                if (response.body() != null) {
                    if (response.body().equals("true")) {
                        setResult(CreateUserNote.RESULT_OK);
                        finish();
                    } else {
                        Toast.makeText(CreateUserNote.this, "Save User Note Failure", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }

        @Override
        public void onFailure(Call<String> call, Throwable t) {
            Toast.makeText(CreateUserNote.this, "Save User Note Failure: " + t.getMessage(), Toast.LENGTH_SHORT).show();
            Log.w("Error", "Save User Note Failure: " + t.getMessage());
        }
    });
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...