viewModelScope.launch第二次不起作用。

11

我有两个片段,FragmentA 包含星球大战角色列表,而 FragmentB 包含该角色的详细信息。我在我的片段中使用 viewModelScope.launch 来获取角色的详细信息。以下是我的 ViewModel:

@HiltViewModel
class DetailsViewModel @Inject constructor(
    private val getSpecieDetailsUseCase: GetSpecieDetailsUseCase,
    private val getFilmDetailsUseCase: GetFilmDetailsUseCase,
    private val getPlanetDetailsUseCase: GetPlanetDetailsUseCase,
    private val mapper: CharacterDetailMapper
) : ViewModel() {

    var characterDetailsModel = MutableLiveData<CharacterDetailsModel?>()

    fun init(infoModel: CharacterInfoModel?) {
        characterDetailsModel.postValue(null)
        try {
            viewModelScope.launch {
                infoModel?.let {
                    val specieResponse = async(context = Dispatchers.IO) {
                        it.specieIdList?.map {
                            getSpecieDetailsUseCase.executeUseCase(
                                GetSpecieDetailsUseCase.GetSpecieDetailsRequest(
                                    it
                                )
                            )
                        }
                    }
                    val filmResponse = async(context = Dispatchers.IO) {
                        it.filmsIdList?.map {
                            getFilmDetailsUseCase.executeUseCase(
                                GetFilmDetailsUseCase.GetFilmDetailsRequest(
                                    it
                                )
                            )
                        }
                    }
                    val planetResponse = it.homeworldId?.let {
                        getPlanetDetailsUseCase.executeUseCase(
                            GetPlanetDetailsUseCase.GetPlanetDetailsRequest(
                                it
                            )
                        )
                    }
                    characterDetailsModel.postValue(
                        mapper.toModel(
                            name = it.name.toString(),
                            birth_year = it.birth_year.toString(),
                            height = it.height.toString(),
                            specieDetailsResponse = specieResponse.await(),
                            filmDetailsResponse = filmResponse.await(),
                            planetDetailsResponse = planetResponse
                        )
                    )
                }
            }
        } catch (exception: Exception) {
            exception.stackTrace
        }

    }
}
viewModelScope.launch 调用第一次时没有问题,但第二次调用不起作用[例如返回到先前的片段并回到详细信息片段]。 init 函数接收到的数据也是更新的数据,但是我的所有异步调用似乎在第二次调用时都不起作用。每当我转到先前的片段时,View Model 的 onCleared 方法都会被调用,我认为这应该清除其作用域。我尝试捕获异常,但没有任何异常抛出。我尝试进行调试,但是我的所有异步调用断点都没有命中。

你确定你没有将空的 infoModel 传递给这个函数吗?顺便说一下,你使用 try/catch 的方式不会起到任何作用。调用 launch 将协程排队启动,它永远不会抛出异常。由于在协程中执行的操作,可能会导致异常发生,但是那时你需要在协程内部使用 try/catch。 - Tenfour04
不,我没有将 null 传递给 infoModel。 - Akshay Shah
onCleared 应该在销毁 ViewModel 之前只被调用一次。如果在返回 Fragment 时收到已经清除的实例,则表示您错误地将其注入为依赖项或以其他方式保留了对它的强引用。 - Pawel
是的,它只有在viewModel被销毁时才会被调用。 - Akshay Shah
5
@AkshayShah 你找到原因并且知道如何修复了吗? - Thân Hoàng
2个回答

3

检查您如何创建此视图模型,更重要的是何时创建。如果您使用by viewModels() LAZY委托,请检查它何时首次初始化。 viewModels()this用作viewModelStoreOwner。在99%的情况下,当launch不起作用时,this将指向主机Activity。 解决方案很简单-创建自己的lambda,该lambda将返回正确的Fragment的viewModelStoreOwner或使用旧的viewModel初始化样式。

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel = ViewModelProvider(this).get(TextClassifiedViewModel::class.java)
    }

0
如果viewModelScope.launch第二次不起作用:
您可以在ViewModel中将viewModelScope.launch { ... }更改为GlobalScope.launch { ... }

在实践中不推荐使用GlobalScope。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接