0

我有 5 个模块(主要、启动、选择位置、权限、首选项)。

我想在 Splash 和 PickLocation 中使用 Preferences 模块。

这是我的模块的流程:Splash -> PickLocation

当我想使用 PickLocation 模块中的 DataStore 类来保存新位置时,我遇到了一个问题:

如果我在 Splash 模块中创建 DataStore 类的新实例并在 PickLocation 模块中创建同一类的另一个实例,则 DataStore 不起作用,但如果我只是在 PickLocation 中创建一个实例,则一切正常。如何使用 dagger hilt 创建一个实例并从所有模块访问?

偏好模块 DI:

package com.mykuyaclient.preference.di

import android.content.Context
import com.mykuyaclient.preference.datastores.CheckLocationIsSetDataStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object PreferenceModule {

    @Provides
    fun provideCheckLocationIsSetDataStore(@ApplicationContext appContext: Context): CheckLocationIsSetDataStore =
        CheckLocationIsSetDataStore(appContext)
}

PickLocation屏幕代码:

@Composable
fun MapScreen(navigatorViewModel: PickLocationViewModel) {
    **val context = LocalContext.current
    val dataStore = CheckLocationIsSetDataStore(context = context)**
    Surface(color = AppColor.ThemeColor.BACKGROUND) {
        val mapView = rememberMapViewWithLifecycle()
        Column(Modifier.fillMaxSize()) {
            Box(modifier = Modifier.fillMaxSize()) {

                MapViewContainer(mapView, navigatorViewModel)
                MapPinOverlay()

                Column(modifier = Modifier.align(Alignment.BottomCenter)) {
                    Button(
                        colors = ButtonDefaults.buttonColors(
                            backgroundColor = AppColor.brandColor.BLUE_DE_FRANCE,
                            contentColor = AppColor.neutralColor.DOCTOR
                        ),
                        onClick = {
                            navigatorViewModel.apply {
//                                popBackStack()
                                navigate(HomeDestination.route())
                                **viewModelScope.launch {
                                    dataStore.set(
                                        this@apply.location.value
                                    )
                                    
                                }**
                            }
                        }) {
                        Text(
                            text = stringResource(R.string.confirm_address),
                            style = AppFont.PoppinsTypography.button
                        )
                    }
                    Spacer(modifier = Modifier.size(16.dp))
                }
            }
        }
    }
}

闪屏代码:

@OptIn(ExperimentalPermissionsApi::class)
@Composable
private fun SplashView(
    modifier: Modifier,
    multiplePermissionsState: MultiplePermissionsState,
    navigator: SplashViewModel = hiltViewModel()
) {
    **val context = LocalContext.current
    val dataStore = CheckLocationIsSetDataStore(context = context)**
    Box(
        modifier = modifier
            .fillMaxSize()
            .background(color = AppColor.brandColor.BLUE_DE_FRANCE)
            .padding(start = 64.dp, end = 64.dp, bottom = 16.dp)
    ) {
        Column(modifier = modifier.align(Alignment.Center)) {
            Image(
                painter = painterResource(id = R.drawable.mykuyatm),
                contentDescription = "mykuya tm image"
            )
            Image(
                painter = painterResource(id = R.drawable.mykuya_powered_by),
                contentDescription = "mykuya powered by image"
            )
        }
        Loading(modifier = modifier.align(Alignment.BottomCenter))
        FeatureThatRequiresPermission(
            multiplePermissionsState = multiplePermissionsState, permissionsState = {
                if (it) {
                    navigator.apply {
                        viewModelScope.launch {
                            delay(Constants.SPLASH_DELAY)
                            **dataStore.get.collect { model ->
                                model.let {
                                   /* if (model.lat == Constants.IF_LOCATION_LAT_NOT_SET && model.lat == Constants.IF_LOCATION_LNG_NOT_SET) {
                                        navigate(PickLocationDestination.route())
                                    }else{
                                        navigate(HomeDestination.route())
                                    }*/
                                    navigate(PickLocationDestination.route())
                                }
                            }**

//                            popBackStack()

                        }
                    }
                }
            })
    }
}

DataStore 类代码:(我如何在所有模块中使用此类的实例)

class CheckLocationIsSetDataStore @Inject constructor(private val context: Context) :
    IDataStore<Location, Location> {
    override val get: Flow<Location>
        get() = context.dataStore.data.catch { exception ->
            if (exception is IOException) {
                emit(emptyPreferences())
            } else {
                throw exception
            }
            Log.e("DataStore Exception: ", exception.toString())
        }.map { preferences ->
            Location("").let {
                it.latitude = preferences[DataStoreKeys.IS_LOCATION_LAT_SET_KEY]
                    ?: Constants.IF_LOCATION_LAT_NOT_SET
                it.longitude = preferences[DataStoreKeys.IS_LOCATION_LNG_SET_KEY]
                    ?: Constants.IF_LOCATION_LNG_NOT_SET
                it
            }
        }

    override suspend fun set(param: Location?) {
        context.dataStore.edit { preferences ->
               preferences[DataStoreKeys.IS_LOCATION_LAT_SET_KEY] =
                   param?.latitude ?: Constants.IF_LOCATION_LAT_NOT_SET
               preferences[DataStoreKeys.IS_LOCATION_LNG_SET_KEY] =
                   param?.longitude ?: Constants.IF_LOCATION_LNG_NOT_SET
           }
    }
}
4

1 回答 1

1

Hilt 可以在视图模型中注入依赖项,因此您需要创建这样的模型。

这是一个基本示例:

class CheckLocationIsSetDataStore @Inject constructor(
    @ApplicationContext val context: Context
) {
    fun dataStore() = context.dataStore
    
    private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "composePreferences")
}

@HiltViewModel
class DataStoreProviderViewModel @Inject constructor(
    private val checkLocationIsSetDataStore: CheckLocationIsSetDataStore,
): ViewModel() {
    private val key = booleanPreferencesKey("some_test_key")

    val get get() = checkLocationIsSetDataStore.dataStore().data.catch { exception ->
        if (exception is IOException) {
            emit(emptyPreferences())
        } else {
            throw exception
        }
        Log.e("DataStore Exception: ", exception.toString())
    }.map { preferences ->
        preferences[key] ?: false
    }

    fun set(value: Boolean) {
        viewModelScope.launch {
            checkLocationIsSetDataStore.dataStore().edit {
                it[key] = value
            }
        }
    }
}

@Composable
fun TestScreen(
) {
    val viewModel = hiltViewModel<DataStoreProviderViewModel>()
    val some by viewModel.get.collectAsState(initial = false)
    Switch(checked = some, onCheckedChange = { viewModel.set(it) })
}
于 2021-10-27T17:51:43.843 回答