我正在使用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.
解决方法:
这是异步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");
}
运行此代码将打印以下序列:
Before attaching listener
After attaching listener
Got data
这可能不是您所期望的,但是当您返回数组时,它正好解释了为什么数组为空.
大多数开发人员的初始响应是尝试“修复”这种异步行为.我建议不要这样做:网络是异步的,越早接受,您就越早了解如何通过现代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的开发人员来说,这是一个常见问题.因此,已经有很多关于这个主题的问题,我建议你也检查一下:
> Setting Singleton property value in Firebase Listener
> Handle data returned by an Async task (Firebase)(显示如何定义和传递您自己的回调)
> Firebase – Android – fetchProvidersForEmail – Why are all the calls asynchronous?(有更多其他类似问题的链接)