当前位置: 首页 > 知识库问答 >
问题:

Android Firebase越来越空

蒯胜泫
2023-03-14

我正在使用Firebase来保存我的数据。我试图在活动中分离Firebase方法和我的方法。例如,我已经创建了一个名为"Firebase method odsHelper"的类,在那里我想编写所有的Firebase方法。例如,"getAllUser"方法应返回列表中的所有用户。我唯一的问题是它不起作用。

我不知道我做错了什么,所以如果你们能帮我。

碎片

  public class MyPlayListFragment extends Fragment {
    private FirebaseDatabase refToVideos;
    private FirebaseUser currentUser;
    private ArrayList<Video> videosList;
    private VideoViewAdapter adapter;
    private RecyclerView rvVideos;
    private List<Video> checkList;


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


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_my_play_list, container, false);
    rvVideos = (RecyclerView)v.findViewById(R.id.rvVideos);

    return v;
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    videosList = new ArrayList<>();
    refToVideos = FirebaseDatabase.getInstance();
    currentUser = FirebaseAuth.getInstance().getCurrentUser();

    FirebaseMethodsHelper fmh = new FirebaseMethodsHelper();


    checkList = fmh.getAllVideosFromDB(currentUser);
    if(checkList != null)
    Log.d("checkList",checkList.toString());

FirebaseMethodHelper类

   public class FirebaseMethodsHelper {
private FirebaseDatabase databaseRef;
private ArrayList<User> usersList;
private ArrayList<Video> videosList;



   public List<Video> getAllVideosFromDB(FirebaseUser currentUser){
        databaseRef = FirebaseDatabase.getInstance();
        databaseRef.getReference(Params.VIDEOS).child(currentUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                    videosList.add(snapshot.getValue(Video.class));
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });


    return videosList;
  }
 }

我不知道为什么,但它总是返回空值。

共有2个答案

班泽语
2023-03-14

它返回null,因为列表videosList尚未初始化。另外,在方法中返回列表的方法是错误的。firebase调用是异步的,因此您无法控制数据何时可用,因此几乎每次您的方法都会返回null(如果列表尚未初始化)或空列表(如果已初始化)。

解决方案是使用接口回调,这将根据需要将视频列表返回到片段:

public interface FirebaseCallback {
    void listVideos(ArrayList<Video> videos);
}

此方法将从您的Firebase MEDHelper类中调用:

public void getAllVideosFromDB(FirebaseUser currentUser, FirebaseCallback callback){
    databaseRef = FirebaseDatabase.getInstance();
    databaseRef.getReference(Params.VIDEOS).child(currentUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            ArrayList<Video> videosList = new ArrayList<>();

            for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                videosList.add(snapshot.getValue(Video.class));
            }

            callback.listVideos(videosList);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });  
}

从片段中,您实现了接口,并将此代码传递给方法,如下所示:

public class MyPlayListFragment extends Fragment implements FirebaseCallback  {
    private FirebaseDatabase refToVideos;
    private FirebaseUser currentUser;
    private ArrayList<Video> videosList;
    private VideoViewAdapter adapter;
    private RecyclerView rvVideos;
    private List<Video> checkList;


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


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_my_play_list, container, false);
    rvVideos = (RecyclerView)v.findViewById(R.id.rvVideos);

    return v;
}
@Override
public void listVideos(ArrayList<Video> videos) {
    //do what you want with the videos
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    videosList = new ArrayList<>();
    refToVideos = FirebaseDatabase.getInstance();
    currentUser = FirebaseAuth.getInstance().getCurrentUser();

    FirebaseMethodsHelper fmh = new FirebaseMethodsHelper();


    checkList = fmh.getAllVideosFromDB(currentUser, this);
    if(checkList != null)
    Log.d("checkList",checkList.toString());
苏丰茂
2023-03-14

这是异步web API的一个典型问题:现在无法返回尚未加载的内容。

Firebase数据库(和大多数现代web API)数据是异步加载的,因为这可能需要一些时间。当数据加载到辅助线程时,主应用程序代码将继续运行,而不是等待数据(这将导致应用程序不响应用户的对话框)。然后,当数据可用时,将调用onDataChange()方法并可以使用数据。

这将更改应用程序的流程。查看这一点的最简单方法是放置一些日志语句:

public List<Video> getAllVideosFromDB(FirebaseUser currentUser){
    databaseRef = FirebaseDatabase.getInstance();
    System.out.println("Before attaching listener");
    databaseRef.getReference(Params.VIDEOS).child(currentUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            System.out.println("Got data");
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            throw databaseError.toException(); // don't ignore errors
        }
    });
    System.out.println("After attaching listener");
}

