使用带有 Firestore 的 collection.add() 应用程序崩溃

Posted

技术标签:

【中文标题】使用带有 Firestore 的 collection.add() 应用程序崩溃【英文标题】:App crashing using collection.add() with Firestore 【发布时间】:2019-04-16 23:52:54 【问题描述】:

我是 android 开发的新手,所以如果这听起来很琐碎或太长,请原谅我,但是我在尝试将项目添加到 Firestore 中的集合时遇到了困难。

我在教程的 cmets 部分的某处读到这发生在 API 25 之下(我使用的是 24),但我不知道为什么。

这是我的部分代码:

FirebaseFirestore db;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_registro);

    FirebaseFirestore firestore = FirebaseFirestore.getInstance();
    FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
            .setTimestampsInSnapshotsEnabled(true)
            .build();
    firestore.setFirestoreSettings(settings);

    db = FirebaseFirestore.getInstance();


public void sendInfo(View view)
        CollectionReference dbArtists = db.collection("artistas");
        Artist a = new Artist("0", "A", 10);
        dbArtists.add(a)
    

sendInfo 与一个可以正常工作的按钮相关联。使应用程序崩溃的行是

dbArtists.add(a)

所以 logcat 有一个警告说明:

com.esiete.anapptitle W/Firestore: (0.6.6-dev) [Firestore]: The behavior for java.util.Date objects stored in Firestore is going to change AND YOUR APP MAY BREAK.
To hide this warning and ensure your app does not break, you need to add the following code to your app before calling any other Cloud Firestore methods:

FirebaseFirestore firestore = FirebaseFirestore.getInstance();
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
    .setTimestampsInSnapshotsEnabled(true)
    .build();
firestore.setFirestoreSettings(settings);

With this change, timestamps stored in Cloud Firestore will be read back as com.google.firebase.Timestamp objects instead of as system java.util.Date objects. So you will also need to update code expecting a java.util.Date to instead expect a Timestamp. For example:

// Old:
java.util.Date date = snapshot.getDate("created_at");
// New:
Timestamp timestamp = snapshot.getTimestamp("created_at");
java.util.Date date = timestamp.toDate();

Please audit all existing usages of java.util.Date when you enable the new behavior. In a future release, the behavior will be changed to the new behavior, so if you do not follow these steps, YOUR APP MAY BREAK.

如上所示添加代码后仍然存在崩溃。 Logcat 显示:

8-11-13 21:44:09.290 30030-30030/com.esiete.anapptitle D/AndroidRuntime: Shutting down VM
2018-11-13 21:44:09.294 30030-30030/com.esiete.anapptitle E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.esiete.anapptitle, PID: 30030
    java.lang.IllegalStateException: Could not execute method for android:onClick
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
        at android.view.View.performClick(View.java:5612)
        at android.view.View$PerformClick.run(View.java:22285)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6123)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
        at android.view.View.performClick(View.java:5612) 
        at android.view.View$PerformClick.run(View.java:22285) 
        at android.os.Handler.handleCallback(Handler.java:751) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6123) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757) 
     Caused by: java.lang.RuntimeException: No properties to serialize found on class com.esiete.anapptitle.Artist
        at com.google.firebase.firestore.g.zzg$zza.<init>(SourceFile:643)
        at com.google.firebase.firestore.g.zzg.zza(SourceFile:331)
        at com.google.firebase.firestore.g.zzg.zzb(SourceFile:152)
        at com.google.firebase.firestore.g.zzg.zza(SourceFile:1085)
        at com.google.firebase.firestore.UserDataConverter.convertPOJO(SourceFile:421)
        at com.google.firebase.firestore.CollectionReference.add(SourceFile:125)
        at com.esiete.anapptitle.RegistroActivity.enviarRegistro(RegistroActivity.java:82)
        at java.lang.reflect.Method.invoke(Native Method) 
        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385) 
        at android.view.View.performClick(View.java:5612) 
        at android.view.View$PerformClick.run(View.java:22285) 
        at android.os.Handler.handleCallback(Handler.java:751) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6123) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757) 
2018-11-13 21:44:09.298 4088-5186/? W/ActivityManager:   Force finishing activity com.esiete.anapptitle/.RegistroActivity
2018-11-13 21:44:09.306 4088-30868/? W/DropBoxManagerService: Dropping: data_app_crash (1752 > 0 bytes)

非常感谢任何帮助或建议。

编辑:添加艺术家类代码。

package com.esiete.anapptitle;

public class Artist 
    private String artistID;
    private String name;
    private int sales;

    public Artist() 
    

    public Artist(String artistID, String name, int sales) 
        this.artistID = artistID;
        this.name = name;
        this.sales = sales;
    

【问题讨论】:

错误消息是在抱怨你的课程Artist:“在类 com.esiete.anapptitle.Artist 上找不到要序列化的属性”。请编辑您的问题以显示该类的代码。 在使用 add() 函数之前,您是否初始化了列表的新实例? @DougStevenson 完成。我尝试按照here 的建议公开我的变量,但没有成功。 @AnjaniMittal 没有。对不起,你在说什么清单?你是说FireStore的吗?是的,我有。 【参考方案1】:

您的 Artist 类没有任何信息表明 Firebase 知道如何在数据库中进行序列化。为了让它知道这一点,该类需要具有公共字段或公共 getter 和 setter 方法。

假设您的数据库中的Artist 文档具有以下三个字段:

artistId: "0"
name: "A"
sales: 10

这意味着你需要这个 Java 类:

public class Artist 
    public String artistId;
    public String name;
    public long sales;

此处的每个公共字段都与数据库中文档的确切字段名称匹配,这就是 Firebase 客户端读取/写入正确值的方式。

您也可以使用这个 Java 类:

public class Artist 
    String artistId;
    String name;
    long sales;

    public Artist()  // Empty constructor is required
    public Artist(String artistId, String name, long sales) 
        this.artistId = artistId;
        this.name = name;
        this.sales = sales;
    

    public String getArtistId()  return this.artistId; 
    public void setArtistId(String artistId)  this.artistId = artistId; 
    public String getName()  return this.name; 
    public void setName(String name)  this.name = name; 
    public long getRanking()  return this.ranking; 
    public void setRanking(long ranking)  this.ranking = ranking; 

第二个类遵循 JavaBean 命名约定,这意味着 getId/setId 定义了一个属性 id,它再次匹配数据库中的确切字段名称。

【讨论】:

谢谢,这立即解决了!我会记住的。我会稍微修改一下你的答案;最后两个 String 语句实际上应该是 long

以上是关于使用带有 Firestore 的 collection.add() 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

React Hooks + Firebase Firestore onSnapshot - 正确使用带有反应钩子的 Firestore 监听器

在 nullsafety 之后使用带有 json_serializable 的 firestore

使用带有 vue 的 firestore 获取图像 url

使用带有 Firestore 的 collection.add() 应用程序崩溃

带有 Repository/Firestore 的 MVVM - 存储来自单个集合的不同查询数组的最佳位置在哪里?

带有 .where() 的 Firestore 查询可以执行空搜索吗