我在用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。
它返回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());
这是异步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");
}
运行此代码将打印以下序列:
在附加侦听器之前
附加侦听器后
有数据吗
这可能不是您所期望的,但准确地解释了为什么返回数组时它是空的。
大多数开发人员最初的反应是尝试“修复”这种异步行为。我建议不要这样做:网络是异步的,你越早接受这一点,你就能越早学会如何使用现代网络应用编程接口变得高效。
我发现为这个异步范例重新定义问题是最容易的。我没有说“先获取所有视频,然后记录它们”,而是将问题定义为“开始获取所有视频。加载视频后,记录它们”。
这意味着任何需要视频的代码都必须在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的开发人员来说,这是一个常见的问题。因此,关于这个话题已经有很多问题了,我建议你也去看看:
问题内容: 我正在编写一个非常简单的查询,但是由于某种原因,我得到了重复的值。 在返回重复值。即: 但是,直接在mysql中运行此查询 不返回重复值。 谁能发现哪里出了问题? 问题答案: 快速的解决方法是使用“不同的根实体结果转换器”。 但这只是一个工作环境。 我怀疑问题属于您的映射。如果从ProcessInstance到其他对象之间急切地加载了1:n关系(称为X),并且一个ProcessInst
我创建了一个简单的REST服务(POST)。但是当我从postman@RequestBody调用这个服务时,它没有收到任何值。 我的java Bean对象如下: System.out.println将null打印为PolcyNumber的值。 请帮我解决这个问题。 我在请求体中传递的JSON是 我甚至在postman中设置了到
我想让对话框片段(DialogFragment)向我返回一个值,该值是在退出时在编辑数量(editQuantity)中输入的。 但我没有办法让它发挥作用。我可以通过将值传递给intent来实现这一点,但这会破坏当前活动的进度。 除了传递意图之外,还有什么方法可以返回我的值吗?
我已经使用API从API中提取了JSON响应,请放心,它看起来像这样: 现在,我实际的JSON响应在JSON数组中有数千个JSON对象,一些键有空值,例如“secondKey”在一些JSON对象中有空值。我需要获取JSON响应中所有空值的键。对我该如何做有什么想法吗? 我解决这个问题的想法是使用Jackson库反序列化JSON并获取所有空值。然而,考虑到性能,是否有任何有效的解决方案?
我到处寻找,并尽一切努力从SQLQueriesRadion按钮获取选定的mySQL值。 这是我的密码 谢啦
问题内容: 我有以下数组: 结果: 现在如何显示具有重复值的键?在此函数不应返回([0],[9]),因为没有重复的值。 如何找到相同值的键,例如 对于“ 2011-06-25”,应返回[7],[8] 问题答案: 函数名称显然很长;) 现在$ dups将包含一个由重复值键控的多维数组,其中包含每个重复项的键,如果您将“ true”作为第二个参数发送,它将返回没有重复值的原始数组。 或者,您可以将原始