java - 如何为 MVVM 模式链接 Retrofit 和 Repository/ViewModel?

标签 java android mvvm retrofit2 android-architecture-components

我在将 Retrofit 与 MVVM 架构链接起来时遇到问题。事实上,在阅读了他们只谈论用于 SQLite 本地数据库的 Room 的文档后,我搜索了相同的内容,但搜索了来自 Rest 服务器的数据。 所以,我尝试做类似的事情,但没有成功: https://proandroiddev.com/mvvm-architecture-viewmodel-and-livedata-part-1-604f50cda1

我有一个观察 ViewModel 的 Activity :

Activity 代码:

mFlightPlanViewModel = ViewModelProviders.of(this).get(FlightPlanViewModel.class);
        mFlightPlanViewModel.getFlightPlans().observe(this, (flightPlans) -> {
            Log.d(TAG, "ON_CHANGED");

            mFlightPlanAdapter.setFlightPlans(flightPlans);
        });

View 模型:

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

它使用这个接口(interface):

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?

最佳答案

嘿,凯文,只是对您的代码进行了一个小小的更改。从您的存储库返回 LiveData,而不是 MutableLiveData :

public LiveData<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.postValue(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.postValue(flightPlans);
            Log.d(TAG, t.getMessage());
        }
    });

    return data;
}

关于java - 如何为 MVVM 模式链接 Retrofit 和 Repository/ViewModel?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55884618/

相关文章:

java - Nutch 不会解析整个网站,只会解析第一个 URL

java - 合并两个非常相似的方法

java - JSP调用servlet并转义注释

安卓 MVVM : How to subscribe to a network call by LiveData in ViewModel

android - Android-具有LiveData的DataBinding保留旧值

mvvm - 使用异步访问 UI 线程/使用 Mvvm 等待

java - 如果语句奇怪地不能正常工作......无法弄清楚

android - 如何在有空间的情况下执行繁重的数据库操作?

android - ionic - svg 不出现

android - 根据 int 值更改 textswitcher/viewswitcher 的 textColor?