Кто-нибудь может сказать мне, как я могу сохранить массив пользовательских объектов в Firebase Firestore (Android)

#android #firebase #google-cloud-firestore #development-environment

#Android #firebase #google-cloud-firestore #среда разработки

Вопрос:

Кто-нибудь может сказать мне, как я могу сохранить массив пользовательских объектов в Firebase Firestore (Android) из одного приложения, а затем извлечь объекты обратно в другое приложение (оба приложения подключены к одному и тому же проекту Firebase). Я попытался использовать Maps, и мне удалось сохранить список заказов, но я не могу получить ArrayList обратно. Вот как я это сделал:

 Map<String, ArrayList<OrderItemModel>> map = new HashMap<>();
map.put(currentOrderNumber, orderList);
firebaseFirestore.collection("orders").document(college).set(map, SetOptions.merge())
        .addOnSuccessListener(new OnSuccessListener<Void>() {
    @Override
    public void onSuccess(Void aVoid) {
        Toast.makeText(getContext(), "Order placed.", Toast.LENGTH_SHORT).show();
    }
}).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        Toast.makeText(getContext(), "Couldn't place order. Please try again.", Toast.LENGTH_SHORT).show();
        progressBar.setVisibility(View.GONE);
    }
});
 

Когда я попытался извлечь его с помощью documentSnapshot.getData(), он возвращает Map<String, Object> . Я попытался преобразовать объект в ArrayList и использовать его в адаптере RecyclerView, но он показывает ошибку.
Вот мой класс OrderItemModel:

 public class OrderItemModel {

    private String itemName;
    private String itemPrice;
    private String itemCount;

    public OrderItemModel() {
    }

    public OrderItemModel(String itemName, String itemPrice, String itemCount) {
        this.itemName = itemName;
        this.itemPrice = itemPrice;
        this.itemCount = itemCount;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public String getItemPrice() {
        return itemPrice;
    }

    public void setItemPrice(String itemPrice) {
        this.itemPrice = itemPrice;
    }

    public String getItemCount() {
        return itemCount;
    }

    public void setItemCount(String itemCount) {
        this.itemCount = itemCount;
    }
}
 

Мой Firebase Firestore:
введите описание изображения здесь

Я пытался разобраться в этом в течение недели и до сих пор ничего не добился. Я много чего перепробовал, но все равно не смог найти решение. Если что-то непонятно, пожалуйста, спросите. Пожалуйста, помогите. Спасибо.

Редактировать:

Я извлекаю данные следующим образом:

 firebaseFirestore.collection("orders").document(college).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task) {
        if (task.isSuccessful()) {
            DocumentSnapshot documentSnapshot = task.getResult();
            assert documentSnapshot != null;
            if (documentSnapshot.exists()) {
                Map<String, Object> listMap = documentSnapshot.getData();
                for (Map.Entry<String, Object> entry : listMap.entrySet()) {
                    Log.d(TAG, "onComplete: Key: "   entry.getKey()   ", Value: "   entry.getValue().toString());
                    if (entry.getKey().equals(currentOrderNumber)) {
                        orderList.addAll((Collection<? extends OrderItemModel>) entry.getValue());
                    }
                }
                Log.d(TAG, "onComplete: ArrayList: "   orderList.get(0).getItemName());         // This line shows error.
                progressBar.setVisibility(View.GONE);
            } else {
                Toast.makeText(ShowOrder.this, "Order document not found!", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(ShowOrder.this, "An error occurred while fetching the data.", Toast.LENGTH_SHORT).show();
        }
    }
});
 

Насколько я понимаю, я успешно извлекаю данные в виде Map<String, Object>, но не могу извлечь из него ArrayList .

 Log.d(TAG, "onComplete: ArrayList: "   orderList.get(0).getItemName());
 

В приведенной выше строке отображается следующая ошибка:

 2021-01-10 23:48:40.192 8747-8747/com.campuscanteen.main E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.campuscanteen.main, PID: 8747
    java.lang.ClassCastException: java.util.HashMap cannot be cast to com.campuscanteen.main.Models.OrderItemModel
        at com.campuscanteen.main.ShowOrder$2.onComplete(ShowOrder.java:89)
        at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:230)
        at android.app.ActivityThread.main(ActivityThread.java:7815)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
 

