2

Hi everyone I am trying to retrieve data from firebase and display them based on what I clicked on RecyclerView and pass the name to the next activity.

Whenever I tried to do this it would always close the app and opens again.

But whenever there is no "Dates_Log_In" in the collection it would run but doesn't display any kind of data.

this is the class that I use for displaying all data in the RecyclerView

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);

    }
}

Attendance 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);
    }

}

And this is where I pass the data and it should display the "Dates_Log_In" to a ListView (not quiet sure if this is the right choice)

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();
            }
        });

During the test run the error gives as it follows

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$1.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$1.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)

and in the logcat this shows

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

This is the rules I set for the database.

{
  "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,
        }
    }
  }
}

I kinda know while fetching the data from the firebase because i didnt include the date on the Attendance.class thats why it is giving a null value (just my hunch). So I tried including it but that also didnt work out for me. Im kinda guessing that there is something wrong on how i call the firebase? I just started just a few days ago and doing this for my project.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Euxicius
  • 47
  • 9
  • The error cause clear that it fails to convert arraylist to string. You should be specific about where/when do you get this error? – Odai A. Ali May 05 '22 at 15:08
  • The error cause is clear which is about failing to convert arraylist to string. You should be specific about where/when do you get this error? I can see that you are newbie to Android programming. You should learn how to use Recyclerview from Android developer Documentation https://developer.android.com/guide/topics/ui/layout/recyclerview?gclsrc=aw.ds&gclid=EAIaIQobChMIzaPRltLI9wIVyo1oCR2l8gEFEAAYASAAEgINl_D_BwE . I would also suggest that you use Firestore firebase instead of FirebaseDatabase, it's much easier to use and structure your data model – Odai A. Ali May 05 '22 at 15:16

1 Answers1

1

This makes no sense:

Log.i("Dates_Log_In", dataSnapshot.getValue(String.class));
Date = dataSnapshot.getValue(date.class);

The dataSnapshot can be a String or it can be a date, but it can never be both at the same time. That means at least one of these lines will always fail.


Since you are reading this path:

mRef = FirebaseDatabase.getInstance().getReference("Users").child(id);

So you are reading from /Users/$id, which as far as I can tell contains the data for a single user. That means you don't need to loop over snapshot.getChildren in your onDataChange, since the snapshot already contains just the data for that single user.

Then there's the matter of data under there, which is hard to determine without seeing your actual JSON. The safest I can recommend is to just let Firebase figure it out, and call getValue() without a type.

mRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        Map<String, object> values = dataSnapshot.getValue();
        ...
    }

Most likely you'll get back a Map<String, Object> from that, which you can then show with something like this: How to print all key and values from HashMap in Android?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807