我正在使用 JetpackCompose,并且我有一个 lifecycle Observable BatteryBroadcast 类,该类使用 Hilt 注入到 MainActivity 中,我想 将数据从 BatteryBroadcast 传递到 ViewModel 以在可组合屏幕中使用该数据。那么如何在所有可组合的 Activity 屏幕中使用相同的 ViewModel 实例呢?我正在将 NavHost 用于可组合屏幕。
class MainActivity : ComponentActivity() {
@Inject
lateinit var batteryBroadcast: BatteryBroadcast
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BatteryAlarmGoldTheme {
val homeViewModel = hiltViewModel<HomeViewModel>()
lifecycle.addObserver(batteryBroadcast)
homeViewModel.setBatteryProfileData(batteryBroadcast.dataFlow)
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
BatteryAlarmGoldApp()
}
}
}
}
}
我的撰写图。
fun NavGraphBuilder.homeNavGraph(
navController: NavHostController
) {
navigation(startDestination = Screen.HomeScreen.route, route = HOME_ROUTE) {
composable(Screen.HomeScreen.route) {
val homeBackStackEntry = remember { navController.getBackStackEntry(HOME_ROUTE) }
val homeViewModel: HomeViewModel = hiltViewModel(homeBackStackEntry)
HomeScreen(
navController = navController,
viewModel = homeViewModel
)
}
composable(Screen.SelectRingtoneScreen.route) {
val homeBackStackEntry = remember { navController.getBackStackEntry(HOME_ROUTE) }
val homeViewModel: HomeViewModel = hiltViewModel(homeBackStackEntry)
RingtoneScreen(
viewModel = homeViewModel
)
}
}
}
我尝试在 Compose 函数中@Inject BattryBroadcast,我还可以访问 ViewModel,以便我可以使用相同的 ViewModel 实例来设置和获取数据,但无法在 compose 函数中使用 @Inject。
为什么不将此视图模型实例传递到您的
BatteryAlarmGoldApp
可组合项中?
class MainActivity : ComponentActivity() {
@Inject
lateinit var batteryBroadcast: BatteryBroadcast
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BatteryAlarmGoldTheme {
val homeViewModel = hiltViewModel<HomeViewModel>()
lifecycle.addObserver(batteryBroadcast)
homeViewModel.setBatteryProfileData(batteryBroadcast.dataFlow)
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
BatteryAlarmGoldApp(homeViewModel)
}
}
}
}
}
然后您可以在您的孩子可组合项中使用它
也许更好的解决方案是将广播接收器制作为
@Composable
并将其包装在DisposableEffect
中。
const val INTENT_ACTION_NFC_READ = "your.package.name.INTENT_ACTION_NFC_READ"
@Composable
fun NfcBroadcastReceiver(
onScanSuccess: (Tag) -> Unit
) {
val context = LocalContext.current
val currentOnScanSuccessEvent by rememberUpdatedState(onScanSuccess)
DisposableEffect(context) {
val intentFilter = IntentFilter(INTENT_ACTION_NFC_READ)
val broadcast = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
when (intent.action) {
INTENT_ACTION_NFC_READ -> {
IntentCompat.getParcelableExtra(intent, NfcAdapter.EXTRA_TAG, Tag::class.java)
?.let { currentOnScanSuccessEvent(it) }
}
else -> {
// No op.
}
}
}
}
}
ContextCompat.registerReceiver(
context,
broadcast,
intentFilter,
ContextCompat.RECEIVER_NOT_EXPORTED
)
onDispose {
context.unregisterReceiver(broadcast)
}
}
}
然后在
@Composable
屏幕中使用它。
@Composable
fun SampleScreen() {
NfcBroadcastReceiver(
onScanSuccess = { tag ->
// Handle tag
}
)
Scaffold(
modifier = ...,
snackbarHost = ...,
topBar = ...
) { padding ->
{ ... }
}
}
当屏幕关闭时,
NfcBroadcastReceiver
将被丢弃。