为Android构建现代应用——主体结构
创建Screents和ViewModels
在前面的章节中,我们已经分析了OrderNow项目的理论概念和我们将赋予的组织。
在本章中,我们将开始实现初始结构和模板,这将联接每一个应用程序的部分。
首先将添加以下带有各自视图模型的主屏幕:
• 首页
• 产品列表
• 产品详情
• 购物车
添加元素的一个例子如下图所示:
Sreens 和 ViewModels
我们将在应用程序中使用依赖管理器将每个ViewModel绑定到各自的屏幕上。为此,我们必须首先在应用程序中依赖Hilt。
implementation 'com.google.dagger:hilt-android:2.38.1' // Use the latest version kapt 'com.google.dagger:hilt-android-compiler:2.38.1' // Use the latest version
在依赖Hilt的过程后,将要求定义应用类型类,例如在我们的示例项目中,将定义为OrderNowApplication,如下:
@HiltAndroidApp class OrderNowApplication:Application() { }
注意:在androidmanifest .xml中注册OrderNowApplication类
<application
android:name=".main.OrderNowApplication"
android:allowBackup="true"
...>
此外,我们将 Navigation Compose依赖到项目中,这将允许View(Composable)在导航期间获得其各自ViewModel的实例:
dependencies {
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
}
一旦在项目中正确地执行了前面的配置,我们就可以像这样将ViewModel注入View:
Home ViewModel:
@HiltViewModel
class HomeViewModel @Inject constructor() : ViewModel() {
...
}
Home Screen:
@Composable
fun HomeScreen(viewModel: HomeViewModel = hiltViewModel()
) {
...
}
每个屏幕都将通过Hilt依赖管理器与其相应的ViewModel相关联。到目前为止,我们已经集成了以下架构组件:Compose、Navigation和ViewModel。
这是Jetpack工具的完美组合,在后面的章节中,我们将看到它在移动开发中的潜力。
UI模式:TopAppBar和BottomAppBar
通过Scaffold组件,我们可以在应用程序中实现两种在Material Design中最常见的UI模式:TopAppBar和BottomAppBar。
Scaffold是一个详细的视图(composable),它将允许我们以以下方式实现这些模式:
Scaffold:
Scaffold(
topBar = {
TopAppBar { /* Top app bar content */ }
},
bottomBar = {
BottomAppBar { /* Bottom app bar content */ }
}
) { contentPadding -> 9 // Screen content
}
在代码片段中,我们定义了topBar,bottomBar,和(还未添加的)屏幕内容。
在Scaffold中,topBar和bottomBar部分是可选的;也就是说,可以省略其中一部分的定义。此外,在Scaffold中,我们可以声明两个更多的组件:
• scaffoldState
• snackbarHost
在下一章,我们将看到每个的用法。现在我们只定义topBar和bottomBar。 现在我们知道如何在我们的应用程序中包含这些UI模式,下一步就是创建代表TopAppBar和BottomAppBar的视图(Composables)。
我们将其组织在一个叫做patterns的目录中,并在其中添加了两个Views,OrderNowTopBar和OrderNowBottomBar,如下所示:
TopAppBar and BottomAppBar Composables:
OrderNowTopBar
OrderNowTopBar的实现很简单。我们最初只需要以以下方式实现它:
@Composable
fun OrderNowTopBar() {
TopAppBar(
title = {
Text(
text = stringResource(id = AppString.app_name),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
},
backgroundColor = MaterialTheme.colors.background,
contentColor = contentColorFor(MaterialTheme.colors.background)
)
}
之前的实现还不包含返回选项等元素;然而,在后面的章节中添加“Back”到TopAppBar中,它将包含这样一个使用状态策略的导航选项。
OrderNowBottomBar
OrderNowBottomBar的实现可以更精细一些,因为我们需要包括屏幕之间的导航。但是,我们将把实现细节留到下一章。
现在,我们将包含一个没有导航的静态定义。
@Composable
fun OrderNowBottomBar() {val selectedIndex = remember { mutableStateOf(0) }BottomNavigation(backgroundColor = MaterialTheme.colors.background,contentColor = contentColorFor(MaterialTheme.colors.background),elevation = 10.dp) {BottomNavigationItem(icon = {Icon(imageVector = Icons.Default.Home, "")},label = { Text(text = "Home") },selected = (selectedIndex.value == 0),unselectedContentColor = Color.Gray,selectedContentColor = orange,onClick = {selectedIndex.value = 0})BottomNavigationItem(icon = {Icon(imageVector = Icons.Default.ShoppingCart, "")},label = { Text(text = "Cart") },selected = (selectedIndex.value == 1),unselectedContentColor = Color.Gray,selectedContentColor = orange,onClick = {selectedIndex.value = 1})}
}
在这个阶段,我们已经有了屏幕、视图模型和Scaffold的定义(其中包括OrderNowBottomBar和OrderNowTopBar)。
下一步是将所有的部分组合在一起,我们将在下一部分中做这个。
将所有元素整合在一起
第一项任务是创建一个名为main的目录。这个目录将是横向的,并将包含App的基类或结构。
在该目录中,我们放置Application类,移动MainActivity到那里,以及应用程序的主屏幕,我们将其命名为OrderNowScreen,如下图所示。
Main Components:
现在我们修改MainActivity.kt类,以便它将登录屏幕加载到OrderNowScreen应用程序,如下所示:
@AndroidEntryPoint
class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {OrderNowScreen()}}
}
然后,在OrderNowScreen视图中,我们像这样定义应用程序的Scaffold:
@Composable
fun OrderNowScreen() {InitialSkeletonTheme {Surface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colors.background) {Scaffold(topBar = { OrderNowTopBar() },bottomBar = { OrderNowBottomBar() }) { contentPadding ->println(contentPadding)}}}
}
当您运行应用程序时,结果应该类似于以下图像:
总结
在本章中,我们已经构建了OrderNow项目的初始结构。
这里定义和实现的组件将是下一章继续讨论导航的基础。
随着我们阅读这些章节,我们将改进OrderNow的每个部分的实现,因此.我们的电子贸易将以最佳方式设计和实施。
源码:
class MainActivity4: ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent{OrderNowScreen()}}
}
@Preview
@Composable
fun OrderNowScreen() {MyTestTheme {Surface(modifier = Modifier.fillMaxSize(),color=MaterialTheme.colors.background){Scaffold(topBar = {OrderNowTopBar()},bottomBar={ OrderNowBottomBar()}) {contentPadding ->println(contentPadding)}}}
}@Preview
@Composable
fun OrderNowBottomBar(){val selectedIndex =remember{ mutableStateOf(0)}BottomNavigation(backgroundColor = MaterialTheme.colors.background,contentColor=contentColorFor(MaterialTheme.colors.background),elevation = 10.dp){BottomNavigationItem(icon = { Icon(imageVector = Icons.Default.Home,"") },label = { Text(text = "首页")},selected =(selectedIndex.value == 0) ,unselectedContentColor = Color.Gray,selectedContentColor = Color.Red,onClick = { selectedIndex.value = 0 })BottomNavigationItem(icon={Icon(imageVector = Icons.Default.Favorite,"")},label = {Text(text="热门")},selected = (selectedIndex.value== 1),unselectedContentColor =Color.Gray,selectedContentColor = Color.Red,onClick ={selectedIndex.value=1})BottomNavigationItem(icon = { Icon(imageVector = Icons.Default.ShoppingCart,"") },label = { Text(text = "购物车")},selected =(selectedIndex.value == 2) ,unselectedContentColor = Color.Gray,selectedContentColor = Color.Red,onClick = { selectedIndex.value = 2 })BottomNavigationItem(icon={Icon(imageVector = Icons.Default.Person,"")},label = {Text(text="我的")},selected = (selectedIndex.value== 3),unselectedContentColor =Color.Gray,selectedContentColor = Color.Red,onClick ={selectedIndex.value=3})}
}@Composable
fun OrderNowTopBar() {TopAppBar(title = {Text(text = stringResource(id = R.string.app_name),textAlign = TextAlign.Center,modifier = Modifier.fillMaxWidth())},backgroundColor = MaterialTheme.colors.background,contentColor = contentColorFor(MaterialTheme.colors.background))
}@HiltAndroidApp
class OrderNowApplication : Application() {
}
相关文章:

