问题描述
我添加了一些代码以使我的问题更清楚.
I've added some code to make my question more clear.
改造界面:
public interface JsonPlaceHolderAPI {
public static final String BASE_URL = "https://jsonplaceholder.typicode.com/";
@GET("todos/{number}")
Call<ResponseBody> getJsonResponse(@Path("number") String number);
}
存储库:--> fetchResponse() 将 Viewmodel 的 MutableLiveData 作为参数,并使用它更新其值,然后触发 View 更改其 UI.
The repository: --> fetchResponse() takes Viewmodel's MutableLiveData as parameter and uses it to update its value and then trigger View to change its UI.
public class Repository {
private final JsonPlaceHolderAPI api;
public Repository() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.build();
api = retrofit.create(JsonPlaceHolderAPI.class);
}
public void fetchResponse(String number, final MutableLiveData<CharSequence> mld){
final MutableLiveData<CharSequence> ml = new MutableLiveData<>();
api.getJsonResponse(number).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
mld.setValue(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {}
});
}
}
视图模型:
public class MainActivityViewModel extends AndroidViewModel {
MutableLiveData<CharSequence> response = new MutableLiveData<>();
Repository repository;
public MainActivityViewModel(@NonNull Application application) {
super(application);
repository = new Repository();
}
public void fetchData(String number) {
response.setValue("Loading data");
repository.fetchResponse(number, response);
}
public LiveData<? extends CharSequence> getLiveData() {
return response;
}
}
视图:
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewModel = ViewModelProviders.of(this).get(MainActivityViewModel.class);
initViews();
viewModel.getLiveData().observe(this, new Observer<CharSequence>() {
@Override
public void onChanged(CharSequence charSequence) {
if (charSequence != null) {
txt.setText(charSequence);
}
}
});
}
...
我不确定是否应该将 MutableLiveData 从 viewModel 传递到存储库.
I am not sure if I should pass the MutableLiveData from the viewModel to the Repository.
是否有任何推荐的方法可以让 viewModel 知道数据已准备好从 Repository 发布??
Is there any recommended way to let viewModel know that data is ready to be published from Repository??
我已经阅读了很多问题和文章,但我仍然不明白.如果有人向我解释实现它的好方法,我会很高兴!
I have read a lot of questions and articles and still I don't get it. I would love if somebody explain to me a nice way to achieve it!
推荐答案
Api
public interface TodoApi {
@GET("todos/")
Call<List<Todo>> getTodos();
@GET("todos/{id}")
Call<Todo> getTodo(@Path("id") long id);
}
存储库
public class TodoRepository {
private static final String TAG = "TodoRepository";
private static final TodoRepository ourInstance = new TodoRepository();
private TodoApi api;
private MutableLiveData<List<Todo>> todoListLiveData = new MutableLiveData<>();
private MutableLiveData<Todo> todoLiveData = new MutableLiveData<>();
public static TodoRepository getInstance() {
return ourInstance;
}
private TodoRepository() {
api = ApiBuilder.create(TodoApi.class);
}
public LiveData<List<Todo>> getTodos() {
api.getTodos().enqueue(new Callback<List<Todo>>() {
@Override
public void onResponse(@NonNull Call<List<Todo>> call, @NonNull Response<List<Todo>> response) {
todoListLiveData.setValue(response.body());
}
@Override
public void onFailure(@NonNull Call<List<Todo>> call, @NonNull Throwable t) {
Log.d(TAG, "onFailure: failed to fetch todo list from server");
}
});
return todoListLiveData;
}
public LiveData<Todo> getTodo(long id) {
api.getTodo(id).enqueue(new Callback<Todo>() {
@Override
public void onResponse(@NonNull Call<Todo> call, @NonNull Response<Todo> response) {
todoLiveData.setValue(response.body());
}
@Override
public void onFailure(@NonNull Call<Todo> call, @NonNull Throwable t) {
Log.d(TAG, "onFailure: failed to get todo");
}
});
return todoLiveData;
}
}
视图模型
public class MainActivityViewModel extends ViewModel {
private static final String TAG = "MainActivityViewModel";
private TodoRepository repository = TodoRepository.getInstance();
private MutableLiveData<Boolean> isLoading = new MutableLiveData<>();
private LiveData<List<Todo>> todoLiveData;
public MainActivityViewModel() {
super();
isLoading.setValue(true);
todoLiveData = repository.getTodos();
}
@Override
protected void onCleared() {
super.onCleared();
}
public MutableLiveData<Boolean> getIsLoading() {
return isLoading;
}
public LiveData<List<Todo>> getTodoLiveData() {
return todoLiveData;
}
}
查看
@Override
View
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
todoListRecyclerView = findViewById(R.id.todo_recycler_view);
loadingIndicator = findViewById(R.id.todo_loading_indicator);
mViewModel = ViewModelProviders.of(this).get(MainActivityViewModel.class);
getSupportActionBar().setTitle("Todos");
mViewModel.getIsLoading().observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean isLoading) {
if (isLoading) loadingIndicator.setVisibility(View.VISIBLE);
else loadingIndicator.setVisibility(View.GONE);
}
});
mViewModel.getTodoLiveData().observe(this, new Observer<List<Todo>>() {
@Override
public void onChanged(List<Todo> todos) {
mViewModel.getIsLoading().postValue(false);
initRecyclerView(todos);
}
});
}
完整样本
https://github.com/AnvarNazar/RetrofitTypicodeApiExample
这篇关于如何将 ViewModel 与 Repository 连接起来,以便将数据传播到 View(MVVM、Livedata)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!