《Jetpack Compose从入门到实战》第九章 Accompanist 与第三方组件库

目录
- Accompanist
- SystemUiController
- Pager
- SwipeRefresh
- Flow Layout
- Insets
- Lottie
- Coil
- AsyncImage
- SubcomposeAsyncImage
- AsyncImagePainter
Accompanist
- 最新可用版本
- accompanist官方文档
SystemUiController
- 依赖:implementation “com.google.accompanist:accompanist-systemuicontroller:<version>”
@Composable
fun SystemUiTest() {Box(modifier = Modifier.fillMaxSize()) {val systemUiController = rememberSystemUiController()val useDarkIcons = MaterialTheme.colors.isLightSideEffect {systemUiController.setSystemBarsColor(color = Color.Transparent, darkIcons = useDarkIcons)}
// TopAppBar(title = { Text(text = "TopAppBar") }, modifier = Modifier.statusBarsPadding(), backgroundColor = Color.Gray)//使用com.google.accompanist:accompanist-insets-ui:0.30.1 实现沉浸式状态栏的效果TopAppBar(title = { Text(text = "TopAppBar") }, backgroundColor = Color.Gray, contentPadding = WindowInsets.statusBars.asPaddingValues())}
}
@Composable
fun SystemUiControllerDemo() {val systemUiController = rememberSystemUiController()val useDarkIcons = MaterialTheme.colors.isLightval colorPanel = listOf(Color.Gray,Color.Red,Color.Black,Color.Cyan,Color.Transparent,Color.DarkGray,Color.LightGray,Color.Yellow)SideEffect {systemUiController.setSystemBarsColor(Color.Transparent, useDarkIcons)}Column(Modifier.systemBarsPadding().fillMaxSize().background(Color(0xFF0079D3))) {colorPanel.forEach {Box(modifier = Modifier.fillMaxWidth().height(48.dp).background(it).clickable {systemUiController.setSystemBarsColor(it, useDarkIcons)})}}
}
- 略直接设置状态栏和底部导航栏颜色的方法
Pager
- implementation “com.google.accompanist:accompanist-pager:$accompanist_version”
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PagerTest() {Box(modifier = Modifier.fillMaxSize()) {val pagerState = rememberPagerState()val scope = rememberCoroutineScope()HorizontalPager(pageCount = 3, modifier = Modifier.fillMaxSize(), state = pagerState) { page ->when (page) {0 -> ColorBox(color = Color.Blue, pageIndex = page)1 -> ColorBox(color = Color.Cyan, pageIndex = page)2 -> ColorBox(color = Color.Magenta, pageIndex = page)}}SideEffect {scope.launch {delay(3000)pagerState.scrollToPage(2)}}}
}@Composable
fun ColorBox(color: Color, pageIndex: Int) {Box(modifier = Modifier.fillMaxSize().background(color = color), contentAlignment = Alignment.Center) {Text(text = "page $pageIndex")}
}
- 略直接跳转到某个页面的方法
@OptIn(ExperimentalPagerApi::class)
@Composable
fun PagerDemo() {val pagerState = rememberPagerState()val scope = rememberCoroutineScope()var selectedScreens by remember { mutableStateOf(0) }val screens = listOf(Screens("首页", Icons.Filled.Home) { Home() },Screens("我喜欢的", Icons.Filled.Favorite) { Favorite() },Screens("设置", Icons.Filled.Settings) { Settings() })Scaffold(bottomBar = {BottomNavigationBar(selectedScreens,screens,onClick = {selectedScreens = itscope.launch { pagerState.scrollToPage(selectedScreens) }})}) {HorizontalPager(count = screens.size,modifier = Modifier.fillMaxSize(),state = pagerState) { page ->screens.forEachIndexed { index, screens ->when (page) {index -> screens.content()}}}}LaunchedEffect(pagerState) {snapshotFlow { pagerState.currentPage }.collect { page ->selectedScreens = page}}}@Composable
fun Home() {Box(modifier = Modifier.fillMaxSize().background(Color.Gray),contentAlignment = Alignment.Center) {Text(text = "1. 首页🤭",style = MaterialTheme.typography.h5)}
}@Composable
fun Favorite() {Box(modifier = Modifier.fillMaxSize().background(Color(0xFFF8F8F8)),contentAlignment = Alignment.Center) {Text(text = "2. 我喜欢的❤",style = MaterialTheme.typography.h5)}
}
@Composable
fun Settings() {Box(modifier = Modifier.fillMaxSize(),contentAlignment = Alignment.Center) {Text(text = "3. 设置⚙",style = MaterialTheme.typography.h5)}
}
@Composable
fun BottomNavigationBar(selectedScreen: Int,screens: List<Screens>,onClick: (targetIndex: Int) -> Unit
) {NavigationBar {screens.forEachIndexed { index, screen ->NavigationBarItem(icon = { Icon(screen.iconVector, contentDescription = null) },label = { Text(screen.label) },selected = selectedScreen == index,onClick = { onClick(index) })}}
}data class Screens(val label: String,val iconVector: ImageVector,val content: @Composable () -> Unit
)
SwipeRefresh
- implementation “com.google.accompanist:accompanist-swiperefresh:$accompanist_version”
@Preview
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun SwipeRefreshTest() {Box(modifier = Modifier.fillMaxSize()) {val viewModel: MyViewModel = viewModel()val isRefreshing by viewModel.isRefreshing.collectAsState()val background by animateColorAsState(targetValue = viewModel.background, animationSpec = tween(1000), label = "backgroundAnim")/* SwipeRefresh(state = rememberSwipeRefreshState(isRefreshing), onRefresh = { viewModel.refresh() }) {Box(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).background(background))}*/val pullRefreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = { viewModel.refresh() })Box(modifier = Modifier.fillMaxSize().pullRefresh(pullRefreshState).verticalScroll(rememberScrollState()).background(background),) {PullRefreshIndicator(isRefreshing, pullRefreshState, modifier = Modifier.align(Alignment.TopCenter))}}
}class MyViewModel : ViewModel() {private val _isRefreshing = MutableStateFlow(false)private val colorPanel = listOf(Color.Gray, Color.Red, Color.Black, Color.Cyan, Color.DarkGray, Color.LightGray, Color.Yellow)val isRefreshing: StateFlow<Boolean>get() = _isRefreshingvar background by mutableStateOf(Color.Gray)fun refresh() {viewModelScope.launch {_isRefreshing.emit(true)delay(1000)background = colorPanel.random()_isRefreshing.emit(false)}}}
Flow Layout
- 会自动换行的row和Column
- implementation “com.google.accompanist:accompanist-flowlayout:$accompanist_version”
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun FlowLayoutTest() {Column(modifier = Modifier.fillMaxSize()) {FlowRow(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically, maxItemsInEachRow = 3) {Text(text = "text1")Text(text = "text2")Text(text = "text3")Text(text = "text4")Text(text = "text5")Text(text = "text6")}Divider(modifier = Modifier.fillMaxWidth())FlowColumn(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.SpaceEvenly, horizontalAlignment = Alignment.CenterHorizontally, maxItemsInEachColumn = 3) {Text(text = "text1")Text(text = "text2")Text(text = "text3")Text(text = "text4")Text(text = "text5")Text(text = "text6")}}
}
@Composable
fun Tag(modifier: Modifier = Modifier,shape: Shape = CircleShape,elevation: Dp = 0.dp,leadingIcon: @Composable (() -> Unit)? = null,trailingIcon: @Composable (() -> Unit)? = null,text: String,textStyle: TextStyle = TextStyle(fontWeight = FontWeight.Normal,fontSize = 16.sp,letterSpacing = 0.15.sp),backgroundColor: Color = Color(0xFFE8E8E8),border: BorderStroke? = null,onClick:() -> Unit
){Surface(shape = shape,color = backgroundColor,modifier = modifier,elevation = elevation,border = border) {Row(modifier = Modifier.clickable(onClick = onClick).padding(start = 15.dp, end = 15.dp, top = 8.dp, bottom = 8.dp),verticalAlignment = Alignment.CenterVertically,) {when{leadingIcon != null -> {CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high,content = leadingIcon)Spacer(Modifier.padding(horizontal = 4.dp))Text(text = text,style = textStyle,)}trailingIcon != null -> {Text(text = text,style = textStyle,)Spacer(Modifier.padding(horizontal = 4.dp))CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.high,content = trailingIcon)}else -> {Text(text = text,style = textStyle,)}}}}
}@Composable
fun FlowLayoutDemo() {Surface(modifier = Modifier.systemBarsPadding().fillMaxWidth(),elevation = 8.dp) {FlowRow(modifier = Modifier.padding(8.dp),crossAxisSpacing = 12.dp,mainAxisSpacing = 10.dp) {Tag(leadingIcon = {Icon(painterResource(id = R.drawable.wechat), null, tint = Color.White)},text = "WeChat",elevation = 6.dp,textStyle = TextStyle(Color.White),backgroundColor = Color(0xFF07C160)) { }Tag(leadingIcon = {Icon(painterResource(id = R.drawable.twitter), null, tint = Color.White)},text = "Twitter",elevation = 6.dp,textStyle = TextStyle(Color.White),backgroundColor = Color(0xFF1DA1F2)) { }Tag(leadingIcon = {Icon(painterResource(id = R.drawable.github), null, tint = Color.White)},text = "Github",elevation = 6.dp,textStyle = TextStyle(Color.White),backgroundColor = Color(0xFF181717)) { }Tag(leadingIcon = {Icon(painterResource(id = R.drawable.microsoftedge), null, tint = Color(0xFF0078D7))},text = "Edge",elevation = 6.dp) { }Tag(leadingIcon = {Icon(painterResource(id = R.drawable.microsoft), null, tint = Color(0xFF5E5E5E))},text = "Microsoft",elevation = 6.dp) { }}}
}
Insets
- implementation “com.google.accompanist:accompanis-inss-ui:<version>”
@Composable
fun InsetsDemo() {val systemUiController = rememberSystemUiController()val useDarkIcons = MaterialTheme.colors.isLightSideEffect {systemUiController.setSystemBarsColor(Color.Transparent, useDarkIcons)}Scaffold(topBar = {TopAppBar(title = {Text("TopAppBar")},backgroundColor = Color.Gray,contentPadding = WindowInsets.statusBars.asPaddingValues())},modifier = Modifier.fillMaxSize(),contentColor = Color.Black) { }
}
Lottie
- 添加依赖配置 implementation “com.airbnb.android:lottie-compose:$lottieVersion”
- 创建Lottie动画
- 创建两个状态用来描述动画的速度和开始暂停状态
var isPlaying by remember {mutableStateOf(true)}var speed by remember {mutableStateOf(1f)}
- 加载Lottie动画资源,这里用本地加载方式
- Lottie框架提供了加载res/raw,加载URL,加载手机目录下的静态资源,加载asset目录下的静态资源,加载json字符串的功能
val lottieComposition by rememberLottieComposition(spec = RawRes(R.raw.lottie),)
- 接下来创建Lottie动画状态
val lottieAnimationState by animateLottieCompositionAsState (composition = lottieComposition,iterations = LottieConstants.IterateForever,isPlaying = isPlaying,speed = speed,restartOnPlay = false)
- 最后设置动画资源句柄和动画状态
LottieAnimation(lottieComposition,lottieAnimationState,modifier = Modifier.size(400.dp))
Coil
- 添加依赖: implementation “io.coil-kt:coil-compose:$coil_version”
AsyncImage
@Preview
@Composable
fun AsyncImageDemo() {AsyncImage(model = ImageRequest.Builder(LocalContext.current).data(ImageUrl).crossfade(true).build(),//model = (ImageUrl),contentDescription = stringResource(R.string.description),placeholder = painterResource(id = R.drawable.place_holder),error = painterResource(id = R.drawable.error),onSuccess = {Log.d(TAG, "success")},onError = { error ->Log.d(TAG, "error")},onLoading = { loading ->Log.d(TAG, "loading")},modifier = Modifier.clip(CircleShape))
}
SubcomposeAsyncImage
@Preview
@Composable
fun SubcomposeAsyncImageDemo() {SubcomposeAsyncImage(model = "ImageUrl",loading = { CircularProgressIndicator() },contentDescription = "compose_museum")
}
@Preview
@Composable
fun SubcomposeAsyncImageDemo() {SubcomposeAsyncImage(model = "ImageUrl",contentDescription = "compose_museum") {if (painter.state is AsyncImagePainter.State.Loading || painter.state is AsyncImagePainter.State.Error) {CircularProgressIndicator()} else {SubcomposeAsyncImageContent()}}
}
SubcomposeAsyncImage(model = ImageRequest.Builder(LocalContext.current).data(ImageUrl.testUrl1).size(1920,1080),.build(),contentDescription = null,) {val state = painter.statewhen(state) {is AsyncImagePainter.State.Loading -> CircularProgressIndicator()is AsyncImagePainter.State.Error -> Text("${state.result.throwable}")is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent()is AsyncImagePainter.State.Empty -> Text("Empty")}}
AsyncImagePainter
- 这个组件是底层API,使用时会出现很多不可预期的行为,所以建议用前面两个
- 如果项目要求不能用AsyncImage则用这个
- 不能用Success状态来判断,否则图片不能加载成功
val painter = rememberAsyncImagePainter(model = ImageRequest.Builder(LocalContext.current).data("https://pic-go-bed.oss-cn-beijing.aliyuncs.com/img/20220316151929.png").build()
)
if (painter.state is AsyncImagePainter.State.Loading) {CircularProgressIndicator()
}
Image(painter = painter,contentDescription = stringResource(R.string.description)
)
《Jetpack Compose从入门到实战》第一章 全新的 Android UI 框架
《Jetpack Compose从入门到实战》 第二章 了解常用UI组件
《Jetpack Compose从入门到实战》第三章 定制 UI 视图
《Jetpack Compose从入门到实战》第八章 Compose页面 导航
《Jetpack Compose从入门到实战》第九章 Accompanist 与第三方组件库
相关文章:
《Jetpack Compose从入门到实战》第九章 Accompanist 与第三方组件库
目录 AccompanistSystemUiControllerPagerSwipeRefreshFlow LayoutInsets LottieCoilAsyncImageSubcomposeAsyncImageAsyncImagePainter Accompanist 最新可用版本accompanist官方文档 SystemUiController 依赖:implementation “com.google.accompanist:accompa…...
Centos7 docker 容器内root身份应用自启动 /usr/sbin/init 问题
Centos7 docker 容器内root身份应用自启动 & /usr/sbin/init 问题 环境:我在一个 docker 容器内手动安装了 mysql、nginx、autotestsystem(自己的服务); mysql 和 nginx 都做了服务脚本:mysqld.service、nginx.se…...
STL学习笔记之容器
首先我们要学习的是容器 第一个是容器的初始化(构造方式)有三种方式 分别是 第一种 int arr[]{1,2,3} vector<int> v1(arr,arr3) 即容器存放的种类和从另外一个数组去拷贝一段数据。 第二种 vector<int> v2(3,10); 第一个3是指存放…...
Java基础---第十二篇
系列文章目录 文章目录 系列文章目录一、获取一个类Class对象的方式有哪些?二、ArrayList 和 LinkedList 的区别有哪些?三、用过 ArrayList 吗?说一下它有什么特点?一、获取一个类Class对象的方式有哪些? 搞清楚类对象和实例对象,但都是对象。 第一种:通过类对象的 get…...
Acwing 841. 字符串哈希
Acwing 841. 字符串哈希 题目描述思路讲解代码展示 题目描述 思路讲解 代码展示 #include <iostream> #include <algorithm>using namespace std;typedef unsigned long long ULL;const int N 100010, P 131; // P 131 或者13331(经验值)int n, m; char str[N]…...
NEON优化:性能优化经验总结
NEON优化:性能优化经验总结 1. 什么是 NEONArm Adv SIMD 历史 2. 寄存器3. NEON 命名方式4. 优化技巧5. 优化 NEON 代码(Armv7-A内容,但区别不大)5.1 优化 NEON 汇编代码5.1.1 Cortex-A 处理器之间的 NEON 管道差异5.1.2 内存访问优化 Reference: NEON优…...
C++ 并发编程实战 第九章
目录 9.1 线程池 9.1.1 最简易可行的线程池 9.1.2 等待提交给线程池的任务完成运行 9.1.3等待其他任务完成的任务 9.1.4 避免任务队列上的争夺 9.1.5 任务窃取 9.2 中断线程 9.2.1 发起一个线程,以及把他中断 9.2.2 检测线程是否被中断 9.2.3 中断条件变…...
【Java】super 关键字用法
目录 this与super区别 1.访问成员变量-示例代码 继承中构造方法的访问特点 2.访问构造方法-示例代码: 继承中成员方法访问特点 3.访问成员方法-示例代码: super 关键字的用法和 this 关键字相似 this : 代表本类对象的引用super : 代表父类存储空间…...
前端笔试题总结,带答案和解析
1. 执行以下程序,输出结果为() var x 10; var y 20; var z x < y ? x:y; console.log(xx;yy;zz);A x11;y21;z11 B x11;y20;z10 C x11;y21;z10 D x11;y20;z11 初始化x的值为10,y的值为20,x < y返回结果为tru…...
Omniverse Machinima
Omniverse Machinima App | NVIDIA Omniverse Machinima 是 NVIDIA 推出的一款实时动画创作工具,可用于在虚拟世界中制作和操纵角色及其环境。该工具使用 Universal Scene Description (USD) 作为其通用场景描述格式,可与多种 3D 建模、动画和渲染应用程…...
【测试人生】游戏业务测试落地精准测试专项的一些思路
精准测试在互联网领域有广泛的应用。以变更为出发点,通过对变更内容进行分析,可以确定单次变更具体涉及到哪些模块和功能点,以及是否存在夹带风险,从而从QA的视角,可以知道哪些功能模块需要做测试,以及哪些…...
Redis 数据类型底层原理
String 内部编码有三种:int、embstr、raw int:如果一个字符串对象保存的是整数值,并且这个整数值可以用 long类型来表示(不超过 long 的表示范围,如果超过了 long 的表示范围,那么按照存储字符串的编码来存储…...
EasyEdge 智能边缘控制台通过sdk发布应用
离线部署SDK生成 模型部署完成后会出现下载SDK的按钮,点击按钮下载SDK并保存好SDK。 进入EasyDL官网的技术文档 安装智能边缘控制台 跟着教程,完成安装:点此链接 树莓派4b是Linux arm64的架构,点击对应的链接进行下载。 下载完成…...
centos软件设置开机启动的方式
以下以redis作为案例: 开机启动方式一 [Unit] Descriptionredis-server Afternetwork.target [Service] Typeforking # 这里需要修改自己的配置文件 ExecStart/usr/local/bin/redis-server /etc/redis/redis.conf PrivateTmptrue [Install] WantedBymulti-user.tar…...
二叉树和堆
二叉树不存在度大于2的结点(每个根最多只有两个子结点)二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树 两个特殊的二叉树——(满二叉树,完全二叉树) 满二叉树——每个根结点都有左右…...
洛谷P5732 【深基5.习7】杨辉三角题解
目录 题目【深基5.习7】杨辉三角题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1传送门 代码解释亲测 题目 【深基5.习7】杨辉三角 题目描述 给出 n ( n ≤ 20 ) n(n\le20) n(n≤20),输出杨辉三角的前 n n n 行。 如果你不知道什么是杨辉三角…...
Docker 精简安装 Nacos 2.2.1 单机版本
准备工作: 1)已安装docker 2)数据库准备,演示使用MySql5.7版本 1、拉取 [rootTseng-HW ~]# docker pull nacos/nacos-server:v2.2.1 v2.2.1: Pulling from nacos/nacos-server 2d473b07cdd5: Already exists 77c5a601c050: Pul…...
IntelliJ IDEA配置Cplex12.6.3详细步骤
Cplex12.6.3版IntelliJ IDEA配置详细步骤 一、Cplex12.6.3版下载地址二、Cplex安装步骤三、IDEA配置CPLEX3.1 添加CPLEX安装目录的cplex.jar包到项目文件中3.2 将CPLEX的x64_win64文件夹添加到IDEA的VM options中 四、检查IDEA中Cplex是否安装成功卸载Cplex 一、Cplex12.6.3版下…...
2023 年最佳多 GPU 深度学习系统指南
动动发财的小手,点个赞吧! 本文[1]提供了有关如何构建用于深度学习的多 GPU 系统的指南,并希望为您节省一些研究时间和实验时间。 1. GPU 让我们从有趣(且昂贵)的部分开始! 购买 GPU 时的主要考虑因素是&am…...
Kotlin异常处理runCatching,getOrNull,onFailure,onSuccess(1)
Kotlin异常处理runCatching,getOrNull,onFailure,onSuccess(1) fun main(args: Array<String>) {var s1 runCatching {1 / 1}.getOrNull()println(s1) //s11,打印1println("-")var s2 ru…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
