skip to Main Content

I am creating a app that will read data from firebase and display it on a map. The app keeps crashing because there are hell lot of records to retrieve from the database. I need a way with which I get only the latest node data and not the entire data snapshot.

MainActivity.java:

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback{
    FirebaseDatabase db;
    DatabaseReference dbReference;
    TextView speed_disp;
    public List<LatLng> polygon;

    public double getLatitude() {
        return latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    private GoogleMap googleMap;

    private double latitude=19.10815888216128;
    private double longitude=72.83706388922495;

    public void setCord(String lat,String lon){
        this.latitude=Double.parseDouble(lat);
        this.longitude=Double.parseDouble(lon);
    }




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        polygon = new PolyList<>(10);
        setContentView(R.layout.activity_main);

        db = FirebaseDatabase.getInstance();
        speed_disp=findViewById(R.id.speed);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);


//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//            requestPermissions(new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, 1000);
//        }

        try{
            dbReference = db.getReference("Data");
            dbReference.addValueEventListener(new ValueEventListener() {



                @Override
                public void onDataChange(@NonNull DataSnapshot datasnapshot) {
                    Log.d("Lat",datasnapshot.getValue().toString());
                    for (DataSnapshot snapshot: datasnapshot.getChildren()) {

                        String latitude = snapshot.child("lat").getValue(String.class);
                        String longitude = snapshot.child("lon").getValue(String.class);
                        String speed = snapshot.child("speed").getValue(String.class);

                        speed_disp.setText(speed);
                        setCord(latitude,longitude);
                        googleMap.clear();


                        double lat = getLatitude();
                        double lon = getLongitude();

                        LatLng current=new LatLng(lat,lon);


                        // Add marker position to polygon list
                        polygon.add(current);

                        // Draw polyline
                        if (polygon.size() >= 2) {
                            PolylineOptions polylineOptions = new PolylineOptions()
                                    .addAll(polygon)
                                    .width(5)
                                    .color(Color.RED);
                            googleMap.addPolyline(polylineOptions);
                        }

                        googleMap.addMarker(new MarkerOptions().position(current).title("Current Location"));

                        // Move camera to marker
                        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(current,20 ));

                    }


                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {
                    Toast.makeText(MainActivity.this,"Read error!!!",Toast.LENGTH_SHORT).show();
                }


            });
        }catch (Error e) {
            Toast.makeText(MainActivity.this, "Read module error", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        this.googleMap=googleMap;
        googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

//        LatLng current=new LatLng(19.10815888216128,72.83706388922495);
//        this.googleMap.addMarker(new MarkerOptions().position(current).title("Dub maro pls!!"));
//        this.googleMap.moveCamera(CameraUpdateFactory.newLatLng(current));



    }


}

Firebase:

The keys are uniquely generated

I want to read only the newest node from the real-time database. Also, I would appreciate if you guys could improve my code.

2

Answers


  1. It looks like you use push to add children to Data, which means you can use this approach to get only the most recently added child node:

    dbReference = db.getReference("Data");
    Query query = dbReference.orderByKey().limitToLast(1);
    query.addValueEventListener(new ValueEventListener() {
        ...
    

    Also see the Firebase documentation on:

    Login or Signup to reply.
  2. To read only the newest node from the real-time database in Firebase, you can utilize the limitToLast() method in your database reference query. This method ensures that only the specified number of child nodes, starting from the last one, are retrieved. In your case, you can set the limit to 1 to get only the latest node.

    Here’s how you can modify your dbReference to achieve this:

    ```java code
    dbReference = db.getReference("Data").orderByKey().limitToLast(1);
    ```

    This modification ensures that only the latest node will be retrieved, thus reducing the amount of data processed and potentially improving the performance of your app.

    Regarding your code, there are some improvements that can be made for better efficiency and readability:

    1. Use childEventListener instead of valueEventListener: Since you only need to listen for the latest node, ChildEventListener is more suitable as it listens for changes at the child level.

    2. Move Google Map related code out of the loop: You don’t need to clear the map and move the camera for each data snapshot received. Instead, you can move these operations outside the loop to improve efficiency.

    3. Handle potential null values: Ensure that you handle cases where snapshot.child("lat"), snapshot.child("lon"), or snapshot.child("speed") return null values.

    4. Use appropriate data types: Consider using appropriate data types for latitude, longitude, and speed instead of storing them as strings.

    Here’s an improved version of your code:

    ```java code
    dbReference = db.getReference("Data").orderByKey().limitToLast(1);
    dbReference.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
            String latitude = snapshot.child("lat").getValue(String.class);
            String longitude = snapshot.child("lon").getValue(String.class);
            String speed = snapshot.child("speed").getValue(String.class);
    
            if (latitude != null && longitude != null && speed != null) {
                speed_disp.setText(speed);
                setCord(latitude, longitude);
    
                double lat = getLatitude();
                double lon = getLongitude();
                LatLng current = new LatLng(lat, lon);
    
                // Add marker position to polygon list
                polygon.add(current);
    
                // Draw polyline
                if (polygon.size() >= 2) {
                    PolylineOptions polylineOptions = new PolylineOptions()
                            .addAll(polygon)
                            .width(5)
                            .color(Color.RED);
                    googleMap.addPolyline(polylineOptions);
                }
    
                googleMap.clear();
                googleMap.addMarker(new MarkerOptions().position(current).title("Current Location"));
                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(current, 20));
            }
        }
    
        @Override
        public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {}
    
        @Override
        public void onChildRemoved(@NonNull DataSnapshot snapshot) {}
    
        @Override
        public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {}
    
        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            Toast.makeText(MainActivity.this, "Read error!!!", Toast.LENGTH_SHORT).show();
        }
    });
    ```

    This version should be more efficient and handle potential null values more gracefully. Make sure to replace the existing addValueEventListener with addChildEventListener.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search