提问者:小点点

导航到网络呼叫成功时的另一个片段


我想做一个网络呼叫,从一个片段,在按下一个按钮,如果网络呼叫是成功的,然后想导航到另一个片段,如果不是,然后停留在当前的片段,并在祝酒词中显示错误。

我正在通过单击SatrtGameButtonReviewGameRulesFragment进行网络调用,它如下所示:

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
    
    viewModel = ViewModelProvider(requireActivity()).get(SetupGameViewModel::class.java)
    
    binding = DataBindingUtil.inflate<FragmentReviewGameRulesBinding>(
                inflater,
                R.layout.fragment_review_game_rules,
                container,
                false
            )
    
    binding.startGameButton.setOnClickListener {
                viewModel.createGame(this.view)
            }
}

createGame函数位于SetupGameViewModel文件中,如下所示:

fun createGame() {
        coroutineScope.launch {
            val createGameRequest = CreateGameRequest(
                gamePrice = gamePrice,
                gameRules = gameRules,
                playerOneGameName = playerOneGameName
            )
            var getPropertiesDeferred =
                ParagonApi.retrofitService.createGameAsync(createGameRequest)
            try {
                _createGameResponse.value = getPropertiesDeferred.await()
            } catch (e: Exception) {
            }
        }
    }

现在-我想导航到另一个片段的成功这个调用或停留在那里的失败。 正确的做法是什么?


共1个答案

匿名用户

您可以使用LiveData来观察状态,当它是一个成功时,刚刚设置为通知成功已经发生

为您的州创建类

sealed class NetworkLoadingState {
    object OnLoading : NetworkLoadingState()
    object OnSuccess : NetworkLoadingState()
    data class OnError(val message: String) : NetworkLoadingState()
}

SetupGameViewModel中创建要观察的LiveData实例

class SetupGameViewModel : ViewModel() {

   private var _loadState = MutableLiveData<Event<NetworkLoadingState>>()
    val loadState: LiveData<Event<NetworkLoadingState>>
        get() = _loadState

//Instead of `coroutineScope` use `viewModelScope`
fun createGame() {
       // coroutineScope.launch {
        viewModelScope.launch {
            
              _loadState.value = Event(NetworkLoadingState.OnLoading)
            
            val createGameRequest = CreateGameRequest(
                gamePrice = gamePrice,
                gameRules = gameRules,
                playerOneGameName = playerOneGameName
            )
            var getPropertiesDeferred =
                ParagonApi.retrofitService.createGameAsync(createGameRequest)
            try {
                _createGameResponse.value = getPropertiesDeferred.await()
              //Here is code
              _loadState.value = Event(NetworkLoadingState.OnSuccess)
            } catch (e: Exception) {
              _loadState.value = Event(NetworkLoadingState.OnError("Exception message here"))
            }
        }
    }


}

现在在你的碎片里

 binding.startGameButton.setOnClickListener {
            viewModel.createGame(this.view)
            observeLoadingState()
        }

 private fun observeLoadingState() =
        viewModel.loadState.observe(viewLifecycleOwner, EventObserver {
            when (it) {
                is NetworkLoadingState.OnLoading -> println("You can show loading indicator here or whatever to inform user that data is being loaded")
                is NetworkLoadingState.OnSuccess -> println("Success now you can navigate")
                is NetworkLoadingState.OnError -> println(it.errorMessage)
            }
        })

这里是用于处理单个事件的事件类,否则当您的成功片段从后堆栈弹出时,您将导航回成功屏幕

event.kt

/*
 a* Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package your.package.name

import androidx.lifecycle.Observer

/**
 * Used as a wrapper for data that is exposed via a LiveData that represents an event.
 */
open class Event<out T>(private val content: T) {

    @Suppress("MemberVisibilityCanBePrivate")
    var hasBeenHandled = false
        private set // Allow external read but not write

    /**
     * Returns the content and prevents its use again.
     */
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }
    }

    /**
     * Returns the content, even if it's already been handled.
     */
    //fun peekContent(): T = content
}

/**
 * An [Observer] for [Event]s, simplifying the pattern of checking if the [Event]'s content has
 * already been handled.
 *
 * [onEventUnhandledContent] is *only* called if the [Event]'s contents has not been handled.
 */
class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<Event<T>> {
    override fun onChanged(event: Event<T>?) {
        event?.getContentIfNotHandled()?.let {
            onEventUnhandledContent(it)
        }
    }
}

更多信息,你可以访问我的回购,给一个星,如果你喜欢它。