Firebase首次查询返回空数组、后续查询正常的问题如何解决
问题根因
你遇到的首次调用返回空数组是异步调用时序问题导致的:
- Firebase Firestore的
get()方法属于异步网络请求,调用后不会立刻阻塞等待结果返回,而是会先继续执行后续代码 - 你在
firebaseEnquiry方法末尾直接同步返回myListJobs时,Applications集合的查询请求、后续fetchAllJobs里的Jobs集合查询请求都还没有执行完成,此时myListJobs还没被赋值,所以返回空数组 - 第二次调用时,前一次的异步请求已经执行完毕,
myListJobs已经被填充了数据,所以能拿到正确结果
现有代码潜在问题
- 静态全局
myListJobs会出现数据错乱:如果多次调用firebaseEnquiry传入不同status,异步结果返回顺序不可控,会导致返回的列表和传入的status不匹配 - 没有处理查询无数据的回调场景,调用方无法感知请求完成状态
解决方案:使用回调接口传递异步结果
不要用同步返回列表的方式,改成通过回调接口把查询完成后的结果回传给调用方,步骤如下:
- 首先定义结果回调接口
public interface OnJobQueryListener { void onQuerySuccess(ArrayList<Job> jobList); void onQueryFail(Exception e); }
- 修改工具类代码,移除静态全局
myListJobs,改用局部变量存储结果,请求完成后通过回调返回
public class K { private static final String TAG = "ListingJob"; private static FirebaseFirestore mFirebaseFirestore = FirebaseFirestore.getInstance(); public static void firebaseEnquiry(Context context, String status, OnJobQueryListener listener) { ArrayList<Applications> listApplications = new ArrayList<>(); String uid = FirebaseAuth.getInstance().getCurrentUser().getUid(); mFirebaseFirestore.collection("Applications") .whereEqualTo("status", status) .whereEqualTo("User_id", uid) .get() .addOnCompleteListener(task -> { if (task.isSuccessful()) { for (QueryDocumentSnapshot document : task.getResult()) { Applications applications = document.toObject(Applications.class); listApplications.add(applications); } if (listApplications.size() > 0) { fetchAllJobs(listApplications, listener); } else { // 无匹配的Applications,直接返回空列表 listener.onQuerySuccess(new ArrayList<>()); } } else { listener.onQueryFail(task.getException()); } }) .addOnFailureListener(e -> { Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show(); listener.onQueryFail(e); }); } private static void fetchAllJobs(ArrayList<Applications> listApplications, OnJobQueryListener listener) { ArrayList<Job> myListJobs = new ArrayList<>(); mFirebaseFirestore.collection("Jobs") .get() .addOnCompleteListener(task -> { if (task.isSuccessful()) { for (QueryDocumentSnapshot document : task.getResult()) { for (int i = 0; i < listApplications.size(); i++) { String jobId = document.getId().trim(); if (listApplications.get(i).getJob_id().trim().equals(jobId)) { Job job = document.toObject(Job.class); myListJobs.add(job); } } } listener.onQuerySuccess(myListJobs); } else { listener.onQueryFail(task.getException()); } }); } }
- 调用方使用示例
K.firebaseEnquiry(context, "你的status参数", new OnJobQueryListener() { @Override public void onQuerySuccess(ArrayList<Job> jobList) { // 这里拿到查询结果,更新UI或者后续处理 } @Override public void onQueryFail(Exception e) { // 处理错误场景 Log.d(TAG, "查询失败: ", e); } });
内容的提问来源于stack exchange,提问作者Imran Khan
相关产品推荐
相关产品推荐

