Android Graduation Project Practical Project (21) News App (Category: Society, Military, Technology, Finance, Entertainment) [Can be used for Android graduation or Android course assignments] (See the source code at the end of the article)

1. Introduction to project operation


Video demonstration address:https://www.bilibili.com/video/BV1Ju4y1x75p/


image-20231005171527290

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:

  1. 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.
  2. Class declaration:

    • HomeActivity is declared as a class that extends ComponentActivity, which is part of the Android Activity Framework.
  3. @AndroidEntryPointannotation:

    • 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.
  4. onCreatefunction:

    • onCreateThe function is the entry point to this activity and is called when the activity is created.
  5. setContentfunction:

    • In the onCreate function, use the setContent function to set the active content to Compose UI.
  6. Compose UI content:

    • Compose UI is defined within a GoodNewsTheme composable function.
    • Using the Surface composable function provides a background color based on MaterialTheme. It takes up the entire screen (use fillMaxSize()).
    • Created ViewModel instances for MainViewModel and HomeViewModel (using viewModel()).
    • Use rememberAnimatedNavController to create a navigation controller that supports animated transitions between targets.
  7. AnimatedNavHostComposable functions:

    • AnimatedNavHost is a composable function used for navigation in Compose applications. It is similar to standard NavHost but supports animation for custom navigation transitions.
    • startDestination is set to HOME_PAGE, indicating the initial target.
    • Various animation transitions are specified for the enter, exit, pop-in, and pop-out transitions using slideInHorizontally and slideOutHorizontally.
  8. Combinable goals:

    • Within AnimatedNavHost, different composable targets are defined for different application pages using the composable 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.

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:

  1. 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.
  2. HomeRepositoryClass declaration:

    • HomeRepositoryThe 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).
  3. 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 of NetworkRequest and return a Result object based on specific conditions.
    • If the response code of the obtained news data (code) is equal to the specified Constant.CODE, then return successfulResult.success(news) ; Otherwise, return a failedResult object containing exception information.
  4. Get collection news:

    • getCollectionNewsThe 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>. getCollectionNewsResult
  5. Save and delete news data:

    • has two private suspend functions insertCollectionNew and deleteCollectionNew for saving and deleting news data in the local database.
    • insertCollectionNew Inserts the given CollectionNews object into the database.
    • deleteCollectionNew Removes the given CollectionNews object from the database.

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


おすすめ

転載: blog.csdn.net/m0_63324772/article/details/133581702