я могу сделать наблюдателя liveata в моей модели представления? или я должен всегда наблюдатель во фрагменте / деятельности? - PullRequest
0 голосов
/ 21 марта 2020

Я новичок в MVVM. поэтому у меня есть 2 запроса к серверу из моего фрагмента / действия, результат первого запроса будет использоваться в качестве входного параметра для второго запроса.

, поэтому сначала в моем фрагменте, когда нажимается кнопка, затем Я делаю запрос, чтобы проверить, забанен ли пользователь или нет, если нет, то этот пользователь может создать сообщение.

, поэтому сначала я проверяю, забанен ли пользователь или не использует этот код в моем фрагменте

class CreateEventFragment : Fragment() {

    lateinit var model: CreateEventViewModel


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        model = ViewModelProvider(this).get(CreateEventViewModel::class.java)

        button.setOnClickListener {
            model.checkIfUserIsBanned()
        }

    }


}

и вот модель представления

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

    val mUserIsBanned :MutableLiveData<Boolean> = UserClient.mUserIsBanned

    fun checkIfUserIsBanned(userID: String) {
        UserRepository.checkIfUserIsBanned(id)
    }


}

, а вот клиент (для простоты я пропускаю репозиторий)

object UserClient {

    val mUserIsBanned = MutableLiveData<Boolean>()

    fun checkIfUserIsBanned(userID: String) {

        // perform networking, after getting the value then

        if (user.isBanned) {
            mUserIsBanned.postValue(true)
        } else {
            mUserIsBanned.postValue(false)
        }

    }



}

вот проблема, второй запрос нужен результат первого результата, т.е. mUserIsBanned необходимо проверить, не заблокирован ли пользователь, а затем выполнить второй запрос (пользователь создает сообщение). мой вопрос, где я могу разместить эту логи c? в viewmodel или в моем фрагменте?

if (userIsBanned == false) {
   createPost()
}

из учебника, который я видел, кажется, что liveata всегда наблюдается во фрагменте. поэтому первый вариант заключается в том, чтобы поместить logi c во фрагмент, подобный этому

    model.mUserIsBanned.observe(viewLifecycleOwner, Observer { isBanned ->

        val userIsBanned = isBanned ?: return@Observer

        if (!userIsBanned) {
            model.createPost()
        }

    })

. Можно ли размещать проверку кода таким образом во фрагменте?

на самом деле мне не нужно наблюдать isBanned, мне просто нужно проверить его один раз

или второй вариант - проверить userIsBanned или нет в viewmodel, но я не знаю как сделать наблюдение жилетата во viewmodel

или у меня все неправильно? Я не уверен, используя этот MVVM

, пожалуйста, помогите, java тоже нормально.

Ответы [ 2 ]

0 голосов
/ 27 марта 2020

Мы можем подумать о трех подходах:

  1. вам нужно получать isBanned каждый раз, когда вы пытаетесь создать сообщение
  2. вы получаете isBanned один или один раз в 5 минут (после 5 минут кеша истекает)
  3. вы никогда не проверяете его, API вернет ответ об ошибке при попытке создать сообщение, если пользователь isBanned. API также возвращает спецификацию c модель / http_code, чтобы вы также могли понять, что пользователь isBanned

Подход 1 - , а не ОК, подход 2 - в порядке, если isBanned - используется и в других местах, и если вы храните его локально (до следующего открытия приложения или некоторого периода времени). Подход 3 должен быть всегда, isBanned всегда должен проверяться сервером.

Подход 2 :

Просмотр / Фрагмент / Активность:

// has no idea about detail; isBanned check or other kinds of validations
// new type of validations can be added without modifying this code (max post characters)
observeCreatePost()
viewModel.createPost(params)

ViewModel:

// does not know about validations, checks. But if you create Post only using this viewModel, then validation can be here as well

val createPostState = MutableLiveData<Result<Boolean>>()

fun createPost(params:String){
   createPostState.postValue(UIResult.Loading)

   createPostUseCase(params)
     // or .subscribe()
     .observe{ result->
        // ideally you convert Exceptions to (String) representation here
        createPostState.postValue(result.data)
     }
}

CreatePostUseCase:

operator fun invoke(params:String):Result<Boolean>{
    // validations are here, multiple ViewModels can use this UseCase
    // validate if params are valid, if not return Result.Error()

    // still does not know if userBanned comes from local data or API
    if(repository.isUserBanned()){
       return Result.Error()
    }else{
       return repository.createPost(params)
    }
}

PostRepository:

fun isUserBanned():Boolean{
   if(userBanned exist locally and not expired)
       return userBanned locally
   else
       isUserBanned = api.isUserBanned()
       storeLocal(isUserBanned)
       return isUserBanned
}

fun createPost(params):Result<Boolean>{
   response = api.createPost(params)
   // return Result wrapped response 
}
0 голосов
/ 26 марта 2020

Вы можете попробовать MediatorLiveData для второй операции. MediatorLiveData делает то, что создает прослушиваемый контейнер для ваших различных LiveData объектов и предоставляет вам обратный вызов при изменении любого базового / наблюдаемого значения.

Пример: Предположим, что необходимо вызвать LiveData<B> на любое значение, отличное от LiveData<A>, здесь вы можете рассматривать LiveData<B> как MediatorLiveData.

Таким образом, объявление для LiveData<B> будет:

val bLiveData : LiveData<B> = MediatorLiveData<B>().apply {
    addSource(aLiveData) { aData ->
        value = convertADataToB(aData) //value is backing property for getValue()/setValue() method, use postValue() explicitly upon bg operation
    }
}

В вашем случае введите этот код внутри ViewModel:

val createPostLiveData: LiveData<Boolean> = MediatorLiveData<Boolean>().apply {
    addSource(mUserIsBanned) { flag ->
        if (!flag) {
            createPost() // Check whether you can return result from here and provide to this mediator livedata a value
        }
    }
}

См. MediatorLiveData

...