Редактировать 2:

Я создал класс, как вы предложили:

 public class OrderList {
    public List<OrderItemModel> modelList;

    public OrderList() {
    }

    @Override
    public String toString() {
        return "OrderList{"  
                "modelList="   modelList  
                '}';
    }
}
 

И попробовал эти строки для получения данных:

 List<OrderItemModel> myLists = documentSnapshot.toObject(OrderList.class).modelList;
                        Log.d(TAG, "onComplete: ArrayList: "   myLists.toString());  // myLists here has null value.
 

Таким образом, список имеет нулевое значение. Простите за недостаток знаний и, пожалуйста, помогите.

Комментарии:

1. Можете ли вы предоставить свой код при попытке извлечения данных? Какую ошибку он показывает? — также укажите исключение

2. Как указано в исключении, вы пытаетесь преобразовать HashMap в OrderItemModel . Итак, я предполагаю, что entry.GetValue() возвращает тип HashMap, и вы хотите преобразовать его в OrderItemModel в строке кода 89.

3. @SlothCoding Да. Я также попробовал documentSnapshot.getData().get(currentOrderNumber), и результат тот же. Я не знаю, что делать. Можете ли вы сказать мне способ вернуть ArrayList. Я хочу использовать ArrayList для RecyclerView.

Ответ №1:

Вы получаете следующую ошибку:

java.lang.ClassCastException: java.util.HashMap не может быть приведен к com.campuscanteen.main.Модели.OrderItemModel

Потому что вы пытаетесь преобразовать объект типа HashMap в объект типа OrderItemModel, что на самом деле невозможно в Java.

Видя ваш скриншот, ваш документ содержит свойство типа array с именем «201». Этот массив содержит объекты в терминах «OrderItemModel». Я не уверен, почему вы назвали бы этот массив таким образом, поскольку «OrderItems» может быть более значимым. Однако, чтобы сопоставить этот массив с a List<OrderItemModel> , вы должны просто создать класс с одним свойством:

 class OrdersDocument {
    public List<OrderItemModel> orderItems;
}
 

Теперь вы можете создать ссылку на документ, прикрепить прослушиватель и преобразовать массив в список пользовательских объектов:

 List<OrderItemModel> orderItems = document.toObject(OrdersDocument.class).orderItems;
 

Как объясняется в моей статье по следующей ссылке:

Как сопоставить массив объектов из Cloud Firestore со списком объектов?

Комментарии:

1. Я сохраняю заказы, размещенные клиентом. ‘201’ — это номер заказа, а массив — это элементы в этом порядке. Я пытался, как вы сказали, но получаемый arraylist имеет нулевое значение. Я не понимаю, как это будет работать (извините, я новичок в разработке Android). Мой вопрос — поскольку мы сохранили map<String, Arraylist<OrderItemModel>> в Firestore, то как мы можем получить его с помощью класса, членом которого является arraylist (разве это тоже не map). И я уже просмотрел вашу статью, прежде чем задавать вопрос здесь, но это не помогло. Я добавлю код в раздел «Редактировать 2:». Пожалуйста, помогите.

2. Пожалуйста, отредактируйте свой вопрос с помощью кода (не моего ответа). Если вы получаете нулевое значение, это означает, что, скорее всего, вы не изменили идентификатор документа с «201» на «OrderItems». Нет, это не должна быть карта. Вы можете получить весь документ в виде карты, но массив должен быть сопоставлен со списком. Попробуйте еще раз и скажите мне, работает ли это.

3. Извините, но на этот раз я получаю сообщение об ошибке — «java.lang.RuntimeException: в классе com.campuscanteen.main не найдено свойств для сериализации. Список заказов »

4. Вы получаете эту ошибку, потому что свойство array в документе по-прежнему называется «201», что неверно . Свойство должно быть названо «OrderItems». Удалите эти данные и добавьте их снова. Если вам нужен идентификатор заказа, вы можете добавить его как свойство класса, верно?

5. Я уже изменил имя документа, но обнаружил, что получаю эту ошибку, потому что у меня был закрытый член в классе orderList и не было никаких геттеров. Простое добавление метода getter решило проблему. И большое спасибо, чувак. Вы очень помогли. И я хотел бы снова связаться с вами в будущем за помощью. Еще раз спасибо.