运行此代码将打印以下序列:

在附加侦听器之前

附加侦听器后

得到数据

这可能不是您所期望的,但准确地解释了返回数组时数组为空的原因。

大多数开发人员的初始响应是尝试并“修复”这种异步行为。我建议您不要这样做:web是异步的,您越早接受这一点,就越早学会如何使用现代web API提高效率。

我发现为这个异步范例重新构造问题是最容易的。我没有说“先获取所有视频,然后记录它们”,而是将问题定义为“开始获取所有视频。加载视频后,记录它们”。

这意味着任何需要视频的代码都必须位于onDataChange()(或从内部调用)内部。例如。:

public List<Video> getAllVideosFromDB(FirebaseUser currentUser){
    databaseRef = FirebaseDatabase.getInstance();
    databaseRef.getReference(Params.VIDEOS).child(currentUser.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                videosList.add(snapshot.getValue(Video.class));
            }
            if (videosList != null) {
                Log.d("checkList",videosList.toString());
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            throw databaseError.toException(); // don't ignore errors
        }
    });

}

正如我所说,对于以前没有处理过异步API的开发人员来说,这是一个常见的问题。因此,关于这个话题已经有很多问题了,我建议你也去看看:

  • 在Firebase侦听器中设置单例属性值
 类似资料:
  • 我有一个Spring启动,Hibernate使用java应用程序。我部署它在一个jetty webserver与多个实例.如果我有太多(大于10)很多实例我得到 许多连接(10x实例)显示为空闲 ps: 实例的Hikari跟踪日志: 设置 没有记录任何有趣的事情。我认为这看起来很有趣-连接不可用 有什么办法可以调试这个吗?我也在java 7上,所以hikari 2.4.7

  • 前面提到多进程的并行可以提高并发度,那么进程是越多越好?一般遇到这种问题都回答不是,事实上,很多大型项目都不会同时开太多进程。 下面以支持100K并发量的Nginx服务器为例。 举个例子: Nginx Nginx是一个高性能、高并发的Web服务器,也就是说它可以同时处理超过10万个HTTP请求,而它建议的启动的进程数不要超过CPU个数,为什么呢? 我们首先要知道Nginx是Master-worke

  • 本文向大家介绍jquery代码规范让代码越来越好看,包括了jquery代码规范让代码越来越好看的使用技巧和注意事项,需要的朋友参考一下 最近学了jQuery,感觉这个jQuery是真的挺不错的,果然像他说的那样,少些多做!刚一入手感觉真是不错。但是写多了,就会发现这个代码一行居然能写那么长。而且可读性还不好。  有幸自己买了一本锋利的jQuery这本书。我就整理了下。到底在实际应用中怎么让自己的j

  • 问题内容: 我正在使用TensorFlow训练用于医学图像应用的CNN。 由于我没有大量数据,因此我尝试在训练循环中对训练批次进行随机修改,以人为地增加训练数据集。我用其他脚本编写了以下函数,并在我的培训批次中调用它: 该代码很好地适用于对我的图像进行修改。 问题是 : 在我的训练循环的每个迭代(前馈+反向传播)之后,将相同的功能稳定地应用到我的下一个训练批次中,将比上一次稳定地花费5秒。 处理大

  • 问题内容: 主管的指示:“我要避免在其中添加任何逻辑models.py。从现在开始,让我们将其用作访问数据库的类,并将所有逻辑保留在使用模型类或包装它们的外部类中。” 我觉得这是错误的方法。我觉得将逻辑排除在模型之外只是为了减小文件大小是一个坏主意。如果逻辑在模型中是最好的,那么无论文件大小如何,它实际上都是应该去的地方。 那么有没有一种简单的方法可以只使用include?用PHP讲,我想向主管建

  • 我是android开发的新手,我的应用程序在调用特定活动时会崩溃。(“governanaceactivity”是活动的名称)当我从MainActivity调用治理活动时,我的应用程序会崩溃,其他菜单工作得很好,唯一的问题是这个活动。 这是GovernanceActivity **所有其他活动都很好,只有这个活动有问题 这是我的宣言** Blockquote 05-21 03:09:53.747 1