Как перехватить java.lang.RuntimeException: не удалось десериализовать объект из Firebase ClassMapper и добавить значения по умолчанию - PullRequest
0 голосов
/ 19 декабря 2018

Я использую 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 или всего пустого экрана всегда лучше, чем Crash.

EDIT: Чтобы установить значение по умолчанию и избежать исключения времени выполнения, я пробовал это с моимМодельный класс.Я до сих пор не знаю, есть ли способ поймать это исключение.

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;
    }
}

1 Ответ

0 голосов
/ 19 декабря 2018

Я отвечаю на этот вопрос из-за вашего запроса от здесь .Так как я вижу, что вы используете библиотеку Firebase-UI, нет необходимости использовать блок try-catch.Как и @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());
    }
};
...