Android Firebase 获取空值 [英] Android firebase getting null

查看:18
本文介绍了Android Firebase 获取空值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Firebase 来保存我的数据.我正在尝试将 Firebase 方法和我的活动方法分开.例如,我创建了名为FirebaseMethodsHelper"的类,我想在那里编写所有 Firebase 方法.例如,getAllUsers"方法应该返回列表中的所有用户.我唯一的问题是它不起作用.

I'm using Firebase to save my data. I'm trying to separate Firebase methods and my methods on the activity. For example i have created class that called "FirebaseMethodsHelper" and there i want to write all the Firebase methods. For example, "getAllUsers" method that should return in list all the users. The only problem i have that it does not working.

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

I dont know what im doing wrong, so if you guys please can help me.

片段

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

我不知道为什么,但它总是返回 null.

I dont know why, but it always return null.

推荐答案

这是异步 Web API 的一个经典问题:你不能返回现在尚未加载的东西.

This is a classic problem with asynchronous web APIs: you cannot return something now that hasn't been loaded yet.

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

Firebase Database (and most modern web APIs) data is loaded asynchronously, since it may take some time. Instead of waiting for the data (which would lead to Application Not Responding dialogs for your users), your main application code continues while the data is loaded on a secondary thread. Then when the data is available, your onDataChange() method is called and can use the data.

这会改变您应用的流程.看到这一点的最简单方法是放置一些日志语句:

This changes the flow of your app. The easiest way to see this is by placing a few log statements:

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

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

Running this code will print the following sequence:

附加监听器之前

附加监听器后

获得数据

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

This is probably not what you expected, but explains precisely why the array is empty when you return it.

大多数开发人员的最初反应是尝试修复"这种异步行为.我不建议这样做:网络是异步的,你越早接受这一点,你就能越早学会如何使用现代网络 API 提高工作效率.

The initial response for most developers is to try and "fix" this asynchronous behavior. I recommend against that: the web is asynchronous, and the sooner you accept that, the sooner you can learn how to become productive with modern web APIs.

我发现为这种异步范式重构问题最容易.我没有说首先获取所有视频,然后记录它们",而是将问题定义为开始获取所有视频.加载视频后,记录它们".

I've found it easiest to reframe problems for this asynchronous paradigm. Instead of saying "First get all videos, then log them", I frame the problem as "Start getting all videos. When the videos are loaded, log them".

这意味着任何需要视频的代码都必须在 onDataChange() 内(或从那里调用).例如:

This means that any code that requires the video must be inside onDataChange() (or called from inside there). E.g.:

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 的开发人员来说,这是一个常见问题.因此,已经有很多关于该主题的问题,我建议您也查看一下:

As I said, this is a common problem for developers who haven't dealt with asynchronous APIs before. As such, there have been quite some questions on the topic already, and I recommend you check them out too:

  • Setting Singleton property value in Firebase Listener
  • Handle data returned by an Async task (Firebase) (showing how to define and pass in your own callback)
  • Firebase - Android - fetchProvidersForEmail - Why are all the calls asynchronous? (with lots more links to other similar questions)

这篇关于Android Firebase 获取空值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