Android读取Firestore时的封装错误。

huangapple go评论107阅读模式
英文:

Android encapsulation bug while reading in Firestore

问题

I have set up a getter method in my ViewModel to get a Long-type field called cWeek. When I use the value.getLong inside the addSnapshotListener, it works and returns the value from the db but when I try to return it, the variable is null. I seriously have no idea what to search for to resolve this problem.

Getter

// this var is initialized in global scope
Long cWeek = getCWeek();

public Long getCWeek() {
        new References()
                .getUserRefDoc()
                .addSnapshotListener(new EventListener<DocumentSnapshot>() {
                    @Override
                    public void onEvent(@Nullable DocumentSnapshot value, @Nullable FirebaseFirestoreException e) {
                        if (e != null) {
                            Log.d(TAG, "Could not get cWeek data " + e);
                        }
                        Long var = (Long) value.get("cWeek");

                        cWeek = var;
                        Log.d(TAG, "cWeek: " + cWeek);
                    }
                });
        Log.d(TAG, "cWeek AFTER: " + cWeek);
        return cWeek;
    }

Logcat:

D/DashboardViewModel: cWeek AFTER: null
D/DashboardViewModel: cWeek: 1
英文:

I have set up a getter method in my ViewModel to get a Long-type field called cWeek. When I use the value.getLong inside the addSnapshotListener, it works and returns the value from the db but when I try to return it, the variable is null. I seriously have no idea what to search for to resolve this problem.

Getter

// this var is initialized in global scope
Long cWeek = getCWeek();

public Long getCWeek() {
        new References()
                .getUserRefDoc()
                .addSnapshotListener(new EventListener&lt;DocumentSnapshot&gt;() {
                    @Override
                    public void onEvent(@Nullable DocumentSnapshot value, @Nullable FirebaseFirestoreException e) {
                        if (e != null) {
                            Log.d(TAG, &quot;Could not get cWeek data &quot; + e);
                        }
                        Long var = (Long) value.get(&quot;cWeek&quot;);

                        cWeek = var;
                        Log.d(TAG, &quot;cWeek: &quot; + cWeek);
                    }
                });
        Log.d(TAG, &quot;cWeek AFTER: &quot; + cWeek);
        return cWeek;
    }

Logcat:

D/DashboardViewModel: cWeek AFTER: null
D/DashboardViewModel: cWeek: 1

答案1

得分: 1

addSnapshotListener异步的,在查询完成之前立即返回。您提供的回调会在稍后的某个时间被调用。与此同时,您的代码会继续执行,并且在查询仍在进行时返回cWeek的初始值。

如果您想要从ViewModel提供Firestore查询(或任何异步函数)的结果,您应该返回一个LiveData,它将传递最终结果。调用者可以观察ViewModel以获取结果,无论何时准备好都会收到。

英文:

addSnapshotListener is asynchronous and returns immediately, before the query is complete. The callback you provide is invoked some time later. Meanwhile, your code continues to execute, and the initial value of cWeek is returned while the query is still happening.

If you want to provide the results of a Firestore query (or any asynchronous function) from a ViewModel, you should return a LiveData that will deliver the final result. The caller can observe the ViewModel for the result, to be received whenever it's ready.

huangapple
  • 本文由 发表于 2020年8月2日 13:57:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/63212862.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定