无法获取 child 的数组列表 (firebase)
Having troubles getting arraylist of a child (firebase)
大家好我正在尝试从 firebase 检索数据并根据我在 RecyclerView 上单击的内容显示它们并将名称传递给下一个 activity。
每当我尝试这样做时,它总是会关闭应用程序并再次打开。
但是只要集合中没有“Dates_Log_In”,它就会 运行 但不会显示任何类型的数据。
这是我用来在 RecyclerView
中显示所有数据的 class
public class Listing extends AppCompatActivity implements AttendanceListAdapter.OnNoteListener{
Button back;
DatabaseReference mRef;
ArrayList<Attendance> userList;
RecyclerView recyclerView;
AttendanceListAdapter adapter;
TextView name;
TextView designation;
TextView activity;
TextView status;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
recyclerView = findViewById(R.id.rcl_List);
back = findViewById(R.id.btn_go_back);
name = findViewById(R.id.txt_name1);
designation = findViewById(R.id.txt_designation1);
activity = findViewById(R.id.txt_activity1);
status = findViewById(R.id.txt_status1);
mRef = FirebaseDatabase.getInstance().getReference("Users");
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
userList = new ArrayList<>();
adapter = new AttendanceListAdapter(this, userList);
recyclerView.setAdapter(adapter);
mRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot : snapshot.getChildren()){
Attendance user = dataSnapshot.getValue(Attendance.class);
userList.add(user);
}
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Listing.this, "Failed to retrieve Data", Toast.LENGTH_LONG).show();
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
@Override
public void onNoteClick(int position) {
userList.get(position);
}
}
出勤率Class
public class Attendance {
public String fullname, designation, activity, status, date;
private long maxid = 0;
private DatabaseReference mref;
public Attendance(){
}
public Attendance(String fullname, String designation, String activity, String status){
this.fullname = fullname;
this.designation = designation;
this.activity = activity;
this.status = status;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public void setActivity(String activity) {
this.activity = activity;
}
public void setStatus(String status) {
this.status = status;
}
public void setDate(String date) {
this.date = date;
}
public String getFullname(){
return fullname;
}
public String getDesignation(){
return designation;
}
public String getActivity(){
return activity;
}
public String getStatus(){
return status;
}
public String getDate(){
return date;
}
}
AttendanceListAdapter
public class AttendanceListAdapter extends RecyclerView.Adapter<AttendanceListAdapter.MyViewHolder> {
ArrayList<Attendance> attendanceArrayList;
Context context;
public AttendanceListAdapter(Context context, ArrayList<Attendance> list){
this.context = context;
this.attendanceArrayList = list;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView name, designation, activity, status;
public MyViewHolder(final View view){
super(view);
name = view.findViewById(R.id.txt_name1);
designation = view.findViewById(R.id.txt_designation1);
activity = view.findViewById(R.id.txt_activity1);
status = view.findViewById(R.id.txt_status1);
}
}
@NonNull
@Override
public AttendanceListAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull AttendanceListAdapter.MyViewHolder holder, int position) {
Attendance user = attendanceArrayList.get(position);
holder.name.setText(user.getFullname());
holder.designation.setText(user.getDesignation());
holder.activity.setText(user.getActivity());
holder.status.setText(user.getStatus());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String id = user.getFullname();
passData(id);
}
});
}
private void passData(String id) {
Intent intent = new Intent(context,Logbook.class);
intent.putExtra("id", id);
context.startActivity(intent);
}
@Override
public int getItemCount() {
return attendanceArrayList.size();
}
public interface OnNoteListener{
void onNoteClick(int position);
}
}
这是我传递数据的地方,它应该将“Dates_Log_In”显示到 ListView(不确定这是否是正确的选择)
public class Logbook extends AppCompatActivity {
Button back;
DatabaseReference mRef;
ListView listView;
ArrayList<String> userList;
ArrayAdapter<String> adapter;
TextView txt_name;
TextView txt_date;
date Date;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logbook);
Intent intent = getIntent();
String id = intent.getStringExtra("id");
Date = new date();
listView = findViewById(R.id.list_date);
back = findViewById(R.id.btn_go_back2);
txt_name = findViewById(R.id.txt_nameselected);
txt_date = findViewById(R.id.txt_date);
txt_name.setText(id);
mRef = FirebaseDatabase.getInstance().getReference("Users").child(id);
userList = new ArrayList<>();
adapter = new ArrayAdapter<String>(this, R.layout.logbook_layout, R.id.txt_date, userList);
mRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot : snapshot.getChildren()){
Log.i("Dates_Log_In", dataSnapshot.getValue(String.class));
Date = dataSnapshot.getValue(date.class);
userList.add(Date.getDate());
}
listView.setAdapter(adapter);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Logbook.this, "Failed to retrieve Data", Toast.LENGTH_LONG).show();
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
在测试过程中运行报错如下
E/le.enrollmentq: [qarth_debug:] get PatchStore::createDisableExceptionQarthFile method fail.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.enrollmentqr, PID: 3144
com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.ArrayList to String
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertString(CustomClassMapper.java:426)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:217)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80)
at com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203)
at com.example.enrollmentqr.Logbook.onDataChange(Logbook.java:64)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
at com.google.firebase.database.core.view.EventRaiser.run(EventRaiser.java:55)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
并且在 logcat 这表明
2022-05-05 22:33:21.684 3144-3144/com.example.enrollmentqr W/ClassMapper: No setter/field for Dates_Log_In found on class com.example.enrollmentqr.Attendance
2022-05-05 22:33:21.700 3144-3144/com.example.enrollmentqr W/ClassMapper: No setter/field for Dates_Log_In found on class com.example.enrollmentqr.Attendance
这是我为数据库设置的规则。
{
"rules": {
".read": true,
".write": true,
"Users": {
"Dates_Log_In":{
"$uid":{
".read": true,
".write": true,
}
},
"activity":{
".read": true,
".write": true,
},
"designation":{
".read": true,
".write": true,
},
"fullname":{
".read": true,
".write": true,
},
"status":{
".read": true,
".write": true,
}
}
}
}
我在从 firebase 获取数据时有点知道,因为我没有在 Attendance.class 中包含日期,这就是它给出空值的原因(只是我的直觉)。所以我尝试包括它,但这对我来说也没有用。我有点猜测我如何称呼 firebase 有问题?我几天前才开始为我的项目做这个。
这毫无意义:
Log.i("Dates_Log_In", dataSnapshot.getValue(String.class));
Date = dataSnapshot.getValue(date.class);
dataSnapshot
可以是 String
,也可以是 date
,但不能同时是两者。这意味着这些行中至少有一条总是会失败。
由于您正在阅读此路径:
mRef = FirebaseDatabase.getInstance().getReference("Users").child(id);
所以您正在阅读 /Users/$id
,据我所知,它包含单个用户的数据。这意味着您不需要在 onDataChange
中遍历 snapshot.getChildren
,因为 snapshot
已经只包含该单个用户的数据。
然后是下面的数据问题,如果不查看您的实际 JSON 很难确定。我可以推荐的最安全的方法是让 Firebase 弄清楚,然后在没有类型的情况下调用 getValue()
。
mRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
Map<String, object> values = dataSnapshot.getValue();
...
}
很可能你会从中得到一个 Map<String, Object>
,然后你可以用这样的东西来显示它:How to print all key and values from HashMap in Android?
大家好我正在尝试从 firebase 检索数据并根据我在 RecyclerView 上单击的内容显示它们并将名称传递给下一个 activity。
每当我尝试这样做时,它总是会关闭应用程序并再次打开。
但是只要集合中没有“Dates_Log_In”,它就会 运行 但不会显示任何类型的数据。
这是我用来在 RecyclerView
中显示所有数据的 classpublic class Listing extends AppCompatActivity implements AttendanceListAdapter.OnNoteListener{
Button back;
DatabaseReference mRef;
ArrayList<Attendance> userList;
RecyclerView recyclerView;
AttendanceListAdapter adapter;
TextView name;
TextView designation;
TextView activity;
TextView status;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
recyclerView = findViewById(R.id.rcl_List);
back = findViewById(R.id.btn_go_back);
name = findViewById(R.id.txt_name1);
designation = findViewById(R.id.txt_designation1);
activity = findViewById(R.id.txt_activity1);
status = findViewById(R.id.txt_status1);
mRef = FirebaseDatabase.getInstance().getReference("Users");
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
userList = new ArrayList<>();
adapter = new AttendanceListAdapter(this, userList);
recyclerView.setAdapter(adapter);
mRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot : snapshot.getChildren()){
Attendance user = dataSnapshot.getValue(Attendance.class);
userList.add(user);
}
adapter.notifyDataSetChanged();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Listing.this, "Failed to retrieve Data", Toast.LENGTH_LONG).show();
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
@Override
public void onNoteClick(int position) {
userList.get(position);
}
}
出勤率Class
public class Attendance {
public String fullname, designation, activity, status, date;
private long maxid = 0;
private DatabaseReference mref;
public Attendance(){
}
public Attendance(String fullname, String designation, String activity, String status){
this.fullname = fullname;
this.designation = designation;
this.activity = activity;
this.status = status;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public void setActivity(String activity) {
this.activity = activity;
}
public void setStatus(String status) {
this.status = status;
}
public void setDate(String date) {
this.date = date;
}
public String getFullname(){
return fullname;
}
public String getDesignation(){
return designation;
}
public String getActivity(){
return activity;
}
public String getStatus(){
return status;
}
public String getDate(){
return date;
}
}
AttendanceListAdapter
public class AttendanceListAdapter extends RecyclerView.Adapter<AttendanceListAdapter.MyViewHolder> {
ArrayList<Attendance> attendanceArrayList;
Context context;
public AttendanceListAdapter(Context context, ArrayList<Attendance> list){
this.context = context;
this.attendanceArrayList = list;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView name, designation, activity, status;
public MyViewHolder(final View view){
super(view);
name = view.findViewById(R.id.txt_name1);
designation = view.findViewById(R.id.txt_designation1);
activity = view.findViewById(R.id.txt_activity1);
status = view.findViewById(R.id.txt_status1);
}
}
@NonNull
@Override
public AttendanceListAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull AttendanceListAdapter.MyViewHolder holder, int position) {
Attendance user = attendanceArrayList.get(position);
holder.name.setText(user.getFullname());
holder.designation.setText(user.getDesignation());
holder.activity.setText(user.getActivity());
holder.status.setText(user.getStatus());
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String id = user.getFullname();
passData(id);
}
});
}
private void passData(String id) {
Intent intent = new Intent(context,Logbook.class);
intent.putExtra("id", id);
context.startActivity(intent);
}
@Override
public int getItemCount() {
return attendanceArrayList.size();
}
public interface OnNoteListener{
void onNoteClick(int position);
}
}
这是我传递数据的地方,它应该将“Dates_Log_In”显示到 ListView(不确定这是否是正确的选择)
public class Logbook extends AppCompatActivity {
Button back;
DatabaseReference mRef;
ListView listView;
ArrayList<String> userList;
ArrayAdapter<String> adapter;
TextView txt_name;
TextView txt_date;
date Date;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logbook);
Intent intent = getIntent();
String id = intent.getStringExtra("id");
Date = new date();
listView = findViewById(R.id.list_date);
back = findViewById(R.id.btn_go_back2);
txt_name = findViewById(R.id.txt_nameselected);
txt_date = findViewById(R.id.txt_date);
txt_name.setText(id);
mRef = FirebaseDatabase.getInstance().getReference("Users").child(id);
userList = new ArrayList<>();
adapter = new ArrayAdapter<String>(this, R.layout.logbook_layout, R.id.txt_date, userList);
mRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for(DataSnapshot dataSnapshot : snapshot.getChildren()){
Log.i("Dates_Log_In", dataSnapshot.getValue(String.class));
Date = dataSnapshot.getValue(date.class);
userList.add(Date.getDate());
}
listView.setAdapter(adapter);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(Logbook.this, "Failed to retrieve Data", Toast.LENGTH_LONG).show();
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
在测试过程中运行报错如下
E/le.enrollmentq: [qarth_debug:] get PatchStore::createDisableExceptionQarthFile method fail.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.enrollmentqr, PID: 3144
com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.ArrayList to String
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertString(CustomClassMapper.java:426)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(CustomClassMapper.java:217)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(CustomClassMapper.java:80)
at com.google.firebase.database.DataSnapshot.getValue(DataSnapshot.java:203)
at com.example.enrollmentqr.Logbook.onDataChange(Logbook.java:64)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:75)
at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
at com.google.firebase.database.core.view.EventRaiser.run(EventRaiser.java:55)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
并且在 logcat 这表明
2022-05-05 22:33:21.684 3144-3144/com.example.enrollmentqr W/ClassMapper: No setter/field for Dates_Log_In found on class com.example.enrollmentqr.Attendance
2022-05-05 22:33:21.700 3144-3144/com.example.enrollmentqr W/ClassMapper: No setter/field for Dates_Log_In found on class com.example.enrollmentqr.Attendance
这是我为数据库设置的规则。
{
"rules": {
".read": true,
".write": true,
"Users": {
"Dates_Log_In":{
"$uid":{
".read": true,
".write": true,
}
},
"activity":{
".read": true,
".write": true,
},
"designation":{
".read": true,
".write": true,
},
"fullname":{
".read": true,
".write": true,
},
"status":{
".read": true,
".write": true,
}
}
}
}
我在从 firebase 获取数据时有点知道,因为我没有在 Attendance.class 中包含日期,这就是它给出空值的原因(只是我的直觉)。所以我尝试包括它,但这对我来说也没有用。我有点猜测我如何称呼 firebase 有问题?我几天前才开始为我的项目做这个。
这毫无意义:
Log.i("Dates_Log_In", dataSnapshot.getValue(String.class));
Date = dataSnapshot.getValue(date.class);
dataSnapshot
可以是 String
,也可以是 date
,但不能同时是两者。这意味着这些行中至少有一条总是会失败。
由于您正在阅读此路径:
mRef = FirebaseDatabase.getInstance().getReference("Users").child(id);
所以您正在阅读 /Users/$id
,据我所知,它包含单个用户的数据。这意味着您不需要在 onDataChange
中遍历 snapshot.getChildren
,因为 snapshot
已经只包含该单个用户的数据。
然后是下面的数据问题,如果不查看您的实际 JSON 很难确定。我可以推荐的最安全的方法是让 Firebase 弄清楚,然后在没有类型的情况下调用 getValue()
。
mRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
Map<String, object> values = dataSnapshot.getValue();
...
}
很可能你会从中得到一个 Map<String, Object>
,然后你可以用这样的东西来显示它:How to print all key and values from HashMap in Android?