android - 如何捕获java.lang.RuntimeException : Could not deserialize object from Firebase ClassMapper and add default Values

标签 android firebase google-cloud-firestore firebaseui

我正在使用 Firebase UI Recycler Adapter 从 Firestore 读取数据

FirestoreRecyclerOptions<Transaction> options =
                new FirestoreRecyclerOptions.Builder<Transaction>()
                        .setQuery(mQuery, Transaction.class)
                        .setLifecycleOwner(this)
                        .build();

        mAdapter = new TransactionAdapter(options, this, getActivity()) {

            @Override
            public void onDataChanged() {
                // Show/hide content if the query returns empty.
                if (getItemCount() == 0) {
                    mRestaurantsRecycler.setVisibility(View.GONE);
                    mEmptyView.setVisibility(View.VISIBLE);
                } else {
                    mRestaurantsRecycler.setVisibility(View.VISIBLE);
                    mEmptyView.setVisibility(View.GONE);
                }
            }

            @Override
            public void onError(FirebaseFirestoreException e) {
                Log.e("Error", ", not initializing RecyclerView",e);
            }
        };
        Log.w("Test", "No6 query, not initializing RecyclerView");
        mRestaurantsRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRestaurantsRecycler.setAdapter(mAdapter);

我遇到了 Firestore 中某些损坏字段的异常

java.lang.RuntimeException: Could not deserialize object. Failed to convert a value of type java.lang.String to double (found in field 'amount')
    at com.google.firebase.firestore.util.CustomClassMapper.deserializeError(com.google.firebase:firebase-firestore@@17.1.4:524)
    at com.google.firebase.firestore.util.CustomClassMapper.convertDouble(com.google.firebase:firebase-firestore@@17.1.4:427)
    at com.google.firebase.firestore.util.CustomClassMapper.deserializeToPrimitive(com.google.firebase:firebase-firestore@@17.1.4:304)
    at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-firestore@@17.1.4:215)
    at com.google.firebase.firestore.util.CustomClassMapper.deserializeToType(com.google.firebase:firebase-firestore@@17.1.4:180)
    at com.google.firebase.firestore.util.CustomClassMapper.access$200(com.google.firebase:firebase-firestore@@17.1.4:53)
    at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-firestore@@17.1.4:700)
    at com.google.firebase.firestore.util.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-firestore@@17.1.4:674)
    at com.google.firebase.firestore.util.CustomClassMapper.convertBean(com.google.firebase:firebase-firestore@@17.1.4:503)
    at com.google.firebase.firestore.util.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-firestore@@17.1.4:242)
    at com.google.firebase.firestore.util.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-firestore@@17.1.4:97)
    at com.google.firebase.firestore.DocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@17.1.4:203)
    at com.google.firebase.firestore.QueryDocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@17.1.4:121)
    at com.google.firebase.firestore.DocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@17.1.4:183)
    at com.google.firebase.firestore.QueryDocumentSnapshot.toObject(com.google.firebase:firebase-firestore@@17.1.4:101)
    at com.firebase.ui.firestore.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:23)
    at com.firebase.ui.firestore.ClassSnapshotParser.parseSnapshot(ClassSnapshotParser.java:12)
    at com.firebase.ui.common.BaseCachingSnapshotParser.parseSnapshot(BaseCachingSnapshotParser.java:35)
    at com.firebase.ui.common.BaseObservableSnapshotArray.get(BaseObservableSnapshotArray.java:52)
    at com.firebase.ui.firestore.FirestoreRecyclerAdapter.getItem(FirestoreRecyclerAdapter.java:83)
    at com.firebase.ui.firestore.FirestoreRecyclerAdapter.onBindViewHolder(FirestoreRecyclerAdapter.java:125)
    at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6673)
    at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6714)
    at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5647)
    at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5913)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5752)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5748)
    at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2232)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1559)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1519)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:614)
    at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3812)
    at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:3225)
    at android.view.View.measure(View.java:22071)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
    at android.support.design.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:739)

我知道为什么会抛出此错误,并且我也知道如果我更正 Firestore 数据库中的金额字段或通过使用云函数来检查数据验证等,我可以更正此错误。

但我不想要应用程序崩溃的体验。有什么方法可以捕获并添加任何默认值或 Null 来表示损坏的值。显示单个 Null 或 NA 字段或整个空屏幕总是比崩溃好。

编辑: 为了设置默认值并避免运行时异常,我在我的模型类中尝试了这一点。我还是不知道是否有办法捕获这个异常。

public double amount;
public double getAmount() {
    return amount;
}
// If you change it Object, ClassMapper will not throw any exception and 
// You can parse any data type by yourself and also set a default value.
public void setAmount(Object amount) {
    try {
        // You can also add  instanceOf check
        this.amount = Double.parseDouble(amount.toString());
    } catch (Exception e) {
        // Set your default value
        this.amount = 0.00;
    }
}

最佳答案

我回答这个问题是因为你来自 here 的请求。因为我看到您正在使用 Firebase-UI 库,所以不需要使用 try-catch block 。正如 @FrankvanPuffelen 在他的评论中提到的,您可以做的最简单的事情就是重写适配器类中的 onError 方法,如下所示:

FirestoreRecyclerAdapter adapter = new FirestoreRecyclerAdapter<Chat, ChatHolder>(options) {
    @Override
    public void onDataChanged() {
        //Called each time there is a new query snapshot.
    }

    @Override
    public void onError(FirebaseFirestoreException e) {
        //Handle the error
        Log.d(TAG, e.getMessage());
    }
};

关于android - 如何捕获java.lang.RuntimeException : Could not deserialize object from Firebase ClassMapper and add default Values,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53849305/

相关文章:

firebase - 注销错误 Cloud Firestore。调用者无权执行指定操作

java - 如何同时完成Firebase Storage Task和Firestore Task?

android - 为什么从一项 Activity 传递可分包数据并在另一项 Activity 中接收部分修改的数据?

java - 如何在 ARCore 中捕获每一帧

angular - 为什么 Firebase Deploy 只找到 1-2 个文件?只是 Firebase 托管的默认索引

适用于欧盟应用的 Firebase 位置最佳实践

android - 在我的 android 项目中使用 android box 2d

java - Sqlite 和 Window 已经聚焦

firebase - 如何从列表元素中获取单个值

javascript - 我可以使用 Firestore 获取使用 batch().set 创建的文档的生成 ID 吗?