我有一个带有视图模型的可组合项,我想将一个 id 从可组合项传递到视图模型。
我的可组合项是:
@Composable
fun HttpRequestScreen(
viewModel: HttpRequestViewModel = hiltViewModel(),
id: String = EMPTYUUID,
onClick: (String, String, Int) -> Unit // respond, request Function: 1 - send request, 2 - edit request
) {
我有来自不同屏幕的 ID,我想将其传递到我的 Hilt 视图模型。
假设您已遵循撰写导航的文档,您可以在此处找到您的参数:
@HiltViewModel
class RouteDetailsViewModel @Inject constructor(
private val getRouteByIdUC: GetRouteByIdUC,
private val savedStateHandle: SavedStateHandle
): ViewModel() {
private val routeId = savedStateHandle.get<String>("your-param-name") // for example String in my case
}
您需要以单向数据流模式进行思考,其中事件向上流动,状态向下流动。为此,您需要从视图模型中公开某种状态,将请求的状态作为可观察状态发送到可组合项。
你的视图模型可能看起来像这样。
class HttpRequestViewModel: ViewModel() {
private val _httpResponse = mutableStateOf("")
val httpResponse: State<String> = _httpResponse
fun onHttpRequest(requestUrl: String) {
// Execute your logic
val result = "result of your execution"
_httpResponse.value = result
}
}
然后在您的 Composable 中,您可以通过在按钮单击上调用 ViewModel 函数来发送事件,如下所示
@Composable
fun HttpRequestScreen(viewModel: HttpRequestViewModel) {
val state by viewModel.httpResponse
var userInput = remember { TextFieldValue("") }
Column {
Text(text = "HTTP Response = $state")
}
BasicTextField(value = userInput, onValueChange = {
userInput = it
})
Button(onClick = { viewModel.onHttpRequest(userInput.text) }) {
Text(text = "Make Request")
}
}
我希望这能为您指明正确的方向。祝你好运。
如果您使用 Dagger Hilt,则通过 AndroidX 工件
key
添加对
androidx.hilt:hilt-navigation-compose
的支持。
或者,您可以自己创建这个内联函数:
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.HiltViewModelFactory
import androidx.lifecycle.HasDefaultViewModelProviderFactory
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.viewModel
/**
* Returns an existing
* [HiltViewModel](https://dagger.dev/api/latest/dagger/hilt/android/lifecycle/HiltViewModel)
* -annotated [ViewModel] or creates a new one scoped to the current navigation graph present on
* the {@link NavController} back stack.
*
* If no navigation graph is currently present then the current scope will be used, usually, a
* fragment or an activity.
*
* @sample androidx.hilt.navigation.compose.samples.NavComposable
* @sample androidx.hilt.navigation.compose.samples.NestedNavComposable
*/
@Composable
inline fun <reified VM : ViewModel> hiltViewModel(
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
},
key: String? = null
): VM {
val factory = createHiltViewModelFactory(viewModelStoreOwner)
return viewModel(viewModelStoreOwner, key, factory = factory)
}
@Composable
@PublishedApi
internal fun createHiltViewModelFactory(
viewModelStoreOwner: ViewModelStoreOwner
): ViewModelProvider.Factory? = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) {
HiltViewModelFactory(
context = LocalContext.current,
delegateFactory = viewModelStoreOwner.defaultViewModelProviderFactory
)
} else {
// Use the default factory provided by the ViewModelStoreOwner
// and assume it is an @AndroidEntryPoint annotated fragment or activity
null
}