将FirebaseRecyclerViewAdapter耦合到布尔/stringMap.Entry

我正在使用我的应用程序的许多位置的com.firebaseui:firebase-ui:0.2.0库中的FirebaseRecyclerViewAdapter 。 我的问题是如何应用它在查询参数返回一些'索引'条目值(Map.Entry)的情况下。

正如Firebase文档( https://www.firebase.com/docs/android/guide/structuring-data.html )中所述,我使用索引来保持数据结构不变。 这导致了我需要将这些索引绑定到ViewHolder的情况。 在填充视图方法中,我使用索引的键来检索数据以填充视图。

我有麻烦创build适配器,不知道如何定义“modelClass”参数的情况下布尔/stringMap.Entry:

 mAdapter = new FirebaseRecyclerViewAdapter<Map.Entry<String, Boolean>, ItemViewHolder>(???.class, R.layout.my_card, ItemViewHolder.class, getItemIndexQuery(mKey) ) { ... } 

你的值是一个Boolean ,而不是一个Map 。 所以你的评论是正确的:你需要为值types指定Boolean / Boolean.class 。 为了能够查找关键,您需要升级到FirebaseUI-Android 0.2.2。 在那个版本中,我们添加了一个populateViewHolder(VH, T, int)超载,它将项目的位置作为参数。 用这个,你可以查看该项目的关键。

说这是你的JSON结构:

 { "items": { "pushid1": "Fri Jan 01 2016 16:40:54 GMT-0800 (PST)", "pushid2": "Fri Jan 01 2016 16:41:07 GMT-0800 (PST)", "pushid3": "Fri Jan 01 2016 16:41:25 GMT-0800 (PST)", "pushid4": "Fri Jan 01 2016 16:41:37 GMT-0800 (PST)", "pushid5": "Fri Jan 01 2016 16:42:04 GMT-0800 (PST)" }, "index": { "pushid1": true, "pushid3": true, "pushid5": true } } 

所以我们存储代表date/时间的string,并有一个索引来select这些项目的一个子集。

现在我们可以从索引中加载节点,然后加载这些节点引用的项目,并在视图中显示它们:

 FirebaseRecyclerViewAdapter<Boolean, ItemViewHolder> adapter = new FirebaseRecyclerViewAdapter<Boolean, ItemViewHolder>( Boolean.class, android.R.layout.two_line_list_item, ItemViewHolder.class, ref.child("index")){ protected void populateViewHolder(final ItemViewHolder viewHolder, Boolean model, int position) { String key = this.getRef(position).getKey(); ref.child("items").child(key).addListenerForSingleValueEvent(new ValueEventListener() { public void onDataChange(DataSnapshot dataSnapshot) { String date = dataSnapshot.getValue(String.class); ((TextView)viewHolder.itemView.findViewById(android.R.id.text1)).setText(date); } public void onCancelled(FirebaseError firebaseError) { } }); } }; 

屏幕上的输出:

Android应用显示三个日期

有关完整的代码,请参阅本回购中的 Activity34559171

我面临同样的问题,最后我发现这个类: FirebaseIndexRecyclerAdapter这对我来说是完美的。

编辑4

我放弃了下面的代码,这是垃圾。 :(请不要使用它,我重写了Firebase-UI的数据库部分 ,请使用它。

编辑1,2和3

由于addListenerForSingleValueEvent意味着数据将是静态的(除非你改变了键的值),下面是我在不改变键值的情况下防止静态数据的方法:

创build一个事件监听器和持有者对象的列表:

 private Map<DatabaseReference, ValueEventListener> mValueEventListeners = new ArrayMap<>(); private List<TeamInfo> mTeamInfoList = new ArrayList<>(); 

FirebaseRecyclerAdapter

 RecyclerView recyclerView = (RecyclerView) findViewById(R.id.content_main_recycler_view); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(new LinearLayoutManager(this)); mRecyclerViewAdapter = new FirebaseRecyclerAdapter<Long, TeamHolder>( Long.class, R.layout.activity_main_row_layout, TeamHolder.class, Utils.getDatabase() .getReference() .child(Constants.FIREBASE_TEAM_INDEXES) .child(mUser.getUid()) .orderByValue()) { @Override public void populateViewHolder(final TeamHolder teamHolder, Long teamNumberDoNotUse, final int position) { DatabaseReference databaseReference = Utils.getDatabase() .getReference() .child(Constants.FIREBASE_TEAMS) .child(getRef(position).getKey()); if (!mValueEventListeners.containsKey(databaseReference)) { ValueEventListener valueEventListener = new ValueEventListener() { public void onDataChange(DataSnapshot dataSnapshot) { if (dataSnapshot.getValue() != null) { TeamInfo teamInfo = dataSnapshot.getValue(TeamInfo.class); if (position >= mTeamInfoList.size()) { String teamNumber = teamInfo.getNumber(); teamHolder.setTeamNumber(teamNumber); teamHolder.setTeamName(teamInfo.getName(), MainActivity.this.getString(R.string.no_name)); teamHolder.setTeamLogo(teamInfo.getMedia(), MainActivity.this); teamHolder.setListItemClickListener(teamNumber, MainActivity.this, dataSnapshot.getKey()); teamHolder.setCreateNewScoutListener(teamNumber, MainActivity.this, dataSnapshot.getKey()); mTeamInfoList.add(teamInfo); } else { mTeamInfoList.set(position, teamInfo); notifyItemChanged(position); } } else { // This should never happen since we are caching this offline FirebaseCrash.report(new IllegalStateException( "MainActivity RecyclerView event listener had null value (ref: " + dataSnapshot.getRef() + "pointed to non existent data)")); } } public void onCancelled(DatabaseError databaseError) { FirebaseCrash.report(databaseError.toException()); } }; databaseReference.addValueEventListener(valueEventListener); mValueEventListeners.put(databaseReference, valueEventListener); } else { String teamNumber = mTeamInfoList.get(position).getNumber(); teamHolder.setTeamNumber(teamNumber); teamHolder.setTeamName(mTeamInfoList.get(position).getName(), MainActivity.this.getString(R.string.no_name)); teamHolder.setTeamLogo(mTeamInfoList.get(position).getMedia(), MainActivity.this); teamHolder.setListItemClickListener(teamNumber, MainActivity.this, getRef(position).getKey()); teamHolder.setCreateNewScoutListener(teamNumber, MainActivity.this, getRef(position).getKey()); } } }; recyclerView.setAdapter(mRecyclerViewAdapter); 

在你的OnDestroy

 @Override protected void onDestroy() { super.onDestroy(); if (mRecyclerViewAdapter != null) { mRecyclerViewAdapter.cleanup(); } for (DatabaseReference databaseReference : mValueEventListeners.keySet()) { databaseReference.removeEventListener(mValueEventListeners.get(databaseReference)); } }