1

I need to share two variables between two repositories. I've already tried many different solutions, but none worked. In short: first repository contain user last known location (geographical latitude and longitude) second repository calling the api with specified endpoints, such as geographical latitude and longitude. The thing is I consantly receiving those values with equal to 0,0. Could you give me some hint how I should do it? One thing that I observerd is that, the whole program runs immediatly, while the location repository need a couple of seconds to actuall get the latitude and longitude. So the program just constantly calling the api with endpoints equal to 0,0 as I meantioned above.

Location repository

    public class LocationRepository {

    private double mLatitude, mLongitude;
    
    public void test(Application application) {
        FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(application.getApplicationContext());
        {
            if (ContextCompat.checkSelfPermission(
                    application.getApplicationContext(), Manifest.permission.INTERNET) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(application.getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(application.getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

                client.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
                    @Override
                    public void onSuccess(Location location) {
                        mLongitude = location.getLongitude();
                        mLatitude = location.getLatitude();
                    }
                });
            }
        }
    }
}

Forecast repository

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

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());
        }
        data.setValue(response.body());
    }
    @Override
    public void onFailure(Call<ForecastModel> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t.getMessage());
    }
});
return data;
}

ViewModel

private ForecastRepository mForecastRepository;
private LocationRepository mLocationRepository;

private MutableLiveData<ForecastModel> mForecastData;

public ForecastViewModel(@NonNull Application application) {
    super(application);
    mLocationRepository = new LocationRepository();
    mLocationRepository.test(application);

    mForecastRepository = new ForecastRepository();
    mForecastData = mForecastRepository.testCall();
}

1 Answers1

1

You can use two livadata in ViewModel and Transformation.switchMap() to track changes. Everytime mLocationData changes mForcastData will update too. If you don't know how switchMap works you can check it How and where to use Transformations.switchMap? .

Change your ViewModel and LocationRepository like this.

ViewModel

public class ForecastViewModel extends AndroidViewModel {

    private ForcastRepository mForecastRepository;
    private LocationRepostiory mLocationRepository;

    private LiveData<ForecastModel> mForecastData;
    private LiveData<LocationModel> mLocationData;

    public ForecastViewModel(@NonNull Application application) {
        super(application);
        mLocationRepository = new LocationRepostiory();
        mLocationRepository.test(application);
        mLocationData = mLocationRepository.getMutableLiveData();
        mForecastRepository = new ForcastRepository();

        mForecastData = Transformations.switchMap(mLocationData, location->
                mForecastRepository.testCall(location.getLatitude(), location.getLongitude()));
    }

    public LiveData<ForecastModel> getmForecastData() {
        return mForecastData;
    }
}

LocationRepository

class LocationRepostiory {

private LocationModel mLocation;
private MutableLiveData<LocationModel> mutableLiveData = new MutableLiveData();

public void test(Application application) {
    FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(application.getApplicationContext());
    {
        if (ContextCompat.checkSelfPermission(
                application.getApplicationContext(), Manifest.permission.INTERNET) == PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(application.getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(application.getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

            client.getLastLocation().addOnSuccessListener(location -> {
                mLocation = new LocationModel(location.getLongitude(),location.getLatitude());
                mutableLiveData.setValue(mLocation);
            });
        }
    }
}

public MutableLiveData<LocationModel> getMutableLiveData() {
    return mutableLiveData;
}
}

Forcast Repository

public MutableLiveData<ForecastModel> testCall(double mLatitude, double mLongitude ) {
MutableLiveData<ForecastModel> data = new MutableLiveData<>();

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());
        }
        data.setValue(response.body());
    }
    @Override
    public void onFailure(Call<ForecastModel> call, Throwable t) {
        Log.i(TAG, "onFailure: " + t.getMessage());
    }
});
return data;
}

LocationModel

class LocationModel {
    private Double longitude, latitude;

    public LocationModel(Double longitude, Double latitude) {
        this.longitude = longitude;
        this.latitude = latitude;
    }

    public Double getLongitude() {
        return longitude;
    }

    public Double getLatitude() {
        return latitude;
    }
}

If you don't want to make an extra LocationModel class then you can send your location data as List or Arraylist as well. Just I prefer this one.

Edited: There were some mistakes that I have corrected. Now code is working. Logcat from testCall() Method in ForcastRepository D/TAG: testCall: 90.3993212,23.7793183

Rafiul
  • 1,560
  • 7
  • 19
  • This wouldn't work. LocationRepository will return location object which at that point would be null. mLocation's value would remain null - it wont update when location is recieved. – Tayyab Mazhar Jan 05 '21 at 17:55
  • Location wasn't null but there were some errors in the code. Now I have edited. please check again. – Rafiul Jan 05 '21 at 20:30
  • Everything works fine for now. The switchMap is pretty new topic for me. Thank you for help, much appreciate it. – BackToDream Jan 06 '21 at 12:01