【问题标题】:FirebaseRecyclerAdapter with empty view具有空视图的 FirebaseRecyclerAdapter
【发布时间】:2016-12-27 17:03:18
【问题描述】:

我知道有很多方法可以为 RecyclerView 设置一个空视图。但我的问题是针对 FirebaseRecyclerView。

我的布局是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/feed_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

<ProgressBar
    android:id="@+id/feed_loading"
    style="?android:attr/progressBarStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:visibility="gone"/>
</RelativeLayout>

所以我在 RecyclerView 填充其项目之前显示 Loading ProgressBar。现在如果服务器没有任何项目怎么办。在这种情况下,我的 RecyclerView 始终为空,我的 Loading ProgressBar 始终对用户可见。

因此,我不想显示无限期的 ProgressBar,而是显示一些空布局。例如。 “未找到数据”或类似消息。

最终结果应该是:ProgressBar 应该在数据加载到 RecyclerView 之前一直显示,并且一旦数据加载,ProgressBar 应该是不可见的。但如果服务器中没有数据,则应该显示一些空布局而不是 ProgressBar。

在普通的 RecyclerView 中,我们有一个数据集(一些 ArrayList 等),如果它是空的,那么我们可以显示该空布局。但在 FirebaseRecyclerAdapter 的情况下,我的 Activity 或 Context 中没有 Snapshot 的引用。我也没有任何回调告诉我服务器中没有数据。

任何解决方法都会有很大帮助。

【问题讨论】:

    标签: android firebase android-recyclerview firebase-realtime-database firebaseui


    【解决方案1】:

    这是我会尝试的。首先查看下面链接的问题的公认答案。它提供了一些关于 Firebase 查询如何工作的非常好的见解。我认为该信息是可信的,因为答案是由 Firebase 团队中的某个人提供的:

    How to separate initial data load from incremental children with Firebase?

    因此,根据上面链接的问题的答案以及FirebaseRecyclerAdapter 由使用ChildEventListener 填充的FirebaseArray 支持的事实,我将在同一数据库引用上添加一个单值事件侦听器用于填充您的FirebaseRecyclerAdapter。像这样的:

    //create database reference that will be used for both the
    //FirebaseRecyclerAdapter and the single value event listener
    dbRef = FirebaseDatabase.getInstance().getReference();
    
    //setup FirebaseRecyclerAdapter
    mAdapter = new FirebaseRecyclerAdapter<Model, YourViewHolder>(
                    Model.class, R.layout.your_layout, YourViewHolder.class, dbRef) {
    
                    @Override
                    public void populateViewHolder(YourViewHolder holder, Model model, int position){
    
                         //your code for populating each recycler view item
    
                    };
    
    mRecyclerView.setAdapter(mAdapter);
    
    //add the listener for the single value event that will function
    //like a completion listener for initial data load of the FirebaseRecyclerAdapter
    dbRef.addListenerForSingleValueEvent(new ValueEventListener() {
                 @Override
                 public void onDataChange(DataSnapshot dataSnapshot) {
                     //onDataChange called so remove progress bar
    
                     //make a call to dataSnapshot.hasChildren() and based 
                     //on returned value show/hide empty view 
    
                     //use helper method to add an Observer to RecyclerView    
                 }
    
                 @Override
                 public void onCancelled(DatabaseError databaseError) {
    
                 }
          });
    

    这将处理 RecyclerView 的初始设置。当在单值事件侦听器上调用 onDataChange 时,使用辅助方法将观察者添加到 FirebaseRecyclerAdapter 以处理对数据库位置的任何后续添加/删除。

    mObserver = new RecyclerView.AdapterDataObserver() {
                @Override
                public void onItemRangeInserted(int positionStart, int itemCount) {
                    //perform check and show/hide empty view
                }
    
                @Override
                public void onItemRangeRemoved(int positionStart, int itemCount) {
                    //perform check and show/hide empty view
                }
               };
    mAdapter.registerAdapterDataObserver(mObserver);
    

    【讨论】:

    • 感谢您的解决方案,这是一个很棒的技巧,对我有用。
    • 没问题。很高兴能提供帮助。
    • 我似乎无法检查 onItemRangeRemoved() 是否导致空列表。 AdapterDataObserver 和只调用 dbRef.addValueEventListener() 有什么区别?
    • @JustinLiu - 请记住,根据设计,SingleValueEvent 侦听器只会触发一次,之后将不再被调用。因此 ValueEventListener 将仅用于 FirebaseRecyclerAdapter 的初始设置,以查看它是否有任何项目。现在,假设初始设置已完成,并且当最后一个项目突然从 RecyclerView 中移除时用户仍在查看屏幕,您需要一种对此做出反应的方法,否则用户只会看到一个空白屏幕。这就是 DataObserver 的用途 - 在初始设置后对任何数据集更改做出反应。
    • @JustinLiu - onItemRangeRemoved 将在任何时候从 RecyclerAdapter 中删除项目时调用,因此您可以执行诸如调用 mAdapter.getItemCount() 之类的操作....如果它为 0,则显示为空查看。
    【解决方案2】:

    答案来自:https://stackoverflow.com/a/40204298/2170278

    现在的 FirebaseUI 适配器有一个 onDataChanged() 方法,您可以覆盖该方法以检测它们何时完成加载一组数据。

    请参阅source code on github。从那里:

    每次从数据库中完成更新时都会触发此方法。所以第一次调用这个方法时,已经加载了初始数据——包括根本没有数据可用的情况。每次下次调用该方法时,都会完成一次完整的更新(可能包括对多个子项的更新)。

    您通常会重写此方法以隐藏加载指示器(在初始加载之后)或完成对 UI 元素的批量更新。

    FirebaseUI 示例应用会覆盖 onDataChanged() 以隐藏其“加载”指示器:

    public void onDataChanged() {
        // If there are no chat messages, show a view that invites the user to add a message.
        mEmptyListMessage.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-16
      • 2018-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多