从firebase提取数据并将其返回到主线程

问题描述 投票:0回答:3

当前遇到一个问题,我正在从Firebase提取数据。我知道这是因为Firebase是异步的,所以当我进行firebase调用时,它是在自己的线程上执行的,被调用的当前线程会继续执行。我用Firebase中的数据填充对象列表,然后返回该对象列表。问题是,列表始终返回null,因为Firebase代码的执行未及时完成。

我创建了一些从sqlite db获取的异步代码,效果很好,但是这种方法似乎不适用于firebase(我相信这是由于firebases API是异步的),这是我从firebase返回对象列表的方法。

/** Method to get activity data from firebase.
 * @param userInput the user query to select the data
 * @return a list of activity models based on the query
 * */
public List<ActivityModel> retrieveActivityData(String userInput) {
    Log.d(TAG, "retrieveActivityData: starts");
    List<ActivityModel> models = new ArrayList<ActivityModel>();
    // execute the query in firebase
    CollectionReference activfitCollection = db.collection("activity");
    activfitCollection.orderBy("isoTimestamp")
            .startAt(userInput)
            .endAt(DateHelper.getDayEndingDate(userInput))
            .get()
            .addOnCompleteListener(task -> {
                if (task.isSuccessful()) {
                    Log.d(TAG, "onComplete: Getting data successful!");
                    // check to see if it exists
                    if (!task.getResult().isEmpty()) {
                        for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
                            Log.d(TAG, "retrieveActivityData: document = " + documentSnapshot.getId());
                            // cast the document to the activity model
                            Log.d(TAG, "retrieveActivityData: document data " + documentSnapshot.getData());
                            ActivityModel model = mapToActivityModel(documentSnapshot);
                            models.add(model);
                            Log.d(TAG, "retrieveActivityData: array size" + models.size());
                        }
                    }

                } else {
                    Log.e(TAG, "onComplete: Error getting documents: ", task.getException());
                }
            });
    Log.d(TAG, "retrieveActivityData: array size outside " + models.size());
    return models;
}
java android firebase
3个回答
1
投票

由于数据是异步加载的,因此您不能返回数据,您应该在retrieveActivityData方法中传递callback(Interface),并使用接口的回调来加载数据,请检查下面的代码

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        MyFirebaseCallback myFirebaseCallback = new MyFirebaseCallback() {
            @Override
            public void dataLoaded(List<ActivityModel> activityModels) {
                //set the data in recycler view
            }
        };

        retrieveActivityData("myInput",myFirebaseCallback);
    }

    public void retrieveActivityData(String userInput, final MyFirebaseCallback callback) {
        Log.d(TAG, "retrieveActivityData: starts");
        // execute the query in firebase
        CollectionReference activfitCollection = db.collection("activity");
        activfitCollection.orderBy("isoTimestamp")
                .startAt(userInput)
                .endAt(DateHelper.getDayEndingDate(userInput))
                .get()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful()) {
                        List<ActivityModel> models = new ArrayList<ActivityModel>();
                        Log.d(TAG, "onComplete: Getting data successful!");
                        // check to see if it exists
                        if (!task.getResult().isEmpty()) {
                            for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
                                Log.d(TAG, "retrieveActivityData: document = " + documentSnapshot.getId());
                                // cast the document to the activity model
                                Log.d(TAG, "retrieveActivityData: document data " + documentSnapshot.getData());
                                ActivityModel model = mapToActivityModel(documentSnapshot);
                                models.add(model);
                                Log.d(TAG, "retrieveActivityData: array size" + models.size());
                            }
                        }

                        callback.dataLoaded(models);

                    } else {
                        Log.e(TAG, "onComplete: Error getting documents: ", task.getException());
                    }
                });
        Log.d(TAG, "retrieveActivityData: array size outside " + models.size());
    }

    interface MyFirebaseCallback{
        void dataLoaded(List<ActivityModel> activityModels);
    }

1
投票

Option-1:可以使用LiveData来实现。操作完成后,将值发布到LiveData,并观察您的活动或片段内部的值]

MutableLiveData<List<ActivityModel>> listMutableLiveData = new MutableLiveData<>();

public MutableLiveData<List<ActivityModel>> retrieveActivityData(String userInput) {

    List<ActivityModel> models = new ArrayList<ActivityModel>();

    ....
        if (task.isSuccessful()) {
            for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
                ....
                models.add(model);
            }

            //Post value to live data from here
            listMutableLiveData.postValue(models);
        }

    ....

    return listMutableLiveData;
}

然后是observe这样

retrieveActivityData(userInput).observe(this, new Observer<List<ActivityModel>>() {
    @Override
    public void onChanged(List<ActivityModel> activityModels) {
        //you can use list here
    }
});

Option-2:

您可以在Firebase操作完成后使用回调函数获取结果。
  • 为回调创建interface
interface FirebaseResultListener {
    void onComplete(List<ActivityModel> activityModels);
}
  • 配置您的retrieveActivityData以处理此回调
public void retrieveActivityData(String userInput, FirebaseResultListener callback) {

    List<ActivityModel> models = new ArrayList<ActivityModel>();

    ....
    if (task.isSuccessful()) {
        for (DocumentSnapshot documentSnapshot : task.getResult().getDocuments()) {
                ....
            models.add(model);
        }

        //Invoke callback with result from here
        callback.onComplete(models);
    }

    ....
}
  • 在您的活动或片段中实现此界面
retrieveActivityData(userInput, new FirebaseResultListener() {
    @Override
    public void onComplete(List<ActivityModel> activityModels) {
        //you can use list here
    }
});

0
投票

您猜对了!该查询是异步的,因此retrieveActivityData()不应返回List<ActivityModel>,否则它将始终为null。一旦将List编译到onComplete()中,您就必须使用事件总线来触发事件,或者使用LiveData进行观察。

© www.soinside.com 2019 - 2024. All rights reserved.