У меня проблемы с подключением Retrofit к архитектуре MVVM.Действительно, после прочтения документации, в которой говорится только о Room, предназначенной для локальной базы данных SQLite, я искал то же самое, но не данные, полученные с сервера отдыха.Итак, я попытался сделать что-то похожее на это, и это не сработало: https://proandroiddev.com/mvvm-architecture-viewmodel-and-livedata-part-1-604f50cda1
У меня есть активность, которая наблюдает за ViewModel:
Код активности:
mFlightPlanViewModel = ViewModelProviders.of(this).get(FlightPlanViewModel.class);
mFlightPlanViewModel.getFlightPlans().observe(this, (flightPlans) -> {
Log.d(TAG, "ON_CHANGED");
mFlightPlanAdapter.setFlightPlans(flightPlans);
});
ViewModel:
public class FlightPlanViewModel extends AndroidViewModel {
private static final String TAG = "FlightPlanViewModel";
private LiveData<List<FlightPlan>> mFlightPlans;
private FlightPlanRepository mFlightPlanRepository;
public FlightPlanViewModel(@NonNull Application application) {
super(application);
Log.d(TAG, "CONSTRUCTOR");
mFlightPlanRepository = FlightPlanRepository.getInstance();
mFlightPlans = mFlightPlanRepository.getFlightPlans();
}
public LiveData<List<FlightPlan>> getFlightPlans() {
Log.d(TAG, "GET_FLIGHT_PLANS");
return mFlightPlans;
}
}
ViewModel отвечает репозиторию, который использует шаблон синглтона:
public class FlightPlanRepository {
private static final String TAG = "FlightPlanRepository";
private static FlightPlanRepository instance;
private RestApi mRestApi;
private FlightPlanRepository() {
Log.d(TAG, "CONSTRUCTOR");
mRestApi = RestDao.getRestDao();
}
public static FlightPlanRepository getInstance() {
Log.d(TAG, "GET_INSTANCE");
if (instance == null) {
instance = new FlightPlanRepository();
}
return instance;
}
public MutableLiveData<List<FlightPlan>> getFlightPlans() {
Log.d(TAG, "GET_FLIGHT_PLANS");
final MutableLiveData<List<FlightPlan>> data = new MutableLiveData<>();
mRestApi.getFlightPlanList().enqueue(new Callback<List<FlightPlan>>() {
@Override
public void onResponse(Call<List<FlightPlan>> call, Response<List<FlightPlan>> response) {
if (response.code() == 200) {
List<FlightPlan> temp = response.body();
for (FlightPlan flightPlan : temp) {
Log.d(TAG + "res", flightPlan.toString());
}
data.setValue(response.body());
Log.d(TAG + "res", response.toString());
}
}
@Override
public void onFailure(Call<List<FlightPlan>> call, Throwable t) {
List<FlightPlan> flightPlans = new ArrayList<>();
flightPlans.add(new FlightPlan(0, "Test", 3.551, 50.52, 3.55122, 50.52625));
data.setValue(flightPlans);
Log.d(TAG, t.getMessage());
}
});
return data;
}
}
В репозитории используется экземпляр Retrofit:
public class RestDao {
private static final String BASE_URL = "http://192.168.1.78:8080";
private static Retrofit instance;
private static Retrofit getInstance() {
if (instance == null) {
instance = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return instance;
}
public static RestApi getRestDao() {
return getInstance().create(RestApi.class);
}
}
Он использует этот интерфейс:
public interface RestApi {
@GET("/plan/list")
Call<List<FlightPlan>> getFlightPlanList();
}
Часть кода, которая не работает:
public MutableLiveData<List<FlightPlan>> getFlightPlans() {
Log.d(TAG, "GET_FLIGHT_PLANS");
final MutableLiveData<List<FlightPlan>> data = new MutableLiveData<>();
mRestApi.getFlightPlanList().enqueue(new Callback<List<FlightPlan>>() {
@Override
public void onResponse(Call<List<FlightPlan>> call, Response<List<FlightPlan>> response) {
if (response.code() == 200) {
List<FlightPlan> temp = response.body();
for (FlightPlan flightPlan : temp) {
Log.d(TAG + "res", flightPlan.toString());
}
data.setValue(response.body());
Log.d(TAG + "res", response.toString());
}
}
@Override
public void onFailure(Call<List<FlightPlan>> call, Throwable t) {
List<FlightPlan> flightPlans = new ArrayList<>();
flightPlans.add(new FlightPlan(0, "Test", 3.551, 50.52, 3.55122, 50.52625));
data.setValue(flightPlans);
Log.d(TAG, t.getMessage());
}
});
return data;
}
Возвращает пустой список.Я думаю, что понимаю, почему: вызов метода enqueue () сделал запрос, который находится в другом потоке, поэтому здесь мы возвращаем данные, не ожидая результата.
Итак, мой вопрос, как связать Retrofit и мою ViewModel?