1. Introduction to project operation
Video demonstration address:https://www.bilibili.com/video/BV1Ju4y1x75p/
2. Specific implementation
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)
}
}
}
}
}
}
}
This is a Kotlin snippet of an Android application built using the Jetpack Compose library and the Navigation Component integrated with Compose. It represents the main activity of an application named "HomeActivity". Let's explain this code step by step:
-
Import statement:
- The code starts with various import statements that bring in the classes and packages required to build Android applications using Jetpack Compose and Navigation Component.
-
Class declaration:
HomeActivity
is declared as a class that extendsComponentActivity
, which is part of the Android Activity Framework.
-
@AndroidEntryPoint
annotation:- This annotation is used to indicate that this activity is part of Hilt's dependency injection system. Hilt is a library for dependency injection on Android.
-
onCreate
function:onCreate
The function is the entry point to this activity and is called when the activity is created.
-
setContent
function:- In the
onCreate
function, use thesetContent
function to set the active content to Compose UI.
- In the
-
Compose UI content:
- Compose UI is defined within a
GoodNewsTheme
composable function. - Using the
Surface
composable function provides a background color based onMaterialTheme
. It takes up the entire screen (usefillMaxSize()
). - Created ViewModel instances for
MainViewModel
andHomeViewModel
(usingviewModel()
). - Use
rememberAnimatedNavController
to create a navigation controller that supports animated transitions between targets.
- Compose UI is defined within a
-
AnimatedNavHost
Composable functions:AnimatedNavHost
is a composable function used for navigation in Compose applications. It is similar to standardNavHost
but supports animation for custom navigation transitions.startDestination
is set toHOME_PAGE
, indicating the initial target.- Various animation transitions are specified for the enter, exit, pop-in, and pop-out transitions using
slideInHorizontally
andslideOutHorizontally
.
-
Combinable goals:
- Within
AnimatedNavHost
, different composable targets are defined for different application pages using thecomposable
function. HOME_PAGE
: Composable function for main page.EPIDEMIC_NEWS_LIST_PAGE
: Composable function for epidemic news list.RISK_ZONE_DETAILS_PAGE
: A composable function used on the risk area details page, accepting parameters such as “title” and “stringList”.WEB_VIEW_PAGE
: Composable function for web view pages, also accepts "title" and "url" as parameters.
- Within
Overall, this code sets up the navigation structure for an Android application built with Jetpack Compose, defining the different pages or destinations and specifying animated transitions between them. It also integrates with Hilt for dependency injection.
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)
}
This is a Kotlin class for handling news data, it appears to be a repository for news applications. Let me explain the main part of this code:
-
Import statement:
- The code starts with statements that import the required classes and packages. These import statements are used to introduce dependencies, including database operations, network requests, and other helper classes.
-
HomeRepository
Class declaration:HomeRepository
The class is a ViewModel scoped class that uses Hilt's@ViewModelScoped
annotation.- It is a dependency injection class, using the
@Inject
annotation, which means that it can be instantiated by a dependency injection framework (such as Hilt).
-
Function definition:
- This class contains multiple functions for obtaining different types of news, such as social news, military news, technology news, financial news, and entertainment news.
- Each function uses the
fire
function to perform asynchronous operations, and these operations run on the IO scheduler (Dispatchers.IO). These functions obtain news data by calling the relevant methods ofNetworkRequest
and return aResult
object based on specific conditions. - If the response code of the obtained news data (
code
) is equal to the specifiedConstant.CODE
, then return successfulResult.success(news)
; Otherwise, return a failedResult
object containing exception information.
-
Get collection news:
getCollectionNews
The function is used to obtain the collected news data from the local database.- It obtains the collected news data by calling the method of the database access object (
collectionNewsDao
) and encapsulates it in < Return in a i=3>.getCollectionNews
Result
-
Save and delete news data:
- has two private suspend functions
insertCollectionNew
anddeleteCollectionNew
for saving and deleting news data in the local database. insertCollectionNew
Inserts the givenCollectionNews
object into the database.deleteCollectionNew
Removes the givenCollectionNews
object from the database.
- has two private suspend functions
In general, this class acts as the middle layer of news data, responsible for obtaining news data from network requests or local databases, and provides interfaces to perform news-related operations, such as obtaining different types of news, obtaining collected news, Save and delete news data. This helps separate data access and business logic, making the application more maintainable.
3. Project source code
–
–
–
Link: https://pan.baidu.com/s/1JjpTLtw3_5iwRbmSGtOP7w?pwd=nljy
Extraction code: nljy
Note: The project has been encrypted, please contact the author V
(Can do experimental reports, code explanations, etc...)
Please send a private message to the author or
(v)15135757306