撰写创建新的 ViewModel 实例

Art*_*mes 7 android android-viewmodel android-jetpack-compose

我所在的项目正在慢慢采用 Jetpack Compose。它主要是一个单一的ActivityFragment应用程序,我们使用 Android 的导航组件来处理到每个屏幕的转换 ( Fragment)。只要有可能,我们就只用Fragment可组合项替换 s' XML 布局。

截至目前,案件处理情况如下:

A.sFragment显示可组合项并处理导航:

class ScreenFragment : Fragment() {

    // For observing events that trigger navigation
    private val viewModel by lazyViewModel { ScreenViewModel() }

    override fun onCreateView( ... ): View {
        return ComposeView(requireContext()).apply {

            setViewCompositionStrategy(DisposeOnLifecycleDestroyed(viewLifecycleOwner))

            setContent {
                AppTheme {
                    Screen(onBackPressed = { findNavController().navigateUp() })
                }
            }
        }
    }    
    ...

}
Run Code Online (Sandbox Code Playgroud)

B. 处理其他与 UI 相关的所有内容的可组合项:

@Composable
fun CreatePassword(
    onBackPressed: () -> Unit,
) {

    // For observing UI states and events
    val viewModel: CreatePasswordViewModel = viewModel()
    ...
}

Run Code Online (Sandbox Code Playgroud)

ViewModel正如您所看到的,我们在Fragments 和可组合项中都有屏幕的参考。到目前为止,这一直运行良好,可组合函数始终返回'sviewModel()的相同现有实例。FragmentViewModel

ViewModel当我们需要对可组合项上的范围进行引用时,问题就出现了Activity

  1. 我们创建ViewModelActivity
class MainActivity : AppCompatActivity() {

    private val viewModel by lazyViewModel { MainViewModel() }
    ...
}
Run Code Online (Sandbox Code Playgroud)
  1. 获取MainActivity类似ViewModel的参考Fragment
class MainFragment : Fragment() {

    private val viewModel: MainViewModel by viewModels(::requireActivity)
    ...
}
Run Code Online (Sandbox Code Playgroud)
  1. 我们获得可组合项的 ViewModel 的引用,如上所示(项目 B)

通过这样做,Fragment具有相同的 实例Activity,但可组合项却没有。

我的问题是, 是否有可能获得可组合项内的引用?ActivityViewModel现在,我只是将Fragment'sViewModel作为参数传递到我的主可组合屏幕。

Art*_*mes 4

我通过向我的可组合项提供 a来成功传递Activity' ,如下所示:ViewModelViewModelStoreOwner

class ScreenFragment : Fragment() {

    // For observing events that trigger navigation
    private val viewModel by lazyViewModel { ScreenViewModel() }

    override fun onCreateView( ... ): View {
        return ComposeView(requireContext()).apply {

            setViewCompositionStrategy(DisposeOnLifecycleDestroyed(viewLifecycleOwner))

            setContent {
                val viewModelStoreOwner =
                    compositionLocalOf<ViewModelStoreOwner> { requireActivity() }
    
                AppTheme {
                    CompositionLocalProvider(
                        LocalViewModelStoreOwner provides viewModelStoreOwner.current
                    ) {
                        Screen(onBackPressed = { findNavController().navigateUp() })
                    }
                }
            }
        }
    }    
    ...

}
Run Code Online (Sandbox Code Playgroud)