Android全新UI框架之常用ComposeUI组件
在Compose中,每个组件都是一个带有@Composable注解的函数,被称为Composable。Compose已经预置了很多基于MD设计规范的Composable组件。
在布局方面,Compose提供了Column、Row、Box三种布局组件(感觉跟flutter差不多),类似于传统视图开发中的LinearLayout(Vertical)、LinearLayout(Horizontal)、RelateiveLayout,可以满足各类产品的常见布局需求。
Modifier修饰符
在传统开发中,使用xml文件来描述组件的样式,而compose则是使用Modifier修饰符。Modifier允许我们通过链式调用的方式为组件应用一系列的样式设置,如边距、字体、位移等。在Compose中,每个基础的Composable组件都有一个modifier参数,通过传入自定义的Modifier来修改组件的样式。
-
常见修饰符
Modifier.size 设置被修饰组件的大小 Image( painter = painterResource(id = R.drawable.ic_launcher),contentDescription = null, modifier = Modifier.size(width = 10.dp, height = 10.dp) )
Modifier.background 设置被修饰组件的背景颜色。背景色支持纯色背景,也可以使用brush设置渐变背景 Image(painter = painterResource(id = R.drawable.ic_launcher),contentDescription = null,modifier = Modifier.size(width = 100.dp, height = 100.dp).background(brush = Brush.verticalGradient(colors = listOf(Color.Blue,Color.Red)))))
Modifier.fillMaxXXX() 让组件在高度或者宽度上填满父空间 fillMaxSize():填满整个父空间, fillMaxHeight():高度填满父空间,fillMaxWidth():宽度填满父空间 Modifier.border&Modifier.padding border用来为被修饰组件添加边框。边框可以指定颜色、粗细、以及通过shape指定形状。padding用来为被修饰组件增加间隙。可以在border前后各插入一个padding,区分对外和对内的间距 Box(modifier = Modifier.padding(5.dp).border(2.dp, Color.Green, shape = RoundedCornerShape(2.dp)).padding(5.dp)) { Spacer(modifier = Modifier.size(width = 100.dp, height = 10.dp).background(Color.Blue)) }
Modifier.offset 用来移动被修饰组件的位置,分别传入水平方向和垂直方向的偏移量即可 Box(modifier = Modifier.size(100.dp).background(Color.Blue).offset(x = 10.dp, y = 10.dp).background(Color.Cyan)) {}
-
作用域限定Modifier修饰符
Compose充分发挥kotlin的语法特性,让某些Modifier修饰符只能在特定作用域中使用,有利于类型安全地调用它们。所谓“作用域”,在kotlin中就是一个带有Receiver的代码块。注意Receiver代码块默认可以跨层级访问。在compose的DSL中,一般只需要调用当前作用域的方法,为此可以通过@LayoutScopeMarker注解来规避该问题。常见组件的Receiver作用域类型均已使用@LayoutScopeMarker注解进行了声明,使用了该注解之后,像跨级调用外层作用域的方法必须通过显式指明Receiver具体类型。@LayoutScopeMarker @Immutable interface ColumnScope
常见的作用域限定Modifier修饰符:
-
matchParentSize
matchParentSize是只能在BoxScope中使用的作用域限定修饰符。当使用matchParentSize设置尺寸时,可以保证当前组件的尺寸与父组件相同。而父组件默认的是wrapContent。如果使用fillMaxSize取代matchParentSize,那么该组件的尺寸会被设置为父组件所允许的最大尺寸,这样会导致背景铺满整个屏幕,二者区别如下图所示。Column(modifier = Modifier.background(Color.DarkGray)) {Box() {Box(modifier = Modifier // .fillMaxSize().matchParentSize().background(Color.Cyan))Spacer(modifier = Modifier.size(50.dp).padding(10.dp).background(Color.Red))}}
matchParentSize效果如下所示:
fillMaxSize效果如下所示: -
weight
在RowScope和ColumnScope中,可以使用专属的weight修饰符来设置尺寸。与size不同的是weight允许组件通过百分比设置尺寸,也就是允许组件可以自适应适配各种屏幕尺寸的移动端设备。Column(modifier = Modifier.background(Color.DarkGray).width(300.dp).height(200.dp)) {Spacer(modifier = Modifier.fillMaxWidth().weight(1f).background(Color.White))Spacer(modifier = Modifier.fillMaxWidth().weight(1f).background(Color.Red))Spacer(modifier = Modifier.fillMaxWidth().weight(1f).background(Color.Blue))}
-
-
Modifier实现原理
各位读者可以参考下面这篇博客:
图解Compose Modifier实现原理 ,竟然如此简单!
常用的基础组件
文字组件
- Text文本
在Compose中,Text是遵循MD设计规范的上层文本组件,如果想脱离MD,也可以直接使用更底层的文本组件BasicText。
在很多应用场景中,我们需要在一段文字中对局部内容应用特别格式以示突出,比如一个超链接,此时需要用到AnnotatedString。AnnotatedString是一个数据类,除了文本值,还包含一个SpanStyle和ParagraphStyle的Range列表。SpanStyle用于描述在文本中子串的文字样式,ParagraphStyle则用于描述文本中子串的段落样式,Range确定子串的范围。@Composable fun Text(text: String,modifier: Modifier = Modifier,color: Color = Color.Unspecified,fontSize: TextUnit = TextUnit.Unspecified,fontStyle: FontStyle? = null,fontWeight: FontWeight? = null,fontFamily: FontFamily? = null,letterSpacing: TextUnit = TextUnit.Unspecified,textDecoration: TextDecoration? = null,textAlign: TextAlign? = null,lineHeight: TextUnit = TextUnit.Unspecified,overflow: TextOverflow = TextOverflow.Clip,softWrap: Boolean = true,maxLines: Int = Int.MAX_VALUE,onTextLayout: (TextLayoutResult) -> Unit = {},style: TextStyle = LocalTextStyle.current )
用法如下所示:
SpanStyle继承了TextStyle中关于文字样式相关的字段,而ParagraphStyle继承了TextStyle中控制段落的样式,例如textAlign、lineHeight等。SpanStyle和ParagraphStyle中的设置优先于TextStyle中同名属性设置。//append用来添加子串的文本 //withStyle为append的子串指定文字或段落样式 Text(text = buildAnnotatedString {withStyle(style = SpanStyle(fontSize = 24.sp)){append("你现在学习的章节是")}withStyle(style = SpanStyle(fontSize = 24.sp, fontWeight = FontWeight.W900)){append("Text")}append("\n")withStyle(style = ParagraphStyle(lineHeight = 25.sp)){append("在刚刚讲过的内容中,我们学会了如何应用文字样式,以及如何限制文本的行数和处理溢出的视觉效果。")append("\n")append("现在,我们正在学习")withStyle(style = SpanStyle(fontWeight = FontWeight.W900, textDecoration = TextDecoration.Underline, color = Color(0xff59a869))){append("AnnotatedString")}}})
-
SelectionContainer选中文字
Text自身默认是不能被长按选择的,Compose提供了专门的SelectionContainer组件,对包裹的Text进行选中。SelectionContainer() {Text(text = "我是可以被复制的文字") }
-
ClickableText
Compose提供了一种可点击文本组件,可以响应对文字的点击,并返回点击位置。可以让AnnotatedString子串在相应的ClickedText中点击后,做出不同的动作。在AnnotatedString中可以为子串添加一个tag标签,在处理onClick事件时,根据tag实现不同的逻辑。ClickableText(text = annotated, onClick ={annotated.getStringAnnotations(tag = "URL",start = it,end = it).firstOrNull()?.let {Log.e("MainActivity",it.toString())}} )val annotated = buildAnnotatedString {withStyle(style = ParagraphStyle(lineHeight = 25.sp)){// 开始一个注解区域pushStringAnnotation(tag = "URL", annotation = "https://www.baidu.com")// 追加带有注解的文本withStyle(style = SpanStyle(fontWeight = FontWeight.W900,textDecoration = TextDecoration.Underline,color = Color(0xff59a869))){append("AnnotatedString")}// 结束注解区域pop()//下面这段文本不会有注解withStyle(style = SpanStyle(fontWeight = FontWeight.W900,textDecoration = TextDecoration.Underline,color = Color(0xff59a869))){append("NotAnnotatedString")}}}
-
TextField输入框
TextField组件是我们最常用的文本输入框,它也遵循MD设计准则。它也有一个低级别的底层组件,BasicTextField,与TextField和OutlinedTextField不同的是,BasicTextField拥有更多的自定义效果。由于TextField和OutlinedTextField是根据MD准则设计的,无法直接修改输入框的高度,如果尝试修改高度,会看到输入区域被截断,影响正常输入。fun TextField(value: TextFieldValue,onValueChange: (TextFieldValue) -> Unit,modifier: Modifier = Modifier,enabled: Boolean = true,readOnly: Boolean = false,textStyle: TextStyle = LocalTextStyle.current,label: @Composable (() -> Unit)? = null,placeholder: @Composable (() -> Unit)? = null,leadingIcon: @Composable (() -> Unit)? = null,trailingIcon: @Composable (() -> Unit)? = null,supportingText: @Composable (() -> Unit)? = null,isError: Boolean = false,visualTransformation: VisualTransformation = VisualTransformation.None,keyboardOptions: KeyboardOptions = KeyboardOptions.Default,keyboardActions: KeyboardActions = KeyboardActions.Default,singleLine: Boolean = false,maxLines: Int = Int.MAX_VALUE,interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },shape: Shape = TextFieldDefaults.filledShape,colors: TextFieldColors = TextFieldDefaults.textFieldColors() ) fun BasicTextField(value: String,onValueChange: (String) -> Unit,modifier: Modifier = Modifier,enabled: Boolean = true,readOnly: Boolean = false,textStyle: TextStyle = TextStyle.Default,keyboardOptions: KeyboardOptions = KeyboardOptions.Default,keyboardActions: KeyboardActions = KeyboardActions.Default,singleLine: Boolean = false,maxLines: Int = Int.MAX_VALUE,visualTransformation: VisualTransformation = VisualTransformation.None,onTextLayout: (TextLayoutResult) -> Unit = {},interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },cursorBrush: Brush = SolidColor(Color.Black),decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =@Composable { innerTextField -> innerTextField() } )
TextField输入框案例如下:
@Composablefun TextFieldSample(){var text by remember {mutableStateOf("")}Box(modifier = Modifier.fillMaxSize().background(Color(0xfd3d3d3)),contentAlignment = Alignment.Center) {BasicTextField(modifier = Modifier.padding(10.dp).background(Color.White, CircleShape).height(30.dp).fillMaxSize(),value = text,onValueChange = {text = it},decorationBox = {Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.padding(vertical = 2.dp, horizontal = 8.dp)) {Icon(imageVector = Icons.Filled.Search, contentDescription = null)Box(modifier = Modifier.padding(horizontal = 10.dp).width(100.dp), contentAlignment = Alignment.CenterStart) {if(text.isEmpty()){Text(text = "输入点东西看看吧~",style = TextStyle(color = Color(0,0,0,128)))}it()}Box(contentAlignment = Alignment.CenterEnd){if(text.isNotEmpty()){IconButton(onClick = { text="" },modifier = Modifier.size(16.dp)) {Icon(imageVector = Icons.Filled.Close, contentDescription = null, tint = Color.Red)}}}}})}}
-
图片组件
- Icon图标
Icon组件用于显示一系列小图标。Icon组件支持三种不同类型的图片设置:
@Composable fun Icon(imageVector: ImageVector,//矢量图对象,可以显示SVG格式的图标contentDescription: String?,modifier: Modifier = Modifier,tint: Color = LocalContentColor.current ) @Composable fun Icon(bitmap: ImageBitmap,//位图对象,可以显示JPG、PNG等格式的图标contentDescription: String?,modifier: Modifier = Modifier,tint: Color = LocalContentColor.current ) @Composable fun Icon(painter: Painter,//代表一个自定义画笔,可以使用画笔在Canvas上直接绘制图标contentDescription: String?,modifier: Modifier = Modifier,tint: Color = LocalContentColor.current )
- Image图片
Image组件用来显示一张图片。它和Icon一样也支持三种类型的图片设置。
- Icon图标
-
按钮组件
- Button按钮
Button也是最常用的组件之一,它也是按照MD风格来实现的。Button并非唯一可点击组件,理论上任何Composable组件都可以通过Modifier.clickable修饰符化身为可点击组件。
案例如下:
@Composablefun ButtonSample(){val interactionSource = remember {MutableInteractionSource()}val pressState = interactionSource.collectIsPressedAsState()val borderColor = if (pressState.value) Color.Green else Color.WhiteButton(modifier = Modifier.clickable {//该方法在button组件会失效Log.e("MainActivity","点击Butttonclickable")},interactionSource = interactionSource,border = BorderStroke(2.dp, color = borderColor),onClick = {Log.e("MainActivity","点击Buttton")}) {Icon(imageVector = Icons.Filled.Done, contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize))Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))Text(text = "确认")}}
- IconButton图标按钮
IconButton组件实际上只是Button组件的简单封装(一个可点击的图标),它一般用于应用栏中的导航或者其他行为。一般来说,需要在IconButton组件里提供一个图标组件,这个图标的默认尺寸一般为24*24dp。
IconButton(onClick = { text="" },modifier = Modifier.size(16.dp)) {Icon(imageVector = Icons.Filled.Close, contentDescription = null, tint = Color.Red)
- FloatingActionButton悬浮按钮
@Composablefun FloatButton(){FloatingActionButton(onClick = {}) {Row() {Text(text = "添加到我的喜欢")Icon(imageVector = Icons.Filled.Done, contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize))}}ExtendedFloatingActionButton(onClick = { /*TODO*/ }) {Row() {Text(text = "添加到我的喜欢")Icon(imageVector = Icons.Filled.Done, contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize))}}}
- Button按钮
-
选择器
- CheckBox复选框
@Composablefun ChecBoxDemo(){val checkedState = remember {mutableStateOf(true)}Checkbox(checked = checkedState.value,onCheckedChange ={checkedState.value = it},colors = CheckboxDefaults.colors(checkedColor = Color(0xff0079d3)))}
- TriStateCheckBox三态选择框
很多时候,我们的复选框会有很多个,并且希望能够统一选择或者取消,这个时候就可以使用三态选择框
@Composablefun ChecBoxDemo(){val (state,onStateChange) = remember { mutableStateOf(true) }val (state2,onStateChange2) = remember { mutableStateOf(true) }val parentState = remember(state,state2) {if (state&&state2) ToggleableState.Onelse if (!state&&!state2) ToggleableState.Offelse ToggleableState.Indeterminate}val onParentClick = {val s = parentState != ToggleableState.OnonStateChange(s)onStateChange2(s)}TriStateCheckbox(colors = CheckboxDefaults.colors(checkedColor = Color.Red),state = parentState,onClick = onParentClick,)Column(Modifier.padding(10.dp,0.dp,0.dp,0.dp)) {Checkbox(checked = state, onCheckedChange = onStateChange )Checkbox(checked = state2, onCheckedChange = onStateChange2 )}}
- Switch单选开关——控制单个项目的开启或关闭状态
@Composablefun ChecBoxDemo(){val checkedState = remember {mutableStateOf(true)}Switch(checked = checkedState.value, onCheckedChange = {checkedState.value = it})}
- Slider滑竿组件——可用来做音量、亮度之类的数值调整或进度条
var sliderPosition by remember {mutableStateOf(0f)}Slider(value = sliderPosition, onValueChange = {sliderPosition = it})
- 进度条
var progress by remember {mutableStateOf(0.1f)}val animatedProgress by animateFloatAsState(targetValue = progress, animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec)Column {CircularProgressIndicator(progress = animatedProgress)Spacer(modifier = Modifier.requiredHeight(30.dp))OutlinedButton(onClick = {if(progress<1f)progress +=.1f}) {Text(text = "增加进度")}}
- 对话框
@Composablefun DialogDemo(){val openDialog = remember {mutableStateOf(true)}val dialogWidth = 200.dpval dialogHeight = 50.dpif(openDialog.value){Dialog(onDismissRequest = { openDialog.value = false },properties = DialogProperties(dismissOnBackPress = true,//允许通过点击物理返回键取消对话框dismissOnClickOutside = true//允许点击对话框外部取消对话框)) {Box(modifier = Modifier.size(dialogWidth, dialogHeight).background(Color.Blue))}}}
常用的布局组件
-
线性布局
线性布局对应于传统视图中的linearLayout,Compose根据orientation的不同又分为Column和Row。- Column
Column是一个垂直线性布局组件,它能够将子项按照从上到下的顺序垂直排列。verticalArrangement和horizontalAlignment参数分别可以帮助我们安排子项的垂直/水平位置,在默认的情况下,子项会以垂直方向上靠上,水平方向上靠左来布置。 - Row
Row组件能够将内部子项按照从左到右的方向水平排列。用法Column类似。
- Column
-
帧布局
- Box
Box组件是一个能够将里面的子项依次按照顺序堆叠的布局组件,在使用上类似于传统视图中的Framelayout。 - Surface
Surface是一个平面,在MD设计准则中也同样如此,我们可以将很多的组件摆放在这个平面之上,可以设置这个平面的边框、圆角、颜色等。
- Box
-
Spacer留白
在很多时候,需要让两个组件之间留有空白的间隔,这个时候就可以使用该组件。其实当Box组件没有content时,完全可以用Spacer替换。可以给Spacer做如下封装,可以更方便地用在水平或垂直布局中。@Composablefun WidthSpacer(value:Dp){Spacer(modifier = Modifier.width(value))}@Composablefun HeightSpacer(value:Dp){Spacer(modifier = Modifier.height(value))}
-
ConstraintLayout约束布局
各位读者可以参考下面这篇博客:
Compose ConstraintLayout 详讲 -
Scaffold脚手架
Scaffold组件实现了MD的布局结构,通过配合其他MD组件可以轻松构建MD风格的页面。@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")@OptIn(ExperimentalMaterial3Api::class)@Composablefun Sample(){var selectedItem by remember {mutableStateOf(0)}val items = listOf(Item("主页",R.drawable.ic_launcher),Item("列表",R.drawable.ic_launcher),Item("设置",R.drawable.ic_launcher),)Scaffold(topBar ={TopAppBar(title = { Text(text = "主页")},navigationIcon = {IconButton(onClick = { /*TODO*/ }) {Icon(imageVector = Icons.Filled.Menu, contentDescription = null)}})}){Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center){Text(text = "主页面")}}}
列表
很多产品中都有展示一组数据的需求场景,如果数据数量是可以枚举的,则仅需通过Column组件来枚举列出。然而很多时候,列表中的项目会非常多,我们需要滑动列表来查看所有内容,可以通过给Column的modifier添加verticalScroll方法来让列表实现滑动。
@Composablefun ListDemo(){val initialCapacity = 1000 // 设置你想要的初始容量val items = ArrayList<String>(initialCapacity)for (i in 1..initialCapacity) {items.add("我是text$i")}Column(modifier = Modifier.verticalScroll(state = ScrollState(5), enabled = true)) {items.forEach{Text(text = "$it")}}}
给Column的Modifier添加verticalScroll方法可以让列表实现滑动。但是如果列表过长,众多的内容会占用大量的内存。然而更多的内容对于用户其实都是不可见的,没有必要加载到内存。所以compose提供了专门用于处理长列表的组件,LazyColumn和LazyRow,其作用类似于传统视图中的Listview和RecyclerView。
LazyColumn(modifier = Modifier.fillMaxSize().background(Color.Cyan),contentPadding = PaddingValues(30.dp),//为内容设置外边距verticalArrangement = Arrangement.spacedBy(10.dp)//为每个item设置间隔) {items(1000){Text(text = "$it")}}
相关文章:

Android全新UI框架之常用ComposeUI组件
在Compose中,每个组件都是一个带有Composable注解的函数,被称为Composable。Compose已经预置了很多基于MD设计规范的Composable组件。 在布局方面,Compose提供了Column、Row、Box三种布局组件(感觉跟flutter差不多),类似于传统视图…...

网络防御保护综合练习
一、实验拓扑 二、实验要求 1, Fw1和Fw2组成主备模式的双机热备 2,DMZ区存在两台服务器,现在要求生产区的设备仅能在办公时间(9:00 - 18:00)访问,办公区的设备全天都可以访问。 3,办…...
Unity调用文心-ERNIE-Bot-turbo
参考文章 ERNIE-Bot-turbo - 千帆大模型平台 | 百度智能云文档 (baidu.com) 错误码 - 千帆大模型平台 | 百度智能云文档 (baidu.com) private readonly string apiKey "";private readonly string secretKey "";private readonly string tokenUrl &q…...

机器学习基本概念(李宏毅课程)
目录 一、概念:1、机器学习概念:2、深度学习概念: 二、深度学习中f(.)的输入和输出:1、输入:2、输出: 三、三种机器学习任务:1、Regression回归任务介绍:2、Classification分类任务介绍:3、Stru…...

浅谈WPF之利用RichTextBox实现富文本编辑器
在实际应用中,富文本随处可见,如留言板,聊天软件,文档编辑,特定格式内容等,在WPF开发中,如何实现富文本编辑呢?本文以一个简单的小例子,简述如何通过RichTextBox实现富文…...

w29pikachu-ssrf实例
SSRF简介 SSRF是服务器端请求伪造 危害: 1.可以对服务器所在内网、本地进行端口扫描,获取一些服务的信息等 2.目标网站本地敏感数据的读取 3.内外网主机应用程序漏洞的利用 4.内外网web站点漏洞的利用 ssrf常用的相关协议: gopher://: 发…...
使用 openssl 进行哈希计算
版本:OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022) SHAx 系列 如果对象完全存储在内存中,可以使用以下函数: #include <openssl/sha.h>unsigned char *SHA1(const unsigned char *data, size_t count, unsigned…...

深度学习基础——SSD目标检测
SSD网络介绍 使用多个特征图作为特征预测层。 SSD (Single Shot MultiBox Detector)于2016年提出。当网络输入为300300大小时,在VOC2007测试集上达到74.3%的mAP;当输入是512512大小时,达到了76.9%的mAP SSD_Backbone部分介绍 不变的部分 特征提取网…...

鸿蒙系统优缺点,能否作为开发者选择
凡是都有对立面,就直接说说鸿蒙的优缺点吧。 鸿蒙的缺点: 鸿蒙是从2019年开始做出来的,那时候是套壳Android大家都知晓。从而导致大家不看鸿蒙系统,套壳Android就是多次一举。现在鸿蒙星河版已经是纯血鸿蒙,但是它的…...

强化学习入门(Matlab2021b)-创建环境【2】
目录 1 前言2 利用step和reset函数创建自定义环境2.1 对象描述2.2 reset函数2.3 step函数2.3 构建自定义环境3 使用匿名函数传递额外的参数4 可视化检查自定义函数的输出参考链接1 前言 本文介绍如何基于MATLAB编写step、reset函数,创建自己的强化学习环境(Environment)。 使…...
OkHttp 相关问题
1、OkHttp请求整体流程是怎么样? Request-》OkHttpClient-》RealCall 同步 -》 在调用线程 执行五大拦截器 异步 -》 使用分发器将任务在线程池执行 五大拦截器 ---首先AsyncCall --加到等待队列readyAsyncCalls--》判断host有没有 已经存在。有,就赋值原来的。(reuseC…...

html的表单标签(上):form标签和input标签
表单标签 表单是让用户输入信息的重要途径。 用表单标签来完成与服务器的一次交互,比如你登录QQ账号时的场景。 表单分成两个部分: 表单域:包含表单元素的区域,用form标签来表示。表单控件:输入框,提交按…...
网页数据的解析提取(XPath的使用----lxml库详解)
在提取网页信息时,最基础的方法是使用正则表达式,但过程比较烦琐且容易出错。对于网页节点来说,可以定义id、class或其他属性,而且节点之间还有层次关系,在网页中可以通过XPath或CSS选择器来定位一个或多个节点。那么&…...

dell r740服务器黄灯闪烁维修现场解决
1:首先看一下这款DELL非常主力的PowerEdge R740服务器长啥样,不得不说就外观来说自从IBM抛弃System X系列服务器后,也就戴尔这个外观看的比较顺眼。 图一:是DELL R740前视图(这款是8盘机型) 图二ÿ…...
202426读书笔记|《尼采诗精选》——高蹈于生活之上,提升自己向下观望
202426读书笔记|《尼采诗精选》——高蹈于生活之上,提升自己向下观望 第一辑 早期尼采诗歌选辑(1858—1869年)第二辑 前期尼采遗著中的诗歌选辑(1871—1882年)第五辑 戏谑、狡计与复仇——德语韵律短诗序曲(…...

【PX4学习笔记】13.飞行安全与炸机处理
目录 文章目录 目录使用QGC地面站的安全设置、安全绳安全参数在具体参数中的体现安全绳 无人机炸机处理A:无人机异常时控操作B:无人机炸机现场处理C:无人机炸机后期维护和数据处理D:无人机再次正常飞行测试 无人机飞行法律宣传 使…...

Puppeteer 使用实战:如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客(二)
文章目录 上一篇效果演示Puppeteer 修改浏览器的默认下载位置控制并发数错误重试并发控制 错误重试源码 上一篇 Puppeteer 使用实战:如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客(一) 效果演示 上一篇实现了一些基本功能,…...

[ 2024春节 Flink打卡 ] -- 优化(draft)
2024,游子未归乡。工作需要,flink coding。觉知此事要躬行,未休,特记 资源配置调优内存设置 TaskManager内存模型 https://nightlies.apache.org/flink/flink-docs-release-1.18/docs/deployment/config/ TaskManager 内存模型…...

电脑进水无法开机怎么办 电脑进水开不了机的解决方法
意外总是会不定时打破你的计划,电脑这类电器最怕遇到的除了火还有水,设备进水会导致数据丢失,那么我们遇到电脑进水怎么办?进水之后不正确处理也会引起很多不必要的麻烦. 解决办法 第一步:关机 如果您的电脑是在开…...

【Flutter】底部导航BottomNavigationBar的使用
常用基本属性 属性名含义是否必须items底部导航栏的子项List是currentIndex当前显示索引否onTap底部导航栏的点击事件, Function(int)否type底部导航栏类型,定义 [BottomNavigationBar] 的布局和行为否selectedItemColor选中项图标和label的颜色否unsel…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...