为Android构建现代应用——主体结构
创建Screents和ViewModels 在前面的章节中,我们已经分析了OrderNow项目的理论概念和我们将赋予的组织。 在本章中,我们将开始实现初始结构和模板,这将联接每一个应用程序的部分。 首先将添加以下带有各自视图模型的主屏幕: •…...
【shell脚本】shell脚本之日志切割(进阶实战三)
恭喜你,找到宝藏博主了,这里会分享shell的学习整过程。 shell 对于运维来说是必备技能之一,它可以提高很多运维重复工作,提高效率。 shell的专栏,我会详细地讲解shell的基础和使用,以及一些比较常用的she…...
VMLogin和虚拟机里的浏览器有什么区别?
虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统。 指纹浏览器,也称防关联浏览器。 简单来说,就是允许在同一台电设备上操作和管理多个平台、多个账号,账…...
unimrcp server的session资源分配与回收
unimrcp使用APR的内存池管理内存,因此,处理函数中一般都会传递一个pool指针,需要内存时,就从pool里分配一块,一般也不需要关心内存的释放。因为,一路呼叫关联一个session,一个session对应一个po…...
【图论】三种中心性 —— 特征向量、katz 和 PageRank
维基百科:在图论和网络分析中,中心性指标为图中相应网络位置的节点分配排名或数值。中心性这一概念最初起源于社交网络分析,因此很多衡量中心性的术语也反映了其社会学背景。 不同中心性指标对 “重要” 的衡量方式不同,因此适用于…...
[sqoop]将hive查询后的数据导入到MySQL
一、知识点 export:将Hive的表导入到mysql叫导出 搜了很多,发现sqoop在hive导出到mysql时 1)不支持where参数对数据进行过滤。 2)不支持指定hive表的方式导出,只能指定Hive目录进行导出。 二、操作 1、在MySQL中建表 creat…...
Linux df、du命令
df:查看文件系统硬盘使用情况 df 命令,用于显示 Linux 系统中各文件系统的硬盘使用情况,包括文件系统所在硬盘分区的总容量、已使用的容量、剩余容量等。 df 命令的基本格式为: [rootlocalhost ~]# df [选项] [目录或文件名] df…...

