Как обновить ответ сервера в пользовательском интерфейсе с помощью шаблона MVVM - PullRequest
0 голосов
/ 13 июля 2020

Я использую шаблон MVVM в своем приложении. У меня есть отдельный класс репозитория для сетевых операций. В классе репозитория я получаю ответ от сервера. Как я могу показать Toast-сообщение, отправленное с сервера в моем основном действии.

Ниже мой код:

Репозиторий. java

public class MyRepository {

MutableLiveData<List<Facts>> mutableLiveData = new MutableLiveData<>();
    
Application application;

public MyRepository(Application application) {
    this.application = application;
}

public MutableLiveData<List<Facts>> getMutableLiveData(){

    Retrofit retrofit = RetrofitClient.getInstance();
    ApiService apiService = retrofit.create(ApiService.class);

    apiService.getFacts().subscribeOn(Schedulers.io())
                         .observeOn(AndroidSchedulers.mainThread())
                         .subscribe(new Observer<List<Facts>>() {
                             @Override
                             public void onSubscribe(Disposable d) {

                             }

                             @Override
                             public void onNext(List<Facts> facts) {

                                 if(facts.size() > 0 && facts != null){

                                     mutableLiveData.setValue(facts);
                                 }
                             }

                             @Override
                             public void onError(Throwable e) {

                                 TastyToast.makeText(application,e.getMessage(),TastyToast.LENGTH_SHORT,
                                         TastyToast.ERROR).show();
                             }

                             @Override
                             public void onComplete() {

                             }
                         });

       return mutableLiveData;
  }
 }

FactsViewModel. java

public class FactsViewModel extends AndroidViewModel {

MyRepository repo;

public FactsViewModel(@NonNull Application application) {
    super(application);

    repo = new MyRepository(application);
  }

public LiveData<List<Facts>> getAllFacts(){

    return repo.getMutableLiveData();
  }
}

MainActivity. java

 private void myFacts(){

    FactsViewModel viewModel = new ViewModelProvider(this).get(FactsViewModel.class);  

    viewModel.getAllFacts().observe(this, new Observer<List<Facts>>() {
       @Override
       public void onChanged(List<Facts> facts) {

           adapter = new FactsAdapter(facts,getActivity());
           recycle.setAdapter(adapter);
       }
   });

}

Кто-нибудь, дайте мне знать, как я могу отображать всплывающие сообщения об ошибках в MainActivity. Любая помощь будет принята с благодарностью.

СПАСИБО

1 Ответ

0 голосов
/ 13 июля 2020

Чтобы реализовать это, вам сначала нужно создать класс, который имеет статус ответа, загрузка, которая выполняется до выборки данных, и там вы можете установить индикатор выполнения, чтобы он был видимым, тогда в случае успеха вы должны установить данные для своего адаптера и сразу после того, как вы скрываете индикатор выполнения и в случае сбоя, вы показываете ошибку тостового сообщения

  • Это общий c класс
class AuthResource<T>(
    var authStatus : AuthStatus? = null,
    var data : T,
    var msg : String? = null

)

fun <T> success(@Nullable data: T): AuthResource<T> {
    return AuthResource(
        AuthStatus.Success,
        data,
        null
    )
}

fun <T> Error(@NonNull msg: String?, @Nullable data: T) : AuthResource<T>? {
    return AuthResource(
        AuthStatus.ERROR,
        data,
        msg
    )
}

fun <T> loading(@Nullable data: T): AuthResource<T>? {
    return AuthResource(
        AuthStatus.LOADING,
        data,
        null
    )
}


enum class AuthStatus {
    Success, ERROR, LOADING
}
  • Это моя модель представления, в которой я реализую authResource с ответом api
class MainViewModel @Inject constructor( private var webAuth: WebAuth,
    private var favFoodDao: FavFoodDao,
    private var application: Application) : ViewModel() {

    /// you have to create MediatorLiveData with authresource which contains your modelclass 

    private var mediatorLiveData = MediatorLiveData<AuthResource<WrapLatestMeals>>()
    
    ///Here you return a livedata object 
    fun ObserverCountries(): LiveData<AuthResource<WrapCountries>> {
        var liveData = LiveDataReactiveStreams.fromPublisher(
            webAuth.getCountries()
                 ///onerrorreturn , rxjava operator which returns error in case 
                 ///of response failure 
                .onErrorReturn(object : Function<Throwable, WrapCountries> {
                    override fun apply(t: Throwable): WrapCountries {
                        var country = WrapCountries()
                        return country
                    }
                })
                .map(object : Function<WrapCountries, 
                     AuthResource<WrapCountries>> {
                    override fun apply(t: WrapCountries): 
                        AuthResource<WrapCountries> {
                        if(t.meals.isNullOrEmpty())
                        {
                            return Error(
                                "Error",
                                t
                            )!!
                        }
                        return success(t)
                    }
                })
                .subscribeOn(Schedulers.io())
        )

       
        //add that data to mediatorLivedata 
        mediatorLiveDataCountries.addSource(liveData, Observer {
            mediatorLiveDataCountries.postValue(it)
            mediatorLiveDataCountries.removeSource(liveData)
        })
        return mediatorLiveDataCountries

    }

  • Вот как вы обрабатываете статус в своей MainActivity
 mainViewModel = ViewModelProvider(this,provider)[MainViewModel::class.java]
        mainViewModel.ObserverCountries().observe(viewLifecycleOwner, Observer {
             when(it.authStatus) {
                 AuthStatus.LOADING -> /// here you show progressbar in response pre-fetch
                 {
                     
                     countriesFragmentBinding.countryprogress.show()
                 }
                 AuthStatus.Success -> { // here you update your ui

                     countriesAdapter = CountriesAdapter(it.data.meals!!, 
                     requireContext())
                     countriesFragmentBinding.recyclercountries.adapter = countriesAdapter
                     countriesAdapter!!.deleteCategory(23)
                     countriesFragmentBinding.countryprogress.hide()
                 }
                 AuthStatus.ERROR -> // here you hide your progressbar and show your toast
                 {
                   
                     countriesFragmentBinding.countryprogress.hide()
                     ToastyError(requireContext(),getString(R.string.errorretreivingdata))
                 }

             }
        })

        return countriesFragmentBinding.root
    }

}
...