如何作为方法的结果返回 DocumentSnapShot?

Posted

技术标签:

【中文标题】如何作为方法的结果返回 DocumentSnapShot?【英文标题】:How to return a DocumentSnapShot as a result of a method? 【发布时间】:2021-05-06 10:13:33 【问题描述】:

采用 (DocumentSnapShot documentsnapShot) 参数的自定义对象。也是来自 Firebase 的内部对象,它检索快照并将值设置为我的自定义模型也有它的参数(DocumentSnapShot 文档napShot)。但是,我希望从 Firebase 获取数据并将其传递给我的自定义参数,因为我不仅需要 Firebase 还需要多个数据。如果没有覆盖,就无法迭代 Firestore。

代码如下:

public UserSettings getUserSettings(DocumentSnapshot documentSnapshot)
    Log.d(TAG, "getUserSettings: retrieving user account settings from firestore");

    DocumentReference mSettings = mFirebaseFirestore.collection("user_account_settings").document(userID);
    mSettings.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() 
        @Override
        public void onSuccess(DocumentSnapshot documentSnapshot) 
            UserAccountSettings settings = documentSnapshot.toObject(UserAccountSettings.class);
            settings.setDisplay_name(documentSnapshot.getString("display_name"));
            settings.setUsername(documentSnapshot.getString("username"));
            settings.setWebsite(documentSnapshot.getString("website"));
            settings.setProfile_photo(documentSnapshot.getString("profile_photo"));
            settings.setPosts(documentSnapshot.getLong("posts"));
            settings.setFollowers(documentSnapshot.getLong("followers"));
            settings.setFollowing(documentSnapshot.getLong("following"));
        
    );

【问题讨论】:

【参考方案1】:

您现在无法返回尚未加载的内容。 Firestore 加载数据asynchronously,因为这可能需要一些时间。根据您的连接速度和状态,可能需要几百毫秒到几秒钟才能获得该数据。如果您想将settings 对象传递给另一个方法,只需在onSuccess() 方法中调用该方法并将该对象作为参数传递。所以一个快速的解决方法是这样的:

@Override
public void onSuccess(DocumentSnapshot documentSnapshot) 
    UserAccountSettings settings = documentSnapshot.toObject(UserAccountSettings.class);
    yourMethod(settings);

还要提一提的是,您不需要将这些值设置为已经拥有它们的对象。您已经从数据库中获取数据作为对象。

所以请记住,onSuccess() 方法具有异步行为,这意味着它甚至在您从数据库中获取数据之前就已被调用。如果要在该方法之外使用settings 对象,则需要创建自己的callback。要实现这一点,首先你需要创建一个这样的接口:

public interface MyCallback 
    void onCallback(UserAccountSettings settings);

然后您需要创建一个实际从数据库中获取数据的方法。此方法应如下所示:

public void readData(MyCallback myCallback) 
    DocumentReference mSettings = mFirebaseFirestore.collection("user_account_settings").document(userID);
    mSettings.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() 
        @Override
        public void onSuccess(DocumentSnapshot documentSnapshot) 
            UserAccountSettings settings = documentSnapshot.toObject(UserAccountSettings.class);
            myCallback.onCallback(settings);

        
    );

最后只需简单地调用readData() 方法并将MyCallback 接口的实例作为参数传递到您需要的任何地方,如下所示:

readData(new MyCallback() 
    @Override
    public void onCallback(UserAccountSettings settings) 
        Log.d("TAG", settings.getDisplay_name());
    
);

这是您可以在onSuccess() 方法之外使用UserAccountSettings 类的对象的唯一方法。如需更多信息,您还可以查看此video

【讨论】:

您可以在界面中添加successfail,在失败或成功的情况下调用。【参考方案2】:

使用LiveData作为返回类型,观察其值的变化来执行所需的操作。

private MutableLiveData<UserAccountSettings> userSettingsMutableLiveData = new MutableLiveData<>();

public MutableLiveData<UserAccountSettings> getUserSettings(DocumentSnapshot documentSnapshot)

    DocumentReference mSettings = mFirebaseFirestore.collection("user_account_settings").document(userID);
    mSettings.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() 
        @Override
        public void onSuccess(DocumentSnapshot documentSnapshot) 
            UserAccountSettings settings = documentSnapshot.toObject(UserAccountSettings.class);
            settings.setDisplay_name(documentSnapshot.getString("display_name"));
            settings.setUsername(documentSnapshot.getString("username"));
            settings.setWebsite(documentSnapshot.getString("website"));
            settings.setProfile_photo(documentSnapshot.getString("profile_photo"));
            settings.setPosts(documentSnapshot.getLong("posts"));
            settings.setFollowers(documentSnapshot.getLong("followers"));
            settings.setFollowing(documentSnapshot.getLong("following"));

            userSettingsMutableLiveData.setValue(settings);
        
    );

    return userSettingsMutableLiveData;

然后从您的Activity/Fragment 观察LiveData 和内部onChanged 执行您想要的操作。

getUserSettings().observe(this, new Observer<UserAccountSettings>() 
    @Override
    public void onChanged(UserAccountSettings userAccountSettings) 
        //here, do whatever you want on `userAccountSettings`
    
);

【讨论】:

以上是关于如何作为方法的结果返回 DocumentSnapShot?的主要内容,如果未能解决你的问题,请参考以下文章

如何作为方法的结果返回 DataSnapshot 值?

如何作为方法的结果返回 DocumentSnapShot?

java方法通过啥关键字返回结果,如果方法没有返回值,则使用啥关键字作为?

如何定义 java 定义的存储过程以返回多个结果集?

如何在石墨烯中将函数作为查询结果返回?

如何在承诺中返回修改后的结果作为承诺