Getting location using LiveData and FusedLocationProviderClient 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&lt;Location&gt; {

    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&lt;Location&gt;() {
            @Override
            public void onComplete(@NonNull Task&lt;Location&gt; task) {
                if(task.isSuccessful() &amp;&amp; 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&lt;Location&gt;() {
            @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();
        }
    }
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.