Невозможно получить обратный вызов из LiveData с помощью модифицированного вызова через CustomCallAdapterFactory kotlin - PullRequest
0 голосов
/ 10 января 2020

Я новичок в MVVVM и следовал примеру Google GihubBrowser, чтобы реализовать обратный вызов LiveData для модификации, но я не могу запросить запрос при повторной установке с этой реализацией. Пожалуйста, помогите мне, что я делаю неправильно:

Репозиторий

class LoginRepository(var application: Application) {


    var result = MutableLiveData<Resource<GenericResponse>>()


    fun iniateOTPprocess()  {

        result = object : NetworkBoundResource<GenericResponse, GenericResponse>() {

            override fun createCall() = RetroUtils.getApiManager().listRepos()

            override fun processResponse(response: ApiSuccessResponse<GenericResponse>)
                    : GenericResponse {
                val body = response.body
                return body
            }
        }.asLiveData()
    }


    fun getData(): MutableLiveData<Resource<GenericResponse>> {
        return result
    }
}

ViewModel

class LoginViewModel2(application: Application) : AndroidViewModel(application) {


    lateinit var username: MutableLiveData<String>
    lateinit var password: MutableLiveData<String>
    var repository: LoginRepository = LoginRepository(application)
    var data = MediatorLiveData<Resource<GenericResponse>>()


    init {
        data.addSource(repository.getData(), Observer {
            data.postValue(it)
        })
    }


    fun onLoginBtnCLicked() {
        initiateOTP()
    }


    private fun initiateOTP() {
        repository.iniateOTPprocess()
    }


    fun getResponse() : MutableLiveData<Resource<GenericResponse>>{
        return data
    }


}   

Ниже упоминается адаптер

class LiveDataCallAdapter<R>(private val responseType: Type) :
    CallAdapter<R, LiveData<ApiResponse<R>>> {

    override fun responseType() = responseType

    override fun adapt(call: Call<R>): LiveData<ApiResponse<R>> {
        return object : LiveData<ApiResponse<R>>() {
            private var started = AtomicBoolean(false)
            override fun onActive() {
                super.onActive()
                if (started.compareAndSet(false, true)) {
                    call.enqueue(object : Callback<R> {
                        override fun onResponse(call: Call<R>, response: Response<R>) {
                            postValue(ApiResponse.create(response))
                        }

                        override fun onFailure(call: Call<R>, throwable: Throwable) {
                            postValue(ApiResponse.create(throwable))
                        }
                    })
                }
            }
        }
    }
}

Деятельность

  class LoginActivity2 : AppCompatActivity() {


lateinit var binding: LoginViewBinding;
lateinit var vModel: LoginViewModel2;


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this, R.layout.login_view)
    binding.setLifecycleOwner(this)
    vModel = ViewModelProviders.of(this).get(LoginViewModel2::class.java)
    binding.loginViewModel = vModel



    vModel.getResponse().observe(this, Observer { t ->

        Log.e("data", t?.data.toString() ?: "Data is null")


    })

}


}

Обратите внимание, что это не является дубликатом этого

Модификация LiveDataCallAdapter не вызывает функцию adapt (call)

Как я могу чтобы этот код работал, если я непосредственно наблюдаю метод initiateOTP () непосредственно в viewmodel, но таким образом API будет срабатывать даже без нажатия на кнопку, которая мне не нужна.

Пожалуйста, предложите лучший appproach. Заранее спасибо.

1 Ответ

0 голосов
/ 11 января 2020

Каждый раз, когда вы звоните iniateOTPprocess(), создается новый result, поэтому наблюдение за старым бесполезно. Вместо этого попробуйте следующее:

Репозиторий

class LoginRepository(var application: Application) {

    // remove this
    // var result = MutableLiveData<Resource<GenericResponse>>()

    fun initiateOtpProcess(): LiveData<Resource<GenericResponse>> {

        return object : NetworkBoundResource<GenericResponse, GenericResponse>() {

            override fun createCall() = RetroUtils.getApiManager().listRepos()

            override fun processResponse(response: ApiSuccessResponse<GenericResponse>)
                    : GenericResponse {
                val body = response.body
                return body
            }
        }.asLiveData()
    }

    // remove this as well
    // fun getData(): MutableLiveData<Resource<GenericResponse>>
}

В предыдущем Repository проекте initiateOTPprocess и getData должны вызываться последовательно. Вместо этого просто позвольте initiateOtpProcess вернуть LiveData.

ViewModel

class LoginViewModel2(application: Application) : AndroidViewModel(application) {

    lateinit var username: MutableLiveData<String>
    lateinit var password: MutableLiveData<String>
    val repository: LoginRepository = LoginRepository(application)
    val data = MediatorLiveData<Resource<GenericResponse>>()

    var currentOtpSource: LiveData<Resource<GenericResponse>>()


    // init {
    //    data.addSource(repository.getData(), Observer {
    //        data.postValue(it)
    //    })
    //}


    fun onLoginBtnCLicked() {
        initiateOTP()
    }


    private fun initiateOTP() {
        currentOtpSource?.let {
            // remove previous source if any
            data.removeSource(it)
        }

        newSource = repository.iniateOTPprocess()
        currentOtpSource = newSource

        data.addSource(newSource, Observer {
            data.setValue(it)
        })
    }


    fun getResponse() : LiveData<Resource<GenericResponse>>{
        return data
    }
}
...