kotlin 我应该如何将融合位置提供程序客户端注入MVVM中的ViewModel(使用Compose和Dagger-Hilt)

xkrw2x1b  于 2023-04-12  发布在  Kotlin
关注(0)|答案(1)|浏览(120)

问题的背景

我目前正在学习如何在Compose中使用MVVM模式,在Dagger-Hilt中使用依赖注入。
我需要创建一个FusedLocationProviderClient,这样我就可以从我的View Model更新GoogleMap Composable的位置状态。

注意事项

我认为FusedLocationProviderClient应该从Main Activity创建,因为它是一个特定于Android的操作(并且它需要一个Activity上下文)。我也不想将我的Activity上下文传递给我的视图模型,因为它们会导致内存泄漏。
同时,由于我使用Dagger-Hilt,我不需要在Activity中创建我的ViewModel,因为它们可以很容易地注入到我的可组合屏幕中:

@Composable
fun MainScreen(viewModel : MainViewModel = hiltViewModel()) {/*UI logic*/}

在我的MainActivity中,setContent{}中唯一可组合的是一个具有NavHostNavGraphBuilder的函数:

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    private lateinit var navController: NavHostController
    private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
    private var latitude = 0.0
    private var longitude = 0.0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

        setContent {
            MyTheme {
                navController = rememberAnimatedNavController()
                Navigation(navController)
            }
        }
    }

问题

那么,在遵循MVVM原则的同时,如果ViewModel不必在MainActivity中创建,我如何将FusedLocationProviderClient注入到ViewModel中呢?
谢谢!
注意:我也尽量避免使用AndroidViewModel来获取上下文,因为它将更难进行单元测试。

oug3syen

oug3syen1#

如果你使用的是hilt,你可以通过如下模块提供FusedLocationProviderClient

@Module
@InstallIn(SingletonComponent::class)
class LocationModule {
    @Provides
    fun provideFusedLocationProviderClient(
        @ApplicationContext context: Context
    ): FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
}

然后只需将FusedLocationProviderClient注入到需要使用的视图模型中:

@HiltViewModel
class MainViewModel @Inject constructor(
    private val locationClient: FusedLocationProviderClient
) : ViewModel() {
...
}

getFusedLocationProviderClient()只需要Context参数,而不需要Activity,所以我认为您可以使用SingletonComponent作为模块,@ApplicationContext作为上下文,但如果它只需要Activity上下文,您可以尝试使用ActivityRetainedComponent作为模块,@ActivityContext作为上下文,它将为getFusedLocationProviderClient()方法获取Activity的上下文

相关问题