首页 > 解决方案 > 使用 FirestorePagingAdapter 的 SnapshotParser

问题描述

我试图在我的模型id中包含文档,但是当我访问它时,id 的值是null.

在片段/活动中:

public class MyEventsFragment extends Fragment {

    private OnFragmentInteractionListener mListener;
    private FirestorePagingAdapter mAdapter;
    private FirebaseFirestore mFirebaseFirestore;

    public MyEventsFragment() {
        // Required empty public constructor
    }

    public static MyEventsFragment newInstance() {
        return new MyEventsFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mFirebaseFirestore = FirebaseFirestore.getInstance();

        Query query = mFirebaseFirestore.collection("events");

        PagedList.Config config = new PagedList.Config.Builder()
                .setEnablePlaceholders(false)
                .setPrefetchDistance(10)
                .setPageSize(20)
                .build();

        FirestorePagingOptions<Event> options = new FirestorePagingOptions.Builder<Event>()
                .setLifecycleOwner(this)
                .setQuery(query, config, new SnapshotParser<Event>() {
                    @NonNull
                    @Override
                    public Event parseSnapshot(@NonNull DocumentSnapshot snapshot) {
                        Event evt = new Event(
                                snapshot.getId(),
                                snapshot.getString("titre"),
                                snapshot.getString("sport"),
                                snapshot.getString("lieu"),
                                snapshot.get("date", Timestamp.class),
                                snapshot.get("dateLimit", Timestamp.class));
                        Log.i("TEST", evt.toString());
                        return evt;
                    }
                })
                .build();

        mAdapter = new EventFirestorePagingAdapter(options, getContext());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_list_events, container, false);

        RecyclerView mRecyclerView = view.findViewById(R.id.recyclerViewListEvent);
        LinearLayoutManager mLayoutManager = new LinearLayoutManager(getContext());
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mAdapter);

        return view;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onStart() {
        super.onStart();
        mAdapter.startListening();
    }

    @Override
    public void onStop() {
        super.onStop();
        mAdapter.stopListening();
    }

    public interface OnFragmentInteractionListener {
        void onFragmentInteraction(Uri uri);
    }
}

EventFirestorePagingAdapter(扩展 FirestorePagingAdapter):

 public class EventFirestorePagingAdapter extends FirestorePagingAdapter<Event, EventFirestorePagingAdapter.EventViewHolder> {

    private Context mContext;

    public EventFirestorePagingAdapter(@NonNull FirestorePagingOptions<Event> options, Context context) {
        super(options);
        this.mContext = context;
    }

    public class EventViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        TextView titre, sport, lieu, date;

        public EventViewHolder(@NonNull View itemView) {
            super(itemView);

            titre = itemView.findViewById(R.id.titreRecyclerView);
            sport = itemView.findViewById(R.id.sportRecyclerView);
            lieu = itemView.findViewById(R.id.lieuRecyclerView);
            date = itemView.findViewById(R.id.dateRecyclerView);

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            /*for(Map.Entry<String, Object> map: getItem(getAdapterPosition()).getData().entrySet()){
                Log.i("TEST", map.getKey());
            }*/

            Event event = getItem(getAdapterPosition()).toObject(Event.class);
            Log.i("TEST", "id = " + event.getId());
            Toast.makeText(mContext, "OnClick on position : " + getAdapterPosition() + " \nTest : " + event.getTitre() + "\nId : " + event.getId(), Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onBindViewHolder(@NonNull EventViewHolder holder, int position, @NonNull Event model) {
        holder.titre.setText(model.getTitre());
        holder.sport.setText(model.getSport());
        holder.lieu.setText(model.getLieu());
        holder.date.setText(model.getDate().toDate().toString());
    }

    @NonNull
    @Override
    public EventViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i)     {
        View view = LayoutInflater.from(mContext).inflate(R.layout.recyclerview_card_row, viewGroup, false);
        return new EventViewHolder(view);
    }
}

事件类:

public class Event {
    private String id;
    private String titre;
    private String sport;
    private String lieu;
    private Timestamp date;
    private Timestamp dateLimit;

    public Event(){ } // Needed for Firebase

    public Event(String id, String titre, String sport, String lieu, Timestamp date, Timestamp dateLimit) {
        this.id = id;
        this.titre = titre;
        this.sport = sport;
        this.lieu = lieu;
        this.date = date;
        this.dateLimit = dateLimit;
    }

    // ... getters & setters
}

调试:

1) 测试:Event{id='c5jUGQc4c7SHzbpT6N01', titre='Final PSG/MARSEILLE', sport='Football', lieu='Bercy', date=Timestamp(seconds=1550844000, nanoseconds=0), dateLimit=Timestamp(秒=1551009600,纳秒=0)}

2) 测试:id = null

Firestore 数据库:

Firestore 数据库

有同样问题的要点

回答 :

SnapshotParser 没有像我预期的那样工作,但我发现了如何在 onClick() 中访问文档的 id。我用以下代码替换了这一行:

DocumentSnapshot documentSnapshot = getCurrentList().get(getAdapterPosition());
Chat chat = documentSnapshot.toObject(Chat.class);
chat.setId(documentSnapshot.getId());

标签: javaandroidfirebasegoogle-cloud-firestorefirebaseui

解决方案


根据您的评论:

是的,但是我需要稍后在我的 recyclerview 中单击一个项目时检索它

因为您使用的是 aFirestorePagingAdapter而您不能使用这样的东西:

String id = getSnapshots().getSnapshot(position).getId(); //Works only with FirestoreRecyclerAdapter

您需要将文档的 ID 存储为文档的属性。正如我在您的Event课程中看到的那样,该属性id存在,但在数据库中没有id保存文档 ID 的属性。为了解决这个问题,您需要在Event创建新对象时将文档的 id 传递给构造函数,如下所示:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference eventsRef = rootRef.collection("events");
String id = eventsRef.document().getId();
Event event = new Event(id, titre, sport, lieu, date, dateLimit);
eventsRef.document(id).set(event);

推荐阅读