简体   繁体   English

如何将ViewModel与存储库连接,以便将数据传播到视图(MVVM,Livedata)

[英]How to connect ViewModel with Repository so that data is propagated to the View (MVVM, Livedata)

I've added some code to make my question more clear. 我添加了一些代码以使我的问题更加清楚。

Retrofit interface: 改造界面:

public interface JsonPlaceHolderAPI {
    public static final String BASE_URL = "https://jsonplaceholder.typicode.com/";

    @GET("todos/{number}")
    Call<ResponseBody> getJsonResponse(@Path("number") String number);
}

The repository: --> fetchResponse() takes Viewmodel's MutableLiveData as parameter and uses it to update its value and then trigger View to change its UI. 存储库:-> fetchResponse()将Viewmodel的MutableLiveData作为参数,并使用它来更新其值,然后触发View来更改其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) {}
        });
    }
}

The viewModel: viewModel:

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

The View: 风景:

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


    }
    ...

I am not sure if I should pass the MutableLiveData from the viewModel to the Repository. 我不确定是否应该将MutableLiveData从viewModel传递到存储库。

Is there any recommended way to let viewModel know that data is ready to be published from Repository?? 有什么建议的方法可以让viewModel知道可以从存储库发布数据了吗?

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

Respository 储存库

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

ViewModel 视图模型

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

View 视图

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

For full sample 完整样本

https://github.com/AnvarNazar/RetrofitTypicodeApiExample https://github.com/AnvarNazar/RetrofitTypicodeApiExample

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何观察viewmodel中的数据 LiveData + Courotine + MVVM + Retrofit - How to observe data in viewmodel LiveData + Courotine + MVVM + Retrofit MVVM 中视图和 ViewModel 之间的通信与 LiveData - Communication between view and ViewModel in MVVM with LiveData MVVM:复杂的View / ViewModel-&gt;多个LiveData对象? - MVVM: Complex View/ViewModel -> Multiple LiveData objects? 在没有 LiveData 的情况下将数据从 Repository 返回到 ViewModel - Return data from Repository to ViewModel without LiveData MVVM 与 Retrofit - 如何处理存储库中的大量 LiveData? - MVVM with Retrofit - How to deal with a lot of LiveData in Repository? ViewModel中的LiveData如何使用转换观察存储库中的Livedata? - How can LiveData in ViewModel observe the Livedata in Repository using Transformations? 如何正确地在MVVM中将改造数据从存储库获取到视图模型? - How to correctly in MVVM get the retrofit data from the repository to the viewmodel? LiveData,MVVM和存储库模式 - LiveData, MVVM and Repository Pattern MVVM:尝试使用 LiveData 加载数据时,ViewModel 为空 - MVVM: ViewModel is null when trying to load data using LiveData Android MVVM/Repository 如何强制 LiveData 从存储库更新? - Android MVVM/Repository how to force LiveData to update from repository?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM