I’m having a problem, that maybe we can solve it and help the community. I have made an Adapter for my RecyclerView and I have created a listener for the constraint layout in order to remove one element of the list. As you can see in the code the delete message works well but I don’t know how to update the RecyclerView from the AccountFragment (the one that’s using this adapter). Does anyone know how to notify that changes?
AccountFragment:
public class AccountFragment extends Fragment { private TextView textViewUserProfileUsername; private TextView textViewUserProfileDescription; private ImageButton imageButtonAccountEdit; private EditText editTextAccountDescription; private RecyclerView recyclerViewUserProfileComments; private TextView textViewUserProfileNoComments; private ImageView imageViewUserProfileSendMessage; private EditText editTextUserProfileSendMessage; private final Gson gson = new Gson(); private User userLocal; private SharedPreferences sharedPreferences; private Context context; private AlertDialog dialog; private String previousDescription; private AccountCommentsAdapter accountCommentsAdapter; private final List<UserComments> userCommentsList = new ArrayList<>(); public AccountFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = getActivity(); assert context != null; sharedPreferences = context.getSharedPreferences(Constants.sharedPreferencesDocName, Context.MODE_PRIVATE); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_account, container, false); } @Override public void onViewCreated(@NonNull @NotNull View view, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); bindUI(view); setListeners(); userLocal = gson.fromJson(sharedPreferences.getString("user", ""), User.class); showUserInformation(); setAdapter(); } private void bindUI(View view) { textViewUserProfileUsername = view.findViewById(R.id.textViewUserProfileUsername); textViewUserProfileDescription = view.findViewById(R.id.textViewUserProfileDescription); imageButtonAccountEdit = view.findViewById(R.id.imageButtonAccountEdit); recyclerViewUserProfileComments = view.findViewById(R.id.recyclerViewUserProfileComments); textViewUserProfileNoComments = view.findViewById(R.id.textViewUserProfileNoComments); imageViewUserProfileSendMessage = view.findViewById(R.id.imageViewUserProfileSendMessage); editTextUserProfileSendMessage = view.findViewById(R.id.editTextUserProfileSendMessage); } private void setListeners() { imageButtonAccountEdit.setOnClickListener(v -> showEditDescriptionDialog()); imageViewUserProfileSendMessage.setOnClickListener(view -> { if (!TextUtils.isEmpty(editTextUserProfileSendMessage.getText().toString())) { final Date currentTime = new Date(); @SuppressLint("SimpleDateFormat") SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm"); TimeZone timeZone = simpleDateFormat.getTimeZone(); simpleDateFormat.setTimeZone(timeZone); String date = simpleDateFormat.format(currentTime); final UserComments userCommentsToAdd = new UserComments(userLocal.getId(), userLocal.getId(), userLocal.getUsername(), userLocal.getUsername(), editTextUserProfileSendMessage.getText().toString().trim(), date); editTextUserProfileSendMessage.setText(""); addComment(userCommentsToAdd); } }); } private void showUserInformation() { textViewUserProfileUsername.setText(userLocal.getUsername()); textViewUserProfileDescription.setText(userLocal.getDescription()); getUserComments(); } private void showEditDescriptionDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(getString(R.string.edit_description)); final View customLayout = getLayoutInflater().inflate(R.layout.alert_dialog_edit_account, null); builder.setView(customLayout); dialog = builder.create(); editTextAccountDescription = customLayout.findViewById(R.id.editTextAccountDescription); if (userLocal.getDescription() != null) { editTextAccountDescription.setText(userLocal.getDescription()); previousDescription = editTextAccountDescription.getText().toString(); } Button buttonAccountCancelDescription = customLayout.findViewById(R.id.buttonAccountCancelDescription); Button buttonAccountSaveDescription = customLayout.findViewById(R.id.buttonAccountSaveDescription); buttonAccountSaveDescription.setOnClickListener(v -> saveUserDescription()); buttonAccountSaveDescription.setOnClickListener(v -> { if (editTextAccountDescription.getText().toString().length() <= 150) { saveUserDescription(); } else { setErrors(2); } }); editTextAccountDescription.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.length() > 150) { setErrors(2); } } @Override public void afterTextChanged(Editable s) { } }); buttonAccountCancelDescription.setOnClickListener(v -> dialog.dismiss()); dialog.setCancelable(false); dialog.show(); } private void saveUserDescription() { if (!editTextAccountDescription.getText().toString().isEmpty()) { if (!editTextAccountDescription.getText().toString().equals(previousDescription)) { userLocal.setDescription(editTextAccountDescription.getText().toString()); sharedPreferences.edit().putString("user", gson.toJson(userLocal)).apply(); Thread thread = new Thread() { @Override public void run() { Response response; try { response = UserRequests.editUserDescription(userLocal.getId(), userLocal.getDescription()); if (response.code() == 200) { String responseBody = Objects.requireNonNull(response.body()).string(); responseBody = responseBody.replace("rn", ""); if (responseBody.contains("1")) { updateDescription(); } else if (responseBody.contains("2")) { updateDescription(); } else { setErrors(1); } } else { setErrors(1); } } catch (Exception ex) { ex.printStackTrace(); } } }; thread.start(); } else { setErrors(4); } } else { setErrors(3); } } private void updateDescription() { Thread thread = new Thread() { public void run() { requireActivity().runOnUiThread(() -> { textViewUserProfileDescription.setText(userLocal.getDescription()); dialog.dismiss(); }); } }; thread.start(); } private void setErrors(int error) { switch (error) { case 1: Thread thread = new Thread() { public void run() { requireActivity().runOnUiThread(() -> Toast.makeText(context, getString(R.string.generic_error), Toast.LENGTH_SHORT).show()); } }; thread.start(); break; case 2: editTextAccountDescription.setError(getString(R.string.description_length)); editTextAccountDescription.requestFocus(); break; case 3: editTextAccountDescription.setError(getString(R.string.required_field)); editTextAccountDescription.requestFocus(); break; case 4: dialog.dismiss(); break; } } private void setAdapter() { LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context); linearLayoutManager.setStackFromEnd(true); recyclerViewUserProfileComments.setLayoutManager(linearLayoutManager); recyclerViewUserProfileComments.scrollToPosition(userCommentsList.size() - 1); } private void displayMessages() { if (userCommentsList.size() > 0) { Thread thread = new Thread() { public void run() { requireActivity().runOnUiThread(() -> { if (recyclerViewUserProfileComments.getVisibility() == View.GONE) { recyclerViewUserProfileComments.setVisibility(View.VISIBLE); } if (textViewUserProfileNoComments.getVisibility() == View.VISIBLE) { textViewUserProfileNoComments.setVisibility(View.GONE); } accountCommentsAdapter = new AccountCommentsAdapter(context, userCommentsList); recyclerViewUserProfileComments.setAdapter(accountCommentsAdapter); recyclerViewUserProfileComments.scrollToPosition(userCommentsList.size() - 1); accountCommentsAdapter.notifyDataSetChanged(); }); } }; thread.start(); } else { Thread thread = new Thread() { public void run() { requireActivity().runOnUiThread(() -> { recyclerViewUserProfileComments.setVisibility(View.GONE); textViewUserProfileNoComments.setVisibility(View.VISIBLE); }); } }; thread.start(); } } private void addComment(UserComments userCommentsToAdd) { Thread thread = new Thread() { @Override public void run() { Response response; try { response = UserCommentsRequests.addUserComment(userCommentsToAdd); if (response.code() == 200) { String responseBody = Objects.requireNonNull(response.body()).string(); responseBody = responseBody.replace("rn", ""); if (responseBody.contains("1")) { userCommentsList.add(userCommentsToAdd); userCommentsList.clear(); getUserComments(); } } else if (response.code() == 204) { displayMessages(); } else { setErrors(1); } } catch (Exception ex) { ex.printStackTrace(); } } }; thread.start(); } private void getUserComments() { Thread thread = new Thread() { @Override public void run() { Response response; try { response = UserCommentsRequests.getUserComments(userLocal.getId()); if (response.code() == 200) { String responseBody = Objects.requireNonNull(response.body()).string(); responseBody = responseBody.replace("rn", ""); JSONArray responseArray = new JSONArray(responseBody); for (int i = 0; i < responseArray.length(); i++) { String jsonObjectString = responseArray.getJSONObject(i).toString(); userCommentsList.add(gson.fromJson(jsonObjectString, UserComments.class)); } displayMessages(); } else if (response.code() == 204) { displayMessages(); } else { setErrors(1); } } catch (Exception ex) { ex.printStackTrace(); } } }; thread.start(); } }
AccountCommentsAdapter:
public class AccountCommentsAdapter extends RecyclerView.Adapter<AccountCommentsAdapter.AccountCommentsAdapterViewHolder> { private final Context context; List<UserComments> userCommentsList; public static final int MSG_TYPE_LEFT = 0; public static final int MSG_TYPE_RIGHT = 1; public AccountCommentsAdapter(Context context, List<UserComments> userCommentsList) { this.context = context; this.userCommentsList = userCommentsList; } @NonNull @NotNull @Override public AccountCommentsAdapterViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) { View view; if (viewType == MSG_TYPE_RIGHT) { view = LayoutInflater.from(context).inflate(R.layout.fragment_chat_message_sent, parent, false); } else { view = LayoutInflater.from(context).inflate(R.layout.fragment_chat_message_received, parent, false); } return new AccountCommentsAdapterViewHolder(view); } @Override public int getItemViewType(int position) { FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); assert firebaseUser != null; if (userCommentsList.get(position).getUser_from_username().equals(firebaseUser.getDisplayName())) { return MSG_TYPE_RIGHT; } else { return MSG_TYPE_LEFT; } } @Override public void onBindViewHolder(@NonNull @NotNull AccountCommentsAdapterViewHolder holder, int position) { UserComments userComments = userCommentsList.get(position); int viewType = holder.getItemViewType(); if (viewType == MSG_TYPE_LEFT) { holder.textViewMessageUsername.setText(userComments.getUser_from_username()); holder.textViewMessageUsername.setOnClickListener(v -> { Intent intent = new Intent(context, UserProfileActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Bundle bundle = new Bundle(); bundle.putString("userId", userComments.getUser_from_id()); bundle.putString("username", userComments.getUser_from_username()); intent.putExtras(bundle); context.startActivity(intent); }); holder.constraintLayoutMessageRight.setOnLongClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(R.string.delete_message) .setPositiveButton(R.string.yes, (dialogInterface, i) -> deleteMessage(position)) .setNegativeButton(R.string.no, (dialogInterface, which) -> dialogInterface.dismiss()); builder.create(); builder.show(); return false; }); } else { holder.constraintLayoutMessageRight.setOnLongClickListener(v -> { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(R.string.delete_message) .setPositiveButton(R.string.yes, (dialogInterface, i) -> deleteMessage(position)) .setNegativeButton(R.string.no, (dialogInterface, which) -> dialogInterface.dismiss()); builder.create(); builder.show(); return false; }); } holder.textViewMessageMessage.setText(userComments.getMessage()); holder.textViewMessageTime.setText(userComments.getCreated_time()); } @Override public int getItemCount() { return userCommentsList.size(); } public static class AccountCommentsAdapterViewHolder extends RecyclerView.ViewHolder { ConstraintLayout constraintLayoutMessageRight; TextView textViewMessageMessage; TextView textViewMessageTime; TextView textViewMessageUsername; public AccountCommentsAdapterViewHolder(@NonNull @NotNull View itemView) { super(itemView); textViewMessageMessage = itemView.findViewById(R.id.textViewMessageMessage); textViewMessageTime = itemView.findViewById(R.id.textViewMessageTime); constraintLayoutMessageRight = itemView.findViewById(R.id.constraintLayoutMessageRight); textViewMessageUsername = itemView.findViewById(R.id.textViewMessageUsername); } } private void deleteMessage(int position) { UserComments userCommentsToRemove = userCommentsList.get(position); Thread thread = new Thread() { @Override public void run() { Response response; try { response = UserCommentsRequests.removeUserComments(userCommentsToRemove.getId()); if (response.code() == 200) { String responseBody = Objects.requireNonNull(response.body()).string(); responseBody = responseBody.replace("rn", ""); if (responseBody.contains("1")) { userCommentsList.remove(position); // Here it should update the recyclerview in order to notify that element has been removed. } } } catch (Exception ex) { ex.printStackTrace(); } } }; thread.start(); } }
UPDATE:
Solved by adding this method and then call it after userCommentsList.remove(position):
private void updateUI(){ Handler mainHandler = new Handler(context.getMainLooper()); Runnable runnable = this::notifyDataSetChanged; mainHandler.post(runnable); }
Advertisement
Answer
Inside the adapter you can use notifyDataSetChanged()