【问题标题】:I can't share variables between two repositories using mvvm我无法使用 mvvm 在两个存储库之间共享变量
【发布时间】:2021-04-11 06:04:01
【问题描述】:

我需要在两个存储库之间共享两个变量。我已经尝试了许多不同的解决方案,但都没有奏效。简而言之:第一个存储库包含用户最后已知的位置(地理纬度和经度)第二个存储库调用具有指定端点的 api,例如地理纬度和经度。问题是我不断收到等于 0,0 的值。你能给我一些提示我应该怎么做吗?我观察到的一件事是,整个程序立即运行,而位置存储库需要几秒钟才能实际获得纬度和经度。所以程序只是不断地调用端点等于 0,0 的 api,正如我上面的意思。

位置存储库

    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();
                    }
                });
            }
        }
    }
}

预测存储库

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;
}

视图模型

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();
}

【问题讨论】:

  • ForecaseRepository如何访问LocationRepositorymLatitudemLongitude变量?
  • 目前还没有。我已经删除了我试图清理代码的所有内容。我已经尝试将变量设为静态,通过方法发送这些变量,甚至作为列表。
  • 您需要使用 livedata/stateflow,并在预测存储库中观察它。
  • 我以为你无法观察存储库中的实时数据。
  • 您可以随心所欲地观察它。试着正确地构建你的代码。

标签: java android api mvvm retrofit


【解决方案1】:

您可以在 ViewModel 和 Transformation.switchMap() 中使用两个 livadata 来跟踪更改。每次 mLocationData 更改时,mForcastData 也会更新。如果您不知道 switchMap 是如何工作的,您可以查看How and where to use Transformations.switchMap?

像这样更改您的 ViewModel 和 LocationRepository。

视图模型

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;
}
}

预测存储库

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;
}

位置模型

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;
    }
}

如果您不想创建额外的 LocationModel 类,那么您也可以将位置数据作为 List 或 Arraylist 发送。只是我更喜欢这个。

已编辑:我已经纠正了一些错误。现在代码正在运行。 Logcat from testCall() Method in ForcastRepository D/TAG: testCall: 90.3993212,23.7793183

【讨论】:

  • 这行不通。 LocationRepository 将返回位置对象,该对象此时将为空。 mLocation 的值将保持为空 - 它不会在收到位置时更新。
  • Location 不为空,但代码中存在一些错误。现在我已经编辑了。请再次检查。
  • 目前一切正常。 switchMap 对我来说是一个相当新的话题。感谢您的帮助,非常感谢。
猜你喜欢
  • 1970-01-01
  • 2013-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-13
  • 2014-05-15
相关资源
最近更新 更多