简体   繁体   中英

LiveData, MVVM and Repository Pattern

Is this a good approach or I've just found a nasty workaround?

I'm using MediatorLiveData class because seems useful to update the source of a LiveData object.

I mean, the majority of tutorials that I've found on internet just use Livedata or MutableLivedata without a dynamic source, in example:

fun search(/*no input params*/): Call<List<Person>>

But in my case, I have the following web service that performs a search by name:

interface APIServidor {
    @GET("search")
    fun search(@Query("name") name: String): Call<List<Person>>

}

public class PeopleRepository {


    public LiveData<List<Person>> search(String name){

        final MutableLiveData<List<Person>> apiResponse = new MutableLiveData<>();
        Call<List<Person>> call = RetrofitService.Companion.getInstance().getApiServer().search(name);
        call.enqueue(new Callback<List<Person>>() {
            @Override
            public void onResponse(@NonNull Call<List<Person>> call, @NonNull Response<List<Person>> response) {
                if (response.isSuccessful()) {
                    apiResponse.postValue(response.body());
                }
            }

            @Override
            public void onFailure(@NonNull Call<List<Person>> call, @NonNull Throwable t) {
                apiResponse.postValue(null);
            }
        });

        return apiResponse;
    }
}

Then in the viewmodel class I'm adding source per new request.

public class SearchViewModel extends ViewModel {

    private MediatorLiveData<List<Person>> mApiResponse;
    private PeopleRepository mApiRepo;

    public SearchViewModel() {
        mApiResponse = new MediatorLiveData<>();
        mApiRepo = new PeopleRepository();
    }

    public LiveData<List<Person>> getPlayers() {
        return mApiResponse;
    }

    public void performSearch(String name){
        mApiResponse.addSource(mApiRepo.search(name), new Observer<List<Person>>() {
            @Override
            public void onChanged(List<Person> apiResponse)            {
                mApiResponse.setValue(apiResponse);
            }
        });
    }
}

Activity

bt_search.setOnClickListener {
    val player_name = et_player.text.toString()
    viewModel.performSearch(player_name)
}

Project scope

I'm in a personal project

Goals

Use MVVM + Live data + Repository pattern

Problem

I've only found tutorials with a simple approach: observe a LiveData object that access to a repository object and fetch data only once.

In example: Fetch all people ( select * from people ) from web service.

My case: Fetch people that mach a name ( select * from people where name=? ) from web service.

https://medium.com/@elye.project/kotlin-and-retrofit-2-tutorial-with-working-codes-333a4422a890 https://medium.com/@sriramr083/error-handling-in-retrofit2-in-mvvm-repository-pattern-a9c13c8f3995

Doubts

Is a good idea use MediatorLiveData class to merge all requests took from user input?

Should I use MutableLiveData and change the repository class and use a custom clousure?

Is there a better approach?

I was using this pattern with MediatorLiveData as well, but it forms an issue. From the user perspective it seems to function just fine, but one problem here is that every time you call performSearch() the repository creates a new LiveData object which is additionally added to MediatorLiveData via addSource() .

An idea might be to have the repository create the MutableLiveData object only once and on consecutive call just update it's value. So fe MutableLiveData<List<Person>> apiResponse; would be a non initialized private field that gets initialized in the search() method.

Eg. if (apiResponse == null) apiResponse = new MutableLiveData();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM