1

I'm new to firebase database and firebase in general and I encountered a little issue while trying to work with it.

I am using the following JSON code I imported from firebase console, originally I just created a database structure in firebase console then downloaded the JSON code, and it is as follows:

{
  "rides" : {
    "arrive" : "kech",
    "depart" : "agadir",
    "detail" : "0,1",
    "msg" : false,
    "phone" : true,
    "price" : 15,
    "profile_id" : 0,
    "spots" : 3,
    "timedate" : "11/12/2017 11:15",
    "vocal_id" : 0
  }
}

The object i want to fetch is named Ride.java:

public class Ride {
    private String arrive;
    private String depart;
    private String detail;
    private boolean msg;
    private boolean phone;
    private int price;
    private int profile_id;
    private int spots;
    private String timedate;
    private int vocal_id;

    public Ride() {}

    // public getters (I created them I just didn't post it all to make the post shorter)
}

To listen to my database reference I'm using the following code:

FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference ref = database.getReference("rides").child("0"); // 0 is the ride id

        ref.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){
                    Ride ride = singleSnapshot.getValue(Ride.class);
                    rides.add(ride); // list of rides used later in a listadapter
                }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.e(TAG, "onCancelled", databaseError.toException());
            }
        });

I'm trying to fetch a single ride from firebase db and show it in my app. In firebase console it has the url: https://myapp.firebaseio.com/rides/0 (the second ride has id 1 and so on). What is the best practice to grab all rides and from each ride access its attributes?

Edit: When I remove .child("0") I do not get any errors but nothing appears in my listView. Apparently rides.add(ride) doesn't take place for some reason.

I tested it by adding a simple instance of Ride outside the addListenerForSingleValueEvent() method, it works fine.

I also tried changing the listener to addValueEventListener(), same result..

Edit2: I get an error message when I try to retrieve Integers from my database.

I tried this in my database listener:

public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
                    int price = (int) singleSnapshot.child("price").getValue(); //  error takes place here
                    Log.d("FirebaseDb", String.valueOf(price));
                }
            }

The result is this error: (with all ints)

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
    at com.ride.ive.anas.iveride.Fragments.RidesFragment$1.onDataChange(RidesFragment.java:96)

But when I retrieve a String or a Boolean it works fine, as in:

String arrive = (String) singleSnapshot.child("arrive").getValue();

Or Boolean usePhone = (Boolean) singleSnapshot.child("phone").getValue();

Edit3: Here is the RidesFragment.java file upon request by @Prodigy. In which I have a ListView where I try to show all Ride instances stored in my firebase database.

public class RidesFragment extends Fragment {

    ListView list;
    RidesAdapter2 ridesAdapter;
    List<Ride> rides;
    Ride ride;

    List<RidePojo> filteredRides;
    LinearLayout layoutFilter;
    boolean filtersVisible = false;
    boolean searchDone = false;

    String userNumber;

    public RidesFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_rides, container, false);
        getActivity().setTitle("Search for a ride:");

        // filter action button stuff
        setHasOptionsMenu(true);
        layoutFilter = rootView.findViewById(R.id.ll_filter_screen);

        /*FragmentManager fm = getActivity().getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);*/

        ridesAdapter = new RidesAdapter2(getContext(), rides);


        Bundle arguments = getArguments();
        list = rootView.findViewById(R.id.rides_list);
        rides = new ArrayList<>();

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference ref = database.getReference("rides");

        ref.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
                    Ride ride = singleSnapshot.getValue(Ride.class);
                    rides.add(ride);
                    ridesAdapter.notifyDataSetChanged();
                    Log.d("FbDatabase", singleSnapshot.toString());
                }

            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.e(TAG, "onCancelled", databaseError.toException());
            }
        });

        rides.add(ride);

        // In case the rides ArrayList is not empty another fragment appears for no rides criteria
        if(rides.isEmpty()) {
            rootView = inflater.inflate(R.layout.fragment_empty, container, false);
            Button rideButton = rootView.findViewById(R.id.btn_post_ride);
            Button requestButton = rootView.findViewById(R.id.btn_post_request);

            rideButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    launchFragment(new OfferRideFragment(), getActivity());
                }
            });

            requestButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    launchFragment(new RequestFragment(), getActivity());
                }
            });

        }
        else {
            list.setAdapter(ridesAdapter);

        }
        return rootView;
    }

    protected void launchFragment(Fragment f, FragmentActivity a) {
        android.support.v4.app.FragmentTransaction fragmentTransaction =
                a.getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, f);
        fragmentTransaction.commit();
    }
// ....
}
siriuseteor77
  • 1,004
  • 2
  • 12
  • 30

1 Answers1

1

Firebase database naming convention is more like naming file path for example to access rides you use .child("rides") while for arrive it will be .child("rides").child("arrive") or (rides/arrives)

From the firebase link you posted I can see you have a node rides with a child node 0 etc.... But from the json you posted cant see node "0"and this will surely throw an error.

The correct Json should be 
{
  "rides" : {
   "0": {
    "arrive" : "kech",
    "depart" : "agadir",
    "detail" : "0,1",
    "msg" : false,
    "phone" : true,
    "price" : 15,
    "profile_id" : 0,
    "spots" : 3,
    "timedate" : "11/12/2017 11:15",
    "vocal_id" : 0
}
  }
}

This will pull out the data you need and don't forget to add notifydata change listener on tour list adapter when data is added.

See edited code below

public class RidesFragment extends Fragment {

    ListView list;
    RidesAdapter2 ridesAdapter;
    List<Ride> rides;
    Ride ride;

    List<RidePojo> filteredRides;
    LinearLayout layoutFilter;
    boolean filtersVisible = false;
    boolean searchDone = false;

    String userNumber;

    public RidesFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_rides, container, false);
        getActivity().setTitle("Search for a ride:");

        // filter action button stuff
        setHasOptionsMenu(true);
        layoutFilter = rootView.findViewById(R.id.ll_filter_screen);

        /*FragmentManager fm = getActivity().getSupportFragmentManager();
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);*/




        Bundle arguments = getArguments();
        list = rootView.findViewById(R.id.rides_list);
        rides = new ArrayList<>();
        ridesAdapter = new RidesAdapter2(getContext(), rides);
        list.setAdapter(ridesAdapter);

        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference ref = database.getReference("rides");

        ref.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot singleSnapshot: dataSnapshot.getChildren()) {
                    Ride ride = singleSnapshot.getValue(Ride.class);
                    rides.add(ride);
                    ridesAdapter.notifyDataSetChanged();
                    Log.d("FbDatabase", singleSnapshot.toString());
                }

            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.e(TAG, "onCancelled", databaseError.toException());
            }
        });

        //rides.add(ride);

        // In case the rides ArrayList is not empty another fragment appears for no rides criteria
        if(rides.isEmpty()) {
            rootView = inflater.inflate(R.layout.fragment_empty, container, false);
            Button rideButton = rootView.findViewById(R.id.btn_post_ride);
            Button requestButton = rootView.findViewById(R.id.btn_post_request);

            rideButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    launchFragment(new OfferRideFragment(), getActivity());
                }
            });

            requestButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    launchFragment(new RequestFragment(), getActivity());
                }
            });

        }

        //else {
            //list.setAdapter(ridesAdapter);

        //}
        return rootView;
    }

    protected void launchFragment(Fragment f, FragmentActivity a) {
        android.support.v4.app.FragmentTransaction fragmentTransaction =
                a.getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, f);
        fragmentTransaction.commit();
    }
// ....
}
Prodigy
  • 2,094
  • 24
  • 30
  • Works fine without errors but the `rides.add(ride)` still doesnt work... – siriuseteor77 Aug 28 '17 at 18:52
  • Add adapter.notifyDataSetChanged() after rides.add(ride) in the for loop inside valuechangelistener. Let me know if it works – Prodigy Aug 28 '17 at 19:18
  • actually I create the adapter later in the code but I initialised it at the begining and tried what you said but nothing changed. same result.. – siriuseteor77 Aug 29 '17 at 00:11
  • can you show your code, how you use adapter, listview and arraylist – Prodigy Aug 29 '17 at 00:13
  • 1
    You need to add this list.setAdapter(ridesAdapter); next to your listview decleration and remove "list.setAdapter(ridesAdapter);" from the else cause it will never be called – Prodigy Aug 29 '17 at 01:32
  • without the no rides case this is working perfectly, thank you so much. If you could help me with this little issue that would be great but your post answers my dataSnapshot problem, thanks. – siriuseteor77 Aug 29 '17 at 03:23
  • the issue left is that your code goes directly into the empty rides fragment... when i remove that `if` it i get my listView – siriuseteor77 Aug 29 '17 at 03:24
  • Don't get what you meant by "goes directly into empty rides fragment" can you tell me what you want to achieve – Prodigy Aug 29 '17 at 06:16
  • what I want to do is show the rides in a my list view if there are any in the database, but if there isn't any rides I want to show a whole other fragment with a textview, an imageview and some buttons.. – siriuseteor77 Aug 29 '17 at 14:57
  • What you need do is to create a listener where you listen for database event, you use this to check if there is data in your database. If there is you add ride fragment else add other fragment. Hope this help, if not you can lets chat – Prodigy Aug 29 '17 at 16:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/153153/discussion-between-anas-and-prodigy). – siriuseteor77 Aug 29 '17 at 16:41