先梳理一下我们现在有的页面:
MainPage,主页面,用于显示小说列表
FictionNamePage,新建小说和修改小说名字页面
ChapterListPage,章节列表页面,主要显示一本小说下的所有章节以及这本小说的总字数
WriteTextPage,写小说页面,主要用来写小说内容,并实现保存新建等一系列基础功能
好,截止到目前为止,我们以及实现了主页面的列表显示,其他页面的UI设计,主页和新建小说页的相互跳转等功能。
那么本篇主要是顺着制作计划,完成ChapterListPage的跳转和列表实现。
1、ChapterListPage页面跳转实现
之前的代码编写中,跳转到ChapterListPage时,需要好几个参数,比如小说ID,小说名称,小说总字数等,但是这会导致页面传递参数的冗长,甚至在之后的页面跳转中携带的传递参数会进一步增加,导致代码逻辑混乱。
因此,为了解决这种传递参数混乱的问题,最终决定只传递小说ID这一个变量,剩余变量将在ChapterListPage中通过小说ID查询数据库获得。
所以,PageNavHost中代码如下:
// 给章节列表页指定路径
composable(
"chapter_list_page/{fictionId}",
arguments = listOf(
navArgument("fictionId") { type = NavType.IntType },
)
) { backStackEntry ->
ChapterListPage(navController, backStackEntry)
}
MainPage中的导航路线也立刻变得十分简短:
Card(
onClick = {
// 导航到ChapterListPage可组合项
navController.navigate("chapter_list_page/${it.fictionId}")
},
参数传递过去,ChapterListPage中自然要进行接受:
val fictionId = backStackEntry.arguments?.getInt("fictionId")
返回键的代码:
IconButton(onClick = {
navController.popBackStack("main_page", false)
}
,modifier = Modifier.size(50.dp),) {
Image(painter = painterResource(id = R.drawable.btn_back),
contentDescription = "add a book" )
}
这样就完成了跳转。
2、ChapterListPage初始化页面时进行数据库查询获得相关数据
现在到达ChapterListPage的只有一个fictionId,我们必须要借助这个id来从数据库中获得对应的数据,但是涉及到数据库的操作都是suspend挂起函数,并不能在主线程中执行,我们要如何实现呢?
没错这时候就要用到一个函数【LaunchedEffect】:
fun ChapterListPage(
navController: NavController, backStackEntry: NavBackStackEntry,
viewModel: ChapterListViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
var fictionName by remember { mutableStateOf("") }
var textNumber by remember { mutableStateOf(0) }
val fictionId = backStackEntry.arguments?.getInt("fictionId")
var showTextNumber = ""
LaunchedEffect(key1 = Any(), block = {
fictionName = viewModel.getBook(fictionId!!).fictionName
textNumber = viewModel.getBook(fictionId).textNumber
showTextNumber = if (textNumber>9999){
"%.1f".format(textNumber.toFloat()/10000)+ "w字"
}else{
textNumber.toString() + "字"
}
})
}
LaunchedEffect这个函数,会在每次Composable函数重组时激活,其中可以运行挂起函数,它的key是一个标识符,当他等于Any的时候就是每次重组都会执行,换成固定值则只有对应值才会执行,但是我没太搞明白,现在特定条件下触发的话,最好用if语句。
而通过remember创建的变量就能很好的保存在其他线程上此变量的变化值。
所以通过这样,我们就能完美地在ChapterListPage中查询数据库了。
但是这样可能在性能上就不如传递参数快了,毕竟传递参数是直接拿来用,这种方式还得再查询一波,耗时是肯定的,之后会继续看看有没有什么更省力的方法。