#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;
}
}
Я пытался разобраться в этом в течение недели и до сих пор ничего не добился. Я много чего перепробовал, но все равно не смог найти решение. Если что-то непонятно, пожалуйста, спросите. Пожалуйста, помогите. Спасибо.
Редактировать:
Я извлекаю данные следующим образом:
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 решило проблему. И большое спасибо, чувак. Вы очень помогли. И я хотел бы снова связаться с вами в будущем за помощью. Еще раз спасибо.