一.项目运行介绍
视频演示地址:https://www.bilibili.com/video/BV1Ju4y1x75p/
二.具体实现
package com.llw.goodnews.ui.activity
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.composable
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import com.llw.goodnews.ui.pages.EpidemicNewsListPage
import com.llw.goodnews.ui.pages.HomePage
import com.llw.goodnews.ui.pages.PageConstant.EPIDEMIC_NEWS_LIST_PAGE
import com.llw.goodnews.ui.pages.PageConstant.HOME_PAGE
import com.llw.goodnews.ui.pages.PageConstant.RISK_ZONE_DETAILS_PAGE
import com.llw.goodnews.ui.pages.PageConstant.WEB_VIEW_PAGE
import com.llw.goodnews.ui.pages.RiskZoneDetailsPage
import com.llw.goodnews.ui.pages.WebViewPage
import com.llw.goodnews.ui.theme.GoodNewsTheme
import com.llw.goodnews.viewmodel.HomeViewModel
import com.llw.goodnews.viewmodel.MainViewModel
import dagger.hilt.android.AndroidEntryPoint
/**
* 主页面
*/
@AndroidEntryPoint
class HomeActivity : ComponentActivity() {
@ExperimentalAnimationApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
GoodNewsTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
val viewModel: MainViewModel = viewModel()
val homeViewModel: HomeViewModel = viewModel()
val navController = rememberAnimatedNavController()
AnimatedNavHost(
navController = navController,
startDestination = HOME_PAGE,
//进入动画
enterTransition = {
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
)
},
//退出动画
exitTransition = {
slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(500)
)
},
popEnterTransition = {
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(500)
)
},
popExitTransition = {
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(500)
)
}
) {
//主页面
composable(HOME_PAGE) {
HomePage(navController,homeViewModel)
}
//疫情新闻列表页面
composable(EPIDEMIC_NEWS_LIST_PAGE) {
EpidemicNewsListPage(navController, viewModel)
}
//风险区详情页面
composable(
"$RISK_ZONE_DETAILS_PAGE/{title}/{stringList}",
arguments = listOf(
navArgument("title") {
type = NavType.StringType //数据类型
},
navArgument("stringList") {
type = NavType.StringType
}
)
) {
val title = it.arguments?.getString("title") ?: "风险区详情"
val stringList = it.arguments?.getString("stringList")
RiskZoneDetailsPage(navController, title, stringList)
}
//WebView页面
composable(
"$WEB_VIEW_PAGE/{title}/{url}",
arguments = listOf(
navArgument("title") {
type = NavType.StringType
},
navArgument("url") {
type = NavType.StringType
},
)
) {
val title = it.arguments?.getString("title") ?: "WebView页面"
val url = it.arguments?.getString("url") ?: "WebViewUrl"
WebViewPage(navController, title, url)
}
}
}
}
}
}
}
这是一个使用Jetpack Compose库和与Compose集成的Navigation Component构建的Android应用程序的Kotlin代码段。它代表了一个名为"HomeActivity"的应用程序的主活动。让我们逐步解释这段代码:
-
导入语句:
- 代码以各种导入语句开始,这些语句引入了使用Jetpack Compose和Navigation Component构建Android应用程序所需的类和包。
-
类声明:
HomeActivity
被声明为一个类,它扩展了ComponentActivity
,这是Android活动框架的一部分。
-
@AndroidEntryPoint
注解:- 此注解用于指示此活动是Hilt依赖注入系统的一部分。Hilt是用于Android上的依赖注入的库。
-
onCreate
函数:onCreate
函数是此活动的入口点,并在创建活动时调用。
-
setContent
函数:- 在
onCreate
函数内,使用setContent
函数设置了活动的内容为Compose UI。
- 在
-
Compose UI 内容:
- Compose UI 在
GoodNewsTheme
可组合函数内定义。 - 使用
Surface
可组合函数提供了基于MaterialTheme
的背景颜色。它占据整个屏幕(使用fillMaxSize()
)。 - 创建了
MainViewModel
和HomeViewModel
的 ViewModel 实例(使用viewModel()
)。 - 使用
rememberAnimatedNavController
创建支持在目标之间执行动画过渡的导航控制器。
- Compose UI 在
-
AnimatedNavHost
可组合函数:AnimatedNavHost
是一个用于Compose应用程序中的导航的可组合函数。它类似于标准的NavHost
,但支持自定义导航过渡的动画。startDestination
设置为HOME_PAGE
,表示初始目标。- 使用
slideInHorizontally
和slideOutHorizontally
为进入、退出、弹出进入和弹出退出过渡指定了各种动画过渡。
-
可组合目标:
扫描二维码关注公众号,回复: 17133455 查看本文章- 在
AnimatedNavHost
内,使用composable
函数为不同的应用程序页面定义了不同的可组合目标。 HOME_PAGE
:用于主页面的可组合函数。EPIDEMIC_NEWS_LIST_PAGE
:用于疫情新闻列表的可组合函数。RISK_ZONE_DETAILS_PAGE
:用于风险区域详情页面的可组合函数,接受参数如 “title” 和 “stringList”。WEB_VIEW_PAGE
:用于Web视图页面的可组合函数,还接受 “title” 和 “url” 作为参数。
- 在
总的来说,这段代码为使用Jetpack Compose构建的Android应用程序设置了导航结构,定义了不同的页面或目标,并指定了它们之间的动画过渡。它还与Hilt集成,用于依赖注入。
package com.llw.goodnews.repository
import com.llw.goodnews.App
import com.llw.goodnews.db.bean.CollectionNews
import com.llw.goodnews.db.bean.News
import com.llw.goodnews.network.NetworkRequest
import com.llw.goodnews.utils.Constant.CODE
import dagger.hilt.android.scopes.ViewModelScoped
import kotlinx.coroutines.Dispatchers
import javax.inject.Inject
/**
* 新闻数据
* @description HomeRepository
* @author llw
*/
@ViewModelScoped
class HomeRepository @Inject constructor() : BaseRepository() {
/**
* 获取社会新闻
*/
fun getSocialNews() = fire(Dispatchers.IO) {
val news = NetworkRequest.getSocialNews()
if (news.code == CODE) Result.success(news)
else Result.failure(RuntimeException("getNews response code is ${news.code} msg is ${news.msg}"))
}
/**
* 获取军事新闻
*/
fun getMilitaryNews() = fire(Dispatchers.IO) {
val news = NetworkRequest.getMilitaryNews()
if (news.code == CODE) Result.success(news)
else Result.failure(RuntimeException("getNews response code is ${news.code} msg is ${news.msg}"))
}
/**
* 科技新闻
*/
fun getTechnologyNews() = fire(Dispatchers.IO) {
val news = NetworkRequest.getTechnologyNews()
if (news.code == CODE) Result.success(news)
else Result.failure(RuntimeException("getNews response code is ${news.code} msg is ${news.msg}"))
}
/**
* 财经新闻
*/
fun getFinanceNews() = fire(Dispatchers.IO) {
val news = NetworkRequest.getFinanceNews()
if (news.code == CODE) Result.success(news)
else Result.failure(RuntimeException("getNews response code is ${news.code} msg is ${news.msg}"))
}
/**
* 娱乐新闻
*/
fun getAmusementNews() = fire(Dispatchers.IO) {
val news = NetworkRequest.getAmusementNews()
if (news.code == CODE) Result.success(news)
else Result.failure(RuntimeException("getNews response code is ${news.code} msg is ${news.msg}"))
}
/**
* 获取收藏新闻
*/
fun getCollectionNews() = fire(Dispatchers.IO) {
val collectionNews = App.db.collectionNewsDao().getCollectionNews()
if (collectionNews.isNotEmpty()) Result.success(collectionNews)
else Result.failure(RuntimeException("getCollectionNews response is null"))
}
/**
* 保存新闻数据
*/
private suspend fun insertCollectionNew(collectionNews: CollectionNews) =
App.db.collectionNewsDao().insert(collectionNews)
/**
* 删除新闻数据
*/
private suspend fun deleteCollectionNew(collectionNews: CollectionNews) =
App.db.collectionNewsDao().delete(collectionNews)
}
这是一个用于处理新闻数据的Kotlin类,它似乎是一个用于新闻应用程序的存储库(Repository)。让我解释一下这个代码的主要部分:
-
导入语句:
- 代码开始以导入所需的类和包的语句。这些导入语句用于引入依赖项,包括数据库操作、网络请求以及其他辅助类。
-
HomeRepository
类声明:HomeRepository
类是一个ViewModel作用域的类,它使用了Hilt的@ViewModelScoped
注解。- 它是一个依赖注入的类,使用了
@Inject
注解,这表示它可以被依赖注入框架(如Hilt)实例化。
-
函数定义:
- 这个类包含了多个用于获取不同类型新闻的函数,例如社会新闻、军事新闻、科技新闻、财经新闻和娱乐新闻。
- 每个函数都使用
fire
函数来执行异步操作,并且这些操作在IO调度器(Dispatchers.IO)上运行。这些函数通过调用NetworkRequest
的相关方法来获取新闻数据,并根据特定的条件返回一个Result
对象。 - 如果获取的新闻数据的响应代码(
code
)等于指定的Constant.CODE
,则返回成功的Result.success(news)
;否则,返回一个包含异常信息的失败的Result
对象。
-
获取收藏新闻:
getCollectionNews
函数用于从本地数据库获取已收藏的新闻数据。- 它通过调用数据库访问对象(
collectionNewsDao
)的getCollectionNews
方法来获取收藏的新闻数据,并将其封装在Result
中返回。
-
保存和删除新闻数据:
- 有两个私有挂起函数
insertCollectionNew
和deleteCollectionNew
用于在本地数据库中保存和删除新闻数据。 insertCollectionNew
将给定的CollectionNews
对象插入到数据库中。deleteCollectionNew
从数据库中删除给定的CollectionNews
对象。
- 有两个私有挂起函数
总的来说,这个类充当了新闻数据的中间层,负责从网络请求或本地数据库中获取新闻数据,并提供接口来执行与新闻相关的操作,如获取不同类型的新闻、获取收藏的新闻、保存和删除新闻数据。这有助于将数据访问和业务逻辑分离,使应用程序更具可维护性。
三.项目源码
–
–
–
链接:https://pan.baidu.com/s/1JjpTLtw3_5iwRbmSGtOP7w?pwd=nljy
提取码:nljy
注:项目已加密,请联系作者V
(可做实验报告,代码讲解等…)
请私信作者或
(v)15135757306