使用FirestorePagingAdapter的SnapshotParser

时间:2019-02-09 19:43:33

标签: java android firebase google-cloud-firestore firebaseui

我试图在模型中包含文档的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)测试:事件{id ='c5jUGQc4c7SHzbpT6N01',titre ='Final PSG / MARSEILLE',sport ='Football',lieu ='Bercy',date = Timestamp(seconds = 1550844000,nanoseconds = 0),dateLimit = Timestamp(seconds = 1551009600,nanoseconds = 0)}

2)测试:id = null

Firestore数据库:

Firestore Database

Gist with the same issue

答案:

SnapshotParser无法按我预期的方式工作,但我发现了如何在onClick()中访问文档的ID。我用以下代码替换了this line

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

1 个答案:

答案 0 :(得分:0)

根据您的评论:

  

是的,但是稍后我需要从recyclerview中单击某个项目时将其检索

由于您使用的是FirestorePagingAdapter,因此无法使用以下内容:

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

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

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);