Firebase 实时数据库 (Android-Java)- "Class does not define a no-argument constructor"
Firebase Realtime Database (Android-Java)- "Class does not define a no-argument constructor"
我正在尝试从 Java Android 项目的 Firebase 实时数据库中读取数据。我正在使用 Android Studio 4.2.2.
我可以很好地获取 JSON 字符串。当我尝试反序列化数据时,问题就开始了。
那时我得到一个异常:“没有定义无参数构造函数。如果您使用 ProGuard,请确保这些构造函数没有被剥离。”
关键是我已经定义了一个无参数的构造函数。我还检查了这里的文档 https://firebase.google.com/docs/database/android/read-and-write
我的问题是:
- 我做错了什么?
- 如何解析具有多个级别的 JSON?
- 变量名是否必须与 JSON 的键名相同?
提前致谢!
JSON 看起来像这样:
Data Tree
在 Logcat 我可以看到 JSON 安全到达应用程序:
{ key = 1, value = {phone=123456789, name=Mike} }
这里有代码:
public class DataBaseHelper {
private DatabaseReference mDatabase;
public TestData result;
public DataBaseHelper() {
mDatabase = FirebaseDatabase.getInstance().getReference();
// Creamos query
Query query = mDatabase.child("TestData");
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
try {
Log.w("datosdb", userSnapshot.toString());
result = userSnapshot.getValue(TestData.class);
} catch (Exception e) {
Log.w("datosdb", "Parse failed", e);
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w("datosdb", "loadPost:onCancelled", databaseError.toException());
// ...
}
});
}
public class TestData {
public TestData() {
}
public String name;
public int phone;
public String getName() {
return this.name;
}
public int getPhone() {
return this.phone;
}
}
}
例外情况:
2021-07-12 00:58:01.631 25262-25262/com.example.purinasa W/datosdb: DataSnapshot { key = 1, value = {phone=123456789, 名称=迈克} }
2021-07-12 00:58:01.637 25262-25262/com.example.purinasa W/datosdb:解析失败
com.google.firebase.database.DatabaseException: Class com.example.purinasa.application.dataBase.DataBaseHelper$TestData 未定义无参数构造函数。如果您使用 ProGuard,请确保这些构造函数未被剥离。
在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:570)
在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:563)
在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(CustomClassMapper.java:433)
在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:232)
在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80)
在 com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203)
在 com.example.purinasa.application.dataBase.DataBaseHelper$1.onDataChange(DataBaseHelper.java:33)
在 com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
在 com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
在 com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
在 android.os.Handler.handleCallback(Handler.java:938)
在 android.os.Handler.dispatchMessage(Handler.java:99)
在 android.os.Looper.loop(Looper.java:223)
在 android.app.ActivityThread.main(ActivityThread.java:7656)
在 java.lang.reflect.Method.invoke(本机方法)
在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
更新:
在使用@Ticherhaz-FreePalestine 进行一些测试后,我们设法使用以下行单独反序列化数据:
String name = userSnapshot.child("name").getValue(String.class);
Log.w("datosdb", "String is here!!!" + name);
long phone = userSnapshot.child("phone").getValue(Long.class);
Log.w("datosdb", "Long is here!!!" + phone);
顺便说一句,我找不到在不抛出异常的情况下使用此代码的方法。
您已经有一个空的构造函数。所以需要另一个构造函数,它具有所有属性。
@Keep
public class TestData {
private String name;
private int phone;
public TestData() {
}
public TestData(String name, int phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getPhone() {
return this.phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
}
最后,它通过使用 TestData 作为独立 class 而不是内部 class 来工作。我创建了一个新文件 TestData.java 并将其代码移到那里。
所以最后 DatabaseHelper 像这样:
public class DatabaseHelper {
private DatabaseReference mDatabase;
TestData result;
public DatabaseHelper() {
mDatabase = FirebaseDatabase.getInstance().getReference();
// We create a query
Query query = mDatabase.child("TestData");
//We recive query
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
Log.w("datosdb", "Tenemos el resultado de la query.");
try {
Log.w("datosdb", userSnapshot.toString());
// Deserializing only name
String name = userSnapshot.child("name").getValue(String.class);
Log.w("datosdb", "String is here!!!" + name);
// Deserializing only phone
long phone = userSnapshot.child("phone").getValue(Long.class);
Log.w("datosdb", "Long is here!!!" + phone);
// Deserializing into a TestData object
TestData result = userSnapshot.getValue(TestData.class);
Log.w("datosdb", "Parse success!!!");
} catch (Exception e) {
Log.w("datosdb", "Parse failed", e);
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w("datosdb", "loadPost:onCancelled", databaseError.toException());
// ...
}
});
}
}
TestData 看起来像这样(现在在它自己的 .java 文件中):
public class TestData {
private String name;
private long phone;
public TestData(){}
public TestData(String name, long phone){
this.name = name;
this.phone = phone;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public long getPhone() {
return this.phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
}
我正在尝试从 Java Android 项目的 Firebase 实时数据库中读取数据。我正在使用 Android Studio 4.2.2.
我可以很好地获取 JSON 字符串。当我尝试反序列化数据时,问题就开始了。
那时我得到一个异常:“没有定义无参数构造函数。如果您使用 ProGuard,请确保这些构造函数没有被剥离。”
关键是我已经定义了一个无参数的构造函数。我还检查了这里的文档 https://firebase.google.com/docs/database/android/read-and-write
我的问题是:
- 我做错了什么?
- 如何解析具有多个级别的 JSON?
- 变量名是否必须与 JSON 的键名相同?
提前致谢!
JSON 看起来像这样:
Data Tree
在 Logcat 我可以看到 JSON 安全到达应用程序:
{ key = 1, value = {phone=123456789, name=Mike} }
这里有代码:
public class DataBaseHelper {
private DatabaseReference mDatabase;
public TestData result;
public DataBaseHelper() {
mDatabase = FirebaseDatabase.getInstance().getReference();
// Creamos query
Query query = mDatabase.child("TestData");
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
try {
Log.w("datosdb", userSnapshot.toString());
result = userSnapshot.getValue(TestData.class);
} catch (Exception e) {
Log.w("datosdb", "Parse failed", e);
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w("datosdb", "loadPost:onCancelled", databaseError.toException());
// ...
}
});
}
public class TestData {
public TestData() {
}
public String name;
public int phone;
public String getName() {
return this.name;
}
public int getPhone() {
return this.phone;
}
}
}
例外情况:
2021-07-12 00:58:01.631 25262-25262/com.example.purinasa W/datosdb: DataSnapshot { key = 1, value = {phone=123456789, 名称=迈克} } 2021-07-12 00:58:01.637 25262-25262/com.example.purinasa W/datosdb:解析失败 com.google.firebase.database.DatabaseException: Class com.example.purinasa.application.dataBase.DataBaseHelper$TestData 未定义无参数构造函数。如果您使用 ProGuard,请确保这些构造函数未被剥离。 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:570) 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(CustomClassMapper.java:563) 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(CustomClassMapper.java:433) 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:232) 在 com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80) 在 com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203) 在 com.example.purinasa.application.dataBase.DataBaseHelper$1.onDataChange(DataBaseHelper.java:33) 在 com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75) 在 com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63) 在 com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55) 在 android.os.Handler.handleCallback(Handler.java:938) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:223) 在 android.app.ActivityThread.main(ActivityThread.java:7656) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
更新:
在使用@Ticherhaz-FreePalestine 进行一些测试后,我们设法使用以下行单独反序列化数据:
String name = userSnapshot.child("name").getValue(String.class);
Log.w("datosdb", "String is here!!!" + name);
long phone = userSnapshot.child("phone").getValue(Long.class);
Log.w("datosdb", "Long is here!!!" + phone);
顺便说一句,我找不到在不抛出异常的情况下使用此代码的方法。
您已经有一个空的构造函数。所以需要另一个构造函数,它具有所有属性。
@Keep
public class TestData {
private String name;
private int phone;
public TestData() {
}
public TestData(String name, int phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getPhone() {
return this.phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
}
最后,它通过使用 TestData 作为独立 class 而不是内部 class 来工作。我创建了一个新文件 TestData.java 并将其代码移到那里。
所以最后 DatabaseHelper 像这样:
public class DatabaseHelper {
private DatabaseReference mDatabase;
TestData result;
public DatabaseHelper() {
mDatabase = FirebaseDatabase.getInstance().getReference();
// We create a query
Query query = mDatabase.child("TestData");
//We recive query
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
Log.w("datosdb", "Tenemos el resultado de la query.");
try {
Log.w("datosdb", userSnapshot.toString());
// Deserializing only name
String name = userSnapshot.child("name").getValue(String.class);
Log.w("datosdb", "String is here!!!" + name);
// Deserializing only phone
long phone = userSnapshot.child("phone").getValue(Long.class);
Log.w("datosdb", "Long is here!!!" + phone);
// Deserializing into a TestData object
TestData result = userSnapshot.getValue(TestData.class);
Log.w("datosdb", "Parse success!!!");
} catch (Exception e) {
Log.w("datosdb", "Parse failed", e);
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w("datosdb", "loadPost:onCancelled", databaseError.toException());
// ...
}
});
}
}
TestData 看起来像这样(现在在它自己的 .java 文件中):
public class TestData {
private String name;
private long phone;
public TestData(){}
public TestData(String name, long phone){
this.name = name;
this.phone = phone;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public long getPhone() {
return this.phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
}