我一直在使用 StateFlow + 密封接口来表示 Android 应用程序中的各种 UI 状态。在我的 ViewModel 中,我有一个密封接口UiState来执行此操作,并且各种状态公开为StateFlow:
sealed interface UiState {
class LocationFound(val location: CurrentLocation) : UiState
object Loading : UiState
// ...
class Error(val message: String?) : UiState
}
@HiltViewModel
class MyViewModel @Inject constructor(private val getLocationUseCase: GetLocationUseCase): ViewModel() {
private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
val uiState: StateFlow<UiState> = _uiState
// ...
}
Run Code Online (Sandbox Code Playgroud)
然后在可组合项中,我以这种方式观察事件:
@Composable
fun MyScreen(
viewModel: HomeScreenViewModel,
onLocationFound: (CurrentLocation) -> Unit,
onSnackbarButtonClick: () -> Unit
) {
// ...
LaunchedEffect(true) { …Run Code Online (Sandbox Code Playgroud) android android-jetpack-navigation android-jetpack-compose kotlin-stateflow
有没有办法startDestination在运行时动态更改 NavHost 的参数?
on boarding问题:我只想在您第一次启动应用程序时显示屏幕。每次启动时我都想显示登录屏幕。这就是为什么我必须startDestination在运行时动态改变。
但是,每次我尝试这样做时都会收到错误:
java.util.NoSuchElementException: List contains no element matching the predicate.
at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:181)
at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(NavHost.kt:141)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.CrossfadeKt$Crossfade$4$1.invoke(Crossfade.kt:115)
at androidx.compose.animation.CrossfadeKt$Crossfade$4$1.invoke(Crossfade.kt:110)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:124)
at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:55)
at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:141)
at androidx.navigation.compose.NavHostKt$NavHost$5.invoke(Unknown Source:13)
at androidx.navigation.compose.NavHostKt$NavHost$5.invoke(Unknown Source:10)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:145)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2375)
at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2643)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3260)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:3238)
at androidx.compose.runtime.SnapshotStateKt__DerivedStateKt.observeDerivedStateRecalculations(DerivedState.kt:341)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(Unknown Source:1)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:3238)
at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:3203)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:771)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:1031)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:125)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:534)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:503)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109) …Run Code Online (Sandbox Code Playgroud) android android-jetpack android-jetpack-navigation android-jetpack-compose
我有该应用程序,那里有 2 个导航图。首先是RootNavGraph:
@Composable
fun RootNavGraph(navController: NavHostController) {
NavHost(navController, startDestination = RootGraphItem.Splash.route) {
composable(route = RootGraphItem.Splash.route) {
SplashScreen(navController = navController)
}
composable(route = RootGraphItem.Login.route) {
LoginScreen(navController = navController)
}
composable(route = RootGraphItem.Register.route) {
RegisterScreen(navController = navController)
}
composable(route = RootGraphItem.Main.route) {
MainScreen()
}
composable(route = RootGraphItem.BasicInfo.route) {
BasicInfoScreen(navController = navController)
}
composable(route = RootGraphItem.GenderIdentity.route) {
GenderIdentityScreen(navController = navController)
}
composable(route = RootGraphItem.SexualOrientation.route) {
SexualOrientationScreen(navController = navController)
}
composable(route = RootGraphItem.Pronouns.route) {
PronounsScreen(navController = navController)
}
composable(route = RootGraphItem.Interests.route) …Run Code Online (Sandbox Code Playgroud) navigation android kotlin android-jetpack-navigation android-jetpack-compose
我曾尝试阅读此内容,但它并没有解决我的问题
所以我使用此代码导航到下一个目的地
val nextDirection = CreateEventNameFragmentDirections.actionToCreateEventType(userKM, newEvent)
findNavController().navigate(nextDirection)
Run Code Online (Sandbox Code Playgroud)
但它在我错误旋转设备后崩溃
java.lang.IllegalStateException: 没有当前导航节点
我用这个更新gradle
Run Code Online (Sandbox Code Playgroud)implementation 'android.arch.navigation:navigation-fragment-ktx:2.2.1' implementation 'android.arch.navigation:navigation-ui-ktx:2.2.1'
但它仍然不起作用,它仍然崩溃。我该怎么办 ?这是我的主要活动
class MainActivity : AppCompatActivity(), NavController.OnDestinationChangedListener {
private lateinit var navController : NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initial Setup views
navController = Navigation.findNavController(this,R.id.nav_host_fragment)
setupBottomNavMenu()
setupActionBar()
// Add Listeners
navController.addOnDestinationChangedListener(this)
}
private fun setupBottomNavMenu() {
bottom_nav.setupWithNavController(navController)
}
private fun setupActionBar() {
generalToolbar.title = ""
searchToolbar.title = ""
searchWithBackButtonToolbar.title = ""
// set up top hierarchy destination
val appBarConfiguration …Run Code Online (Sandbox Code Playgroud) android android-navigation android-architecture-components android-architecture-navigation android-jetpack-navigation
我正在使用 Jetpack Navigation 进行深层链接。我已添加android:launchMode="singleTask"到我的活动中。如果之前未打开该应用程序,Deeplink 将正确重定向。但是,如果该应用程序存在于内存中,则该应用程序将进入前台,但无法正确打开深层链接。
我的设备是带有 Android 10 的 Pixel 2。我看到onCreate只有在我第一次打开应用程序时才会调用它。但是,onNewIntent每次单击深层链接时都会调用。
是 Jetpack Navigation 中的错误还是我在设置时忘记了某些内容?
我正在尝试从一个导航图(主机片段位于LoginActivity)导航到另一个导航图(主机片段位于HomeActivity)。我知道谷歌提倡使用单一活动应用程序,因此我只会使用这两个活动(以保持最少)。
我的 login_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@id/nav_login">
<fragment
android:id="@+id/nav_login"
android:name="your.appname.LoginFragment"
android:label="@string/login_menu"
tools:layout="@layout/fragment_login" >
<action
android:id="@+id/action_nav_login_to_enterCellphone"
app:destination="@id/login_enter_cellphone"
app:popUpTo="@id/nav_login" />
</fragment>
<fragment
android:id="@+id/login_enter_cellphone"
android:name="your.appname.LoginEnterCellphoneFragment"
android:label="@string/enter_cellphone_fragment_label"
tools:layout="@layout/fragment_login_enter_cellphone" >
<action
android:id="@+id/action_enter_cellphone_to_enterOTPFragment"
app:destination="@id/enterOTPFragment"
app:popUpTo="@id/login_enter_cellphone" />
</fragment>
<fragment
android:id="@+id/enterOTPFragment"
android:name="your.appname.EnterOTPFragment"
android:label="@string/enter_otp_label"
tools:layout="@layout/fragment_enter_o_t_p" >
<action
android:id="@+id/action_enterOTPFragment_to_main_navigation"
app:destination="@id/main_navigation"
app:launchSingleTop="false" />
</fragment>
<include app:graph="@navigation/main_navigation" />
</navigation>
Run Code Online (Sandbox Code Playgroud)
和 main_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_navigation"
app:startDestination="@id/nav_home">
<fragment
android:id="@+id/nav_home"
android:name="your.appname.HomeFragment"
android:label="Home"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/nav_profile"
android:name="your.appname.ProfileFragment"
android:label="@string/profile_menu"
tools:layout="@layout/fragment_profile" />
</navigation> …Run Code Online (Sandbox Code Playgroud) navigation android kotlin android-architecture-navigation android-jetpack-navigation
如何声明具有多个导航参数的导航路线?我查了资料,并且所有 的 这些物品(这似乎只是重申文件说什么),我只能找到途径的例子有一个参数。
这是我所拥有的:
composable(
route = "createExercise/{exerciseId}",
arguments = listOf(navArgument("exerciseId") { type = NavType.IntType })
) { backStackEntry ->
CreateExerciseScreen(
exerciseId = backStackEntry.arguments!!.getInt("exerciseId"),
)
}
Run Code Online (Sandbox Code Playgroud)
这是我想要的:
composable(
route = "createExercise/{exerciseId},{workoutId}",
arguments = listOf(
navArgument("exerciseId") { type = NavType.IntType },
navArgument("workoutId") { type = NavType.IntType },
)
) { backStackEntry ->
CreateExerciseScreen(
exerciseId = backStackEntry.arguments!!.getInt("exerciseId"),
workoutId = backStackEntry.arguments!!.getInt("workoutId"),
)
}
Run Code Online (Sandbox Code Playgroud)
我为上面的例子随意选择了一个逗号分隔的语法来代替我正在寻找的真实语法。
所以,我的问题是:在声明导航路线时,多个参数的正确语法是什么?(可选参数呢?)
我在 Compose 版本中使用 Jetpack Navigation 库。我正在设置导航,就像这里显示的那样
我希望能够从屏幕 A 导航到屏幕 B。一旦 B 执行某些操作并从返回堆栈中弹出,它将返回屏幕 A 可以访问的结果。
我在这里找到了一种使用活动来做到这一点的方法,但我想避免创建任何额外的活动并在撰写中执行此操作。
android android-jetpack android-jetpack-navigation android-jetpack-compose
我正在创建一个带有底部导航和抽屉的简单应用程序。
我将所有屏幕都包裹在带有顶栏和底栏的 Scaffold 中。我想隐藏特定屏幕上的顶部栏和底部栏。有谁知道如何实现
这是设置导航的代码。
val navController = rememberNavController()
val scaffoldState = rememberScaffoldState(rememberDrawerState(DrawerValue.Closed))
Scaffold(
bottomBar = {
AppBottomBar(navController)
},
topBar = {
AppTopBar(scaffoldState)
},
drawerContent = {
DrawerContent(navController, scaffoldState)
},
scaffoldState = scaffoldState
) {
// ovoid bottom bar overlay content
Column(modifier = Modifier.padding(bottom = 58.dp)) {
AppNavigation(navController)
}
}
Run Code Online (Sandbox Code Playgroud)
AppNavigation包含NavHost用于导航到屏幕
android kotlin android-jetpack android-jetpack-navigation android-jetpack-compose
我在这里找到了一个类似的问题。在撰写此问题时,只有此答案可用,这对我没有任何帮助,我相信对提出问题的人也没有任何帮助。
我检查了答案中链接的 repo,它通过在 viewmodel 中创建一个 init 方法并在 Activity/Fragment 中调用它来“解决”问题。
由于viewmodel已经被注入,这个方案对我来说似乎不太理想,我想知道在使用hilt时是否还有其他可用的选项。
android dependency-injection android-viewmodel android-jetpack-navigation dagger-hilt
android ×10
android-jetpack-navigation ×10
kotlin ×3
android-architecture-navigation ×2
navigation ×2
android-architecture-components ×1
dagger-hilt ×1