Android Java - RecyclerView с Firestore не обновляется при удалении элемента - PullRequest
0 голосов
/ 09 января 2020

Я использую Firestore для хранения документов, представляющих людей с именем. Я использую RecyclerView для их отображения, заполняя его картами, которые отображают имена, извлеченные из Firestore. Я реализовал функцию смахивания для удаления, которая удаляет человека из Firestore, когда вы проводите пальцем по карточке этого человека влево или вправо в RecyclerView.

Моя проблема заключается в том, что считывание карты не приводит к тому, что RecyclerView обновление - когда я проверяю Firestore, удаление действительно происходит, но RecyclerView просто показывает пробел, где раньше была эта карта. Ни одна из карточек под удаленной карточкой не «двигается вверх», чтобы заполнить этот пробел.

Внутри onCreate () для действия, которое содержит RecyclerView, я вызываю функцию setUpRecyclerView (). Вот та функция, которая содержит код для считывания:

private void setUpRecyclerView() {
    // create the query who's results you want to populate the recyclerView with
    Query query = clientsReference.orderBy("lastNameLowercase")
            .orderBy("firstNameLowercase");

    // how we get the query into the adapter
    FirestoreRecyclerOptions<Client> options = new FirestoreRecyclerOptions.Builder<Client>()
            .setQuery(query, Client.class)
            .build();

    // assign the adapter
    adapter = new ClientAdapter(options);

    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(adapter);

    /**
     * This section handles what happens when you swipe an item in the recyclerView list
     */
    new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,
            ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        @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) {
            int position = viewHolder.getAdapterPosition();
            adapter.deleteClient(position);
            //adapter.notifyItemRemoved(position);
        }
    }).attachToRecyclerView(recyclerView);

    /**
     * This section handles what happens when you click on an item in the recyclerView list
     */
    adapter.setOnItemClickListener(new ClientAdapter.OnItemClickListener() {
        @Override
        public void onItemClick(DocumentSnapshot documentSnapshot, int position) {
            Client client = documentSnapshot.toObject(Client.class);
            String id = documentSnapshot.getId();
            Intent intentDisplayClient = new Intent(MainActivity.this, DisplayClientActivity.class);

            // Pass ahead the client's id from Firestore to the next activity
            intentDisplayClient.putExtra(KEY_ID, id);
            startActivity(intentDisplayClient);
        }
    });
}

А вот класс адаптера:

public class ClientAdapter extends FirestoreRecyclerAdapter<Client, ClientAdapter.ClientHolder> {

private OnItemClickListener listener;

/**
 * Create a new RecyclerView adapter that listens to a Firestore Query.
 */
public ClientAdapter(@NonNull FirestoreRecyclerOptions<Client> options) {
    super(options);
}

@Override
protected void onBindViewHolder(@NonNull ClientHolder holder, int position, @NonNull Client model) {
    String lastNameWithComma = model.getLastName() + ", ";
    holder.textViewLastName.setText(lastNameWithComma);
    holder.textViewFirstName.setText(model.getFirstName());
}

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

public void deleteClient(int position) {
    getSnapshots().getSnapshot(position).getReference().delete();
}

class ClientHolder extends RecyclerView.ViewHolder {
    TextView textViewLastName;
    TextView textViewFirstName;

    public ClientHolder(@NonNull View itemView) {
        super(itemView);
        textViewLastName = itemView.findViewById(R.id.rv_tv_last_name);
        textViewFirstName = itemView.findViewById(R.id.rv_tv_first_name);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = getAdapterPosition();
                if (position != RecyclerView.NO_POSITION && listener != null) {
                    listener.onItemClick(getSnapshots().getSnapshot(position), position);
                }
            }
        });
    }
}

public interface OnItemClickListener {
    void onItemClick(DocumentSnapshot documentSnapshot, int position);
}

public void setOnItemClickListener(OnItemClickListener listener) {
    this.listener = listener;
}
}

Вы заметите, что в onSwiped есть закомментированная строка () функция внутри setUpRecyclerView (). Когда эта линия используется, происходит другое нежелательное поведение: RecyclerView «перемещает» нижние карты, чтобы заполнить пробел, оставленный удаленной картой, но любая карта в нижней части RecyclerView дублируется и помещается внизу. Так что если это выглядит так:

AB C D

... и я удаляю C, то это выглядит так:

ABDD

Так что я застрял либо со списком, который вообще не обновляется, либо со странным обновлением, которое не имеет смысла.

Если вам интересно, я следую этому руководству до письма и он не работает:

https://www.youtube.com/watch?v=dTuhMFP-a1g&list=PLrnPJCHvNZuAXdWxOzsN5rgG2M4uJ8bH1&index=6&t=0s

Ответы [ 2 ]

0 голосов
/ 04 февраля 2020

Пожалуйста, обратитесь это . Я решил эту проблему, используя это. Надеюсь, это поможет.

Вы должны написать это в методе onStart (). Ты тоже это сделал?

0 голосов
/ 09 января 2020

Если вы используете FirestoreRecyclerAdapter, вам не нужно уведомлять адаптер вручную. Изменения в базе данных будут отражены в вашем пользовательском интерфейсе. Следовательно, нет необходимости вызывать adapter.notifyItemRemoved(position).

. Кроме того, delete(...) выполняется асинхронно. Поэтому вам нужно добавить обратный вызов, чтобы увидеть, был ли документ успешно удален:

public void deleteClient(int position) {
    getSnapshots().getSnapshot(position).getReference().delete()
         .addOnSuccessListener(new OnSuccessListener<Void>() {
              @Override
              public void onSuccess(Void aVoid) {
                  Log.d(TAG, "DocumentSnapshot successfully deleted!");
              }
    })
    .addOnFailureListener(new OnFailureListener() {
         @Override
         public void onFailure(@NonNull Exception e) {
              Log.w(TAG, "Error deleting document", e);
         }
    });
}
...