java版+免费商城搭建+小程序商城免费搭建+Spring Cloud + Spring Boot + MybatisPlus + 前后端分离 + 二次开发
J2EE企业分布式微服务云快速开发架构 Spring CloudSpring Boot2MybatisOauth2ElementUI 前后端分离 1. 鸿鹄Cloud架构清单 2. Commonservice(通用服务) 通用服务:对spring Cloud组件的使用&封装,是一套完整的针对于分布式微…...

软件设计师学习第一章
计算机组成与体系结构(6分) 内容概述 数据的表示 进制转换 R 进制转十进制使用按权展开法,其具体操作方式为:将 R 进制数的每一位数值用 Rk 形示,即幂的底数是 R ,指数为 k , k 与该位和小数点…...

蓝桥杯单片机第十一届国赛 真题+代码
iic.c /* # I2C代码片段说明1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题中对单片机时钟频率的要求,进行代码调试和修改。 */ #include <STC1…...

IDC报告背后:大模型时代,重新理解AI公有云
大模型之于AI公有云的意义,在于大模型可以改变过去“手工作坊定制算法”的高成本模式,转向“工厂模式”,只需要微调和精调,就可以形成针对性的场景算法。 作者|葛覃 出品|产业家 一年前,依然有不少云计算从业者思…...
UNH-IOL Reservation 一致性测试用例【7】- 清除Reservation
Reservation 系列导航 UNH-IOL Reservation 一致性测试用例【1】- Reservation Report 命令验证 UNH-IOL Reservation 一致性测试用例【2】- Reservation注册 UNH-IOL Reservation 一致性测试用例【3】- 取消注册 UNH-IOL Reservation 一致性测试用例【4】- Reservation Acqui…...

Python 生成随机图片验证码
使用Python生成图片验证码 Python 生成随机图片验证码安装pillow包pillow包生成图片基本用法生成图片验证码 Python 生成随机图片验证码 在写一个Web项目的时候一般要写登录操作,而为了安全起见,现在的登录功能都会加上输入图片验证码这一功能ÿ…...
一些有趣的 js 功能函数
一些有趣的 js 功能函数 数组生成数组打乱数组数组简单数据去重数组唯一值数据去重多数组取交集查找最大值索引查找最小值索引找到最接近的数值压缩多个数组(拉链函数)矩阵交换行和列 数字转换进制转换 正则手机号格式化去除多余空格 web重新加载当前页面…...

摄像头m2dock(MAIX-II DOCK)
官方文档地址 https://wiki.sipeed.com/soft/maixpy3/zh/index.html 一、软件准备 1 烧录镜像软件 2 镜像 当前最近版本镜像文件 3 SDFormatter 4 Maixpy IDE 二、SD卡准备 1 格式化SD卡(用SDFormatter) 2 烧录 3 弹出,插入开发板中 出现…...
SpringBoot 如何优雅的进行全局异常处理
在SpringBoot的开发中,为了提高程序运行的鲁棒性,我们经常需要对各种程序异常进行处理,但是如果在每个出异常的地方进行单独处理的话,这会引入大量业务不相关的异常处理代码,增加了程序的耦合,同时未来想改…...

OSPF路由协议(红茶三杯CCNA)
链路状态路由协议 OSPF(开放式最短路径优先)Open Shortest Path First 是一种链路状态路由协议,无路由循环(全局拓扑),RFC2328 “开放”意味着非私有的 管理型距离:110 OSPF采用SPF算法计算到达…...

redis中使用bloomfilter判断元素是否存在
一 bloomfiler的作用 1.1 bloomfilter的作用 由一个初始值为0的bit数组组成,和多个hash函数构成,用来判断集合中是否存在某个元素。 一个很长的二进制数组(00000000)一系列随机hash算法映射函数。主要用于判断一个元素是否存在…...

互联网医院系统源码实现:打造现代化医疗服务平台
摘要 本文将介绍一个基于Python的简化版互联网医院系统的源码实现,主要包含用户注册与登录、医生信息管理、在线预约挂号、在线问诊与咨询、电子病历管理、在线支付与结算等功能。该源码实现仅为示例,实际开发中需要考虑更多的业务逻辑和安全性。 1. …...

每天100w次登陆请求, 8G 内存该如何设置JVM参数?
一、新系统上线如何规划容量? 1.套路总结 任何新的业务系统在上线以前都需要去估算服务器配置和JVM的内存参数,这个容量与资源规划并不仅仅是系统架构师的随意估算的,需要根据系统所在业务场景去估算,推断出来一个系统运行模型&…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...