如何通过FirebaseFirestore查询从类中的方法检索数据列表?

时间:2019-09-25 11:37:35

标签: android firebase google-cloud-firestore

我有一个Firebase数据库。 我想创建一个查询并将其放在DBUtils类的方法中,以便可以从Android项目中的不同活动中调用该查询。

例如,类似:

ArrayList<String> aStringArrayList = DBUtils.GetAllJobsOnADate(Date date);
.
.
.
// use aStringArrayList to populate a listview.

AND

 public  static ArrayList<String> GetJobsOnADate(Date date) {
                final ArrayList<String> mReturnList = new ArrayList<String>();
                FirebaseFirestore db = FirebaseFirestore.getInstance();
                db.collection("jobs")
                        .whereEqualTo("job_date", date)
                        .get()
                        .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                            @Override
                            public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                                for (QueryDocumentSnapshot queryDocumentSnapshot : queryDocumentSnapshots) {
                                     mReturnList.add(queryDocumentSnapshot.get("job_title"));
                                                                                                                }
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // failure code 
                            }
                        });
                return mReturnList;
            }

在调试应用程序时,我可以看到get()确实返回了QuerySnapshotDocument列表(可以在onSuccessListner代码中看到断点),但是aStringArray始终为空。

尝试使用AsyncTask(onPostExecute)。也不起作用。

当然,如果代码在同一活动中的函数中,则可以正常工作。但这就是散布在许多活动中的大量冗余代码。

有什么主意吗?

2 个答案:

答案 0 :(得分:0)

唯一的原因是因为您实际上正在返回一个空列表,该方法是同步的,并且对服务器的Firebase调用是异步的,因此在return mReturnList;之前调用mReturnList.add(queryDocumentSnapshot.get("job_title"));

由于我已经很长时间没有编写Java了,所以我建议您使用Kotlin的一些方法来实现。我将尝试使其类似于Java语法。

因此,为此,您应该使用接口与该类进行通信。

您的界面应如下所示:

interface Callback {
   fun onListLoaded(list : ArrayList<String>)
}

然后在您的班级中需要该列表的人应该实现该接口:

class MyActivity() : Activity(), Callback /*<- your interface*/ {
  ...
  //You implement the method which is signed in your interface.
  override fun onListLoaded(list : ArrayList<String>) {
    //here you can use the list
    list.forEach { ... }
  }

}

然后,您应将实现Callback接口的活动实例传递给与Firebase通信的类:

class FirebaseInteractor() {

    private var listener: Callback? = null //instance of your interface

    fun setListener(listener : Callback) {
        this.listener = listener
    }  

    fun getJobsOnADate(Date date) {
        ...
    }
}

然后,当您加载数据时,在onSuccessListener中以这种方式调用界面:

fun getJobsOnADate(Date date) {
            val db = FirebaseFirestore.getInstance()
            db.collection("jobs")
                    .whereEqualTo("job_date", date)
                    .get()
                    .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                        @Override
                        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                            val list : ArrayList<String> = ArrayList()
                            for (queryDocumentSnapshot in queryDocumentSnapshots) {
                                 list .add(queryDocumentSnapshot.get("job_title"))                                                                        
                            }

                            //Here goes the magic:
                            listener.onListLoaded(list)
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // failure code 
                        }
                    })
        }

这是您设置活动的方式,该活动将Callback接口实现为侦听器(在活动内部):

val firebaseInteractor = FirebaseInterractor()
firebaseInterractor.setListener(this)
firebaseInterractor.getJobsOnADate(date)

调用firebase的onSuccessListener并解析所有数据时,您的活动中的onListLoaded将被交互者发送的列表调用。

答案 1 :(得分:0)

这是上述答案的Java实现。

static GetJobsOnADate(Date date, MyCallbackInterface callback) {
            final ArrayList<String> mReturnList = new ArrayList<String>();
            FirebaseFirestore db = FirebaseFirestore.getInstance();
            db.collection("jobs")
                    .whereEqualTo("job_date", date)
                    .get()
                    .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                        @Override
                        public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                            for (QueryDocumentSnapshot queryDocumentSnapshot : queryDocumentSnapshots) {
                                 mReturnList.add(queryDocumentSnapshot.get("job_title"));
                                }
                            callback.OnDataReceived(mReturnList);
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // failure code 
                        }
                    });

        }

和回调接口:

interface MyCallbackInterface{
    void onDataReceived(ArrayList<String> data);

}