Android firebase 为空 [重复]
Posted
技术标签:
【中文标题】Android firebase 为空 [重复]【英文标题】:Android firebase getting null [duplicate] 【发布时间】:2018-05-23 14:53:09 【问题描述】:我正在使用 Firebase 来保存我的数据。我正在尝试将 Firebase 方法和我的活动方法分开。例如,我创建了名为“FirebaseMethodsHelper”的类,我想在那里编写所有 Firebase 方法。 例如,应该在列表中返回所有用户的“getAllUsers”方法。 我唯一的问题是它不起作用。
我不知道我做错了什么,所以如果你们能帮助我。
片段
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。
【问题讨论】:
【参考方案1】:这是异步 Web API 的一个经典问题:您无法返回尚未加载的内容现在。
Firebase 数据库(以及大多数现代网络 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");
运行此代码将打印以下序列:
附加监听器之前
附加监听器后
得到数据
这可能不是你所期望的,但准确地解释了为什么当你返回它时数组是空的。
大多数开发人员的最初反应是尝试“修复”这种异步行为。我不建议这样做:网络是异步的,您越早接受这一点,您就能越早学习如何使用现代网络 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 的开发人员来说,这是一个常见的问题。因此,关于这个话题已经有很多问题了,我建议你也去看看:
Setting Singleton property value in Firebase Listener Handle data returned by an Async task (Firebase)(展示如何定义和传入你自己的回调) Firebase - android - fetchProvidersForEmail - Why are all the calls asynchronous?(还有很多其他类似问题的链接)【讨论】:
感谢您的回答和您的时间。我会检查这些链接!【参考方案2】:它返回 null 因为列表 videosList
尚未初始化。此外,您在方法中返回列表的方法是错误的。 firebase 调用是异步的,因此您无法控制数据何时可用,因此几乎每次您的方法都会返回 null(如果列表尚未初始化)或空列表(以防您初始化它)。
一种解决方案是使用接口回调,这将根据需要将视频列表返回到您的片段:
public interface FirebaseCallback
void listVideos(ArrayList<Video> videos);
此方法将从您的 FirebaseMethodHelper
类中调用:
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)
);
从您的片段中,您实现接口并将this
传递给方法,如下所示:
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());
【讨论】:
以上是关于Android firebase 为空 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
Firebase Android - 如何随机获取一些项目[重复]
Android Studio中的Firebase android jars文档/javadoc [重复]