3
\$\begingroup\$

My goal is to get the location when the app starts, and if the user navigates away and comes back, to receive one location update and that's it. I am worried about removing the observer in the getLocationUpdates method.

BoundLocationManager.class

public class BoundLocationManager extends LiveData<Location> {

    private static BoundLocationManager instance;
    private FusedLocationProviderClient mFusedLocationClient;
    private LocationRequest mLocationRequest;

    public static BoundLocationManager getInstance(Context appContext) {
        if (instance == null) {
            instance = new BoundLocationManager(appContext);
        }
        return instance;
    }

    private BoundLocationManager(final Context appContext) {
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(appContext);
        createLocationRequest();
        mFusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
            @Override
            public void onComplete(@NonNull Task<Location> task) {
                if(task.isSuccessful() && task.getResult() != null) {
                    setValue(task.getResult());
                } else {
                    mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, null);
                }
            }
        });

    }

    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    LocationCallback mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            for (Location location : locationResult.getLocations()) {
                if (location != null)
                    setValue(location);
            }
        }
    };

    @Override
    protected void onInactive() {
        super.onInactive();
        if (mLocationCallback != null)
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
    }

}

WeatherFragment.class

private void getLocationUpdates() {
        BoundLocationManager.getInstance(getActivity().getApplicationContext()).observe(this, new Observer<Location>() {
            @Override
            public void onChanged(@Nullable Location location) {
                if (location != null) {
                    getWeather(location.getLatitude(), location.getLongitude());
                    getAddress(location.getLatitude(), location.getLongitude());
                    BoundLocationManager.getInstance(getActivity().getApplicationContext()).removeObserver(this);
                } else
                    Toast.makeText(getActivity(), "Location is null", Toast.LENGTH_SHORT).show();
            }
        });
    }

And finally I use it:

@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
            requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION);
        else {
            getLocationUpdates();
        }
    }
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Welcome to Code Review! I hope you get great answers. \$\endgroup\$
    – Phrancis
    Mar 20, 2018 at 0:31
  • \$\begingroup\$ @Phrancis Thank you very much for the encouragement! Have a great day! \$\endgroup\$
    – Suleyman
    Mar 20, 2018 at 1:00

1 Answer 1

5
\$\begingroup\$

Let me explain how to work with LiveData - ViewModel and Activity.

Right now your BoundLocationManager looks good. I'd recommend not to make it's singleton. And also not consuming it directly in your UI (in this case WeatherFragment) code.

It's highly recommended to keep LiveData in ViewModel and your ViewModel will provide it the UI.

Also if you use LiveData, then never worry about removing the observer. It's done automatically for you.

Let me know if you still have some queries.

\$\endgroup\$
2
  • \$\begingroup\$ You save me everywhere :) everything is perfectly clear, but, I remove the observer because I only want to receive one update from the location service, otherwise everytime the user moves the location will be updated. That is why I unregister the observer straight away. \$\endgroup\$
    – Suleyman
    Mar 25, 2018 at 16:10
  • \$\begingroup\$ Haha no problem at all. Take a look at github.com/googlesamples/android-architecture/blob/…, I think it's useful if you want to receive one update. \$\endgroup\$ Mar 25, 2018 at 16:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.