MVVM – where should I call for user location?

Tags: , , ,



currently, I’m building an app which will show for the user recent forecast. For make an api call, I have to provide longitude and latitude as parameter. For now, I have written some code about getting langitude, and longitude, but I don’t receive proper data. As I written those methods in MainActivity, at first, the longitude, and latitude is equal to 0.0, after about two seconds it managing to get proper data. Should I freeze app until the locationManage will get proper data, or should I call those methods somewhere else? Should I call them in repository?

Checking permissions

if (ContextCompat.checkSelfPermission(
            getApplicationContext(), Manifest.permission.INTERNET) == PackageManager.PERMISSION_GRANTED &&
            ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
            ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

    } else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(new String[]{
                    Manifest.permission.INTERNET, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION
                    
            }, 1);
        }
    }
}

onLocationChanged

@Override
public void onLocationChanged(@NonNull Location location) {
    mLatitude = location.getLatitude();
    mLongitude = location.getLongitude();

    Log.i(TAG, "onLocationChanged: "+mLatitude+" "+mLongitude);
}

In repository

public static double mLatitude = MainActivity.mLatitude;
public static double mLongitude = MainActivity.mLongitude;

public ForecastRepository(){
    mApi = RetrofitBuilder.makeCall();
}

public MutableLiveData<ForecastModel> testCall() {
    MutableLiveData<ForecastModel> data = new MutableLiveData<>();

    //TODO temporary values such as latitude/longitude in api call
    mApi.test(mLatitude, mLongitude, "metric", API_KEY).enqueue(new Callback<ForecastModel>() {
        @Override
        public void onResponse(Call<ForecastModel> call, Response<ForecastModel> response) {
            if (!response.isSuccessful()){
                Log.i(TAG, "onResponse: "+ response.code());
            }
            Log.i(TAG, "onResponse: successful "+mLatitude+" "+mLongitude);
            data.setValue(response.body());
        }

        @Override
        public void onFailure(Call<ForecastModel> call, Throwable t) {
            Log.i(TAG, "onFailure: "+t.getMessage());
        }
    });
    return data;
}
}

Answer

The correct way would be to have a LocationRepository where you do all fetching in a background thread of the device location.

Create a MutableLiveData in ViewModel where you will assign the location.

Then update its value using postValue() or setValue().

Write a public getter for this MutableLiveData. This repository will be your location API.

Then your ViewModel should call the method of your repository and assign its result to a LiveData variable of the ViewModel.

Then in your Activity observe the liveData of your ViewModel.

And make your API Call.



Source: stackoverflow