Jetpack-Compose之一基础使用

2023-11-06

一.命令式UI和申明式UI

如果之前有了解或者使用果Flutter,应该会对命令式UI这种架构不陌生。目前申明式UI确实是很火包含Flutter,SwiftUI,JetpackCompose都使用了该种方式。2021年7月底,Google 正式发布了 Jetpack Compose 的 1.0 稳定版本,这说明Google认为Compose已经可以用于生产环境了。

1.命令式UI

回想再传统的Android开发中,首先会在xml布局文件中写好控件,然后在Activity中通过findViewbyid找到该控件,然后通过命令给他设置各种属性,例如设置背景颜色,设置内边距,控件会根据我们所设置的属性 做UI的变化,至始至终我们都是通过改变同一个控件的属性,来获得不同的显示效果.这就是命令式UI.

View view=findViewById(R.id.view)
view.setBackgroundColor(Color.Blue)
view.setTop(xxx)

2.申明式UI

在申明式UI中视图配置是不可变的,意思就是说需要先描述UI界面的样子,状态变化时,界面按照新的描述的重新“渲染”即可得到正确的界面,每次重新渲染就是在控件自身上触发重建, 不会修改旧的实例控件,而是构造不同的新的实例控件进行展示。

return ViewB(
  backgroundColor: Color.Blue,
  top: xxx,
)

二.项目引入Compose

有两种方式,一种是手动引入,另外一种是通过AndroidStudio创建:

1.手动引入Compose依赖

(1.)项目根gradle中添加
buildscript {
    ext {
        compose_version = '1.0.0' // compose版本
    }
    ext.kotlin_version = "1.4.30"
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
(2.)app目录下的build.gradle设置

将app支持的最低API 版本设置为21或更高,同时开启Jetpack Compose enable开关

android {
    defaultConfig {
        ...
        minSdkVersion 21
    }

    buildFeatures {
        // Enables Jetpack Compose for this module
        compose true
    }
    ...

    // Set both the Java and Kotlin compilers to target Java 8.

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}
(3.)添加Jetpack Compose工具包依赖项

在app目录下的build.gradle添加Jetpack Compose 工具包依赖项,代码如下:

dependencies {
    // You also need to include the following Compose toolkit dependencies.
     //compose依赖
       implementation "androidx.compose.ui:ui:$compose_version"
       implementation "androidx.compose.foundation:foundation:$compose_version"
       implementation "androidx.compose.material:material:$compose_version"
       implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
       implementation "androidx.compose.runtime:runtime-rxjava2:$compose_version"
       implementation 'androidx.activity:activity-compose:1.3.0-alpha03'
       implementation "androidx.compose.ui:ui-tooling:$compose_version"
    ...
}

2.AndroidStudio创建Compose工程

三.Compose示例分析

1.Compose简单使用

在MainActivity.kt中添加如下代码:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Text("Hello,Compose!")
        }
    }
}

运行就可以看到效果了:

这种写法与使用 XML 布局的方式差别很大,setContent 块定义了 Activity 的布局。不需要使用 XML 文件来定义布局内容,而是调用一个 Compose 函数,比如上面的 Text 函数, 然后 Jetpack Compose 使用自定义 Kotlin 编译器插件将这些 Compose 函数转换为应用的界面元素。

2.Composable注解

点开Text函数,可以发现它是kotlin的一个顶层函数,并且被@Composable注解修饰:

@Composable
fun Text(
    ...
) {
    Text(
      ...
    )
}

Jetpack Compose的界面是围绕composable函数来构建的。这些composable函数可以通过描述应用程序的形状和数据依赖,以编程方式定义应用程序的UI,而不是着眼于UI的构建过程。因此要创建composable函数,只需要在函数名前面加上一个@composable注解即可。
例如可以通过Composable注解一个方法对Text进行封装:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            helloText("Hello,Compose!")
        }
    }
    @Composable
    fun helloText(text:String){
        Text(text);
    }
}

需要注意,Composable注解的函数只能在其他Composable注解的函数内调用。

四.Compose界面预览

1.@Preview注解

在 Compose 框架中通过给 Composable 函数添加 @Preview 注解就可以在不运行App的情况下确认布局的情况:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            helloText()
        }
    }

    @Preview()
    @Composable
    fun helloText(){
        Text("Hello,Compose!")
    }
}

在IDE的右上角有Code,Split,Design三个选项。分别是只显示代码,同时显示代码和布局和只显示布局。

2.@Preview注解常用参数

打开@Preview注解可以看到可以接收如下参数:

@Repeatable
annotation class Preview(
    val name: String = "",
    val group: String = "",
    @IntRange(from = 1) val apiLevel: Int = -1,
    // TODO(mount): Make this Dp when they are inline classes
    val widthDp: Int = -1,
    // TODO(mount): Make this Dp when they are inline classes
    val heightDp: Int = -1,
    val locale: String = "",
    @FloatRange(from = 0.01) val fontScale: Float = 1f,
    val showSystemUi: Boolean = false,
    val showBackground: Boolean = false,
    val backgroundColor: Long = 0,
    @UiMode val uiMode: Int = 0,
    @Device val device: String = Devices.DEFAULT
)

(1.)给Preview命名
  • name: String: 为该Preview命名,该名字会在布局预览中显示。
  • group: String: 为该Preview设置group名字,可以在UI中以group为单位显示。
(2.)给Preview设置背景颜色
  • showBackground: Boolean: 是否显示背景,true为显示。
  • backgroundColor: Long: 设置背景的颜色(backgroundColor 是 ARGB Long,而不是 Color 值)。
@Preview(showBackground = true, backgroundColor = 0xFF00FF00)
@Composable
fun WithGreenBackground() {
    Text("Hello World")
}

默认情况下,您的可组合项将以透明背景显示。

(3.)给Preview设置显示宽高
  • widthDp: Int: 在Compose中渲染的最大宽度,单位为dp。
  • heightDp: Int: 在Compose中渲染的最大高度,单位为dp。
    默认情况下,系统会自动选择 @Preview 尺寸来封装其内容。如需手动设置尺寸,可以添加 heightDp 和 widthDp 参数。
@Preview(widthDp = 50, heightDp = 50)
@Composable
fun SquareComposablePreview() {
    Box(Modifier.background(Color.Yellow)) {
        Text("Hello World")
    }
}

请注意,这些值已解释为 Dp,您无需在值末尾添加 .dp

(4.)给Preview设置显示系统界面

如需在预览对象中显示状态栏和操作栏,请添加 showSystemUi 参数:

@Preview(showSystemUi = true)
@Composable
fun DecoratedComposablePreview() {
    Text("Hello World")
}

(5.)给Preview设置显示语言区域

如需测试不同的用户语言区域,您需要添加 locale 参数:

@Preview(locale = "fr-rFR")
@Composable
fun DifferentLocaleComposablePreview() {
    Text(text = stringResource(R.string.greetings))
}
(6.)通过@PreviewParameter给Preview添加传递参数预览

如果被 @Composable修饰的组件函数是一个有参数的函数,要对其进行预览,可以使用 @PreviewParameter 注解添加参数,以将数据传递给某个可组合项预览函数。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            showUser(User("罗贯中"))
        }
    }
    @Composable
    @Preview("name",showBackground = true, backgroundColor = 0xFF00FF00)
    fun showUser(@PreviewParameter(UserPreviewParameterProvider::class) user: User) {
        Text(user.name)
    }
}

如需提供示例数据,请创建一个可实现 PreviewParameterProvider 并以序列形式返回示例数据的类。

class UserPreviewParameterProvider : PreviewParameterProvider<User> {
    override val values = sequenceOf(User("刘备"), User("曹操"), User("孙权"))
}

序列中的每个数据元素都会呈现一个预览:

如果不想每一个数据对应的预览都展示,可通过设置 limit 参数来限制呈现的预览数量:

@Composable
@Preview("name",showBackground = true, backgroundColor = 0xFF00FF00)
fun showUser(@PreviewParameter(UserPreviewParameterProvider::class, limit = 2) user: User) {
    Text(user.name)
}

特别需要注意的有两点:
上面的参数都是可选参数,还有像背景设置等的参数并不是对实际的App进行设置,只是对Preview中的背景进行设置,为了更容易看清布局。
在实际的开发中,预览函数不要发布到线上,所以最佳做法是单独创建不会被应用调用的预览函数用于查看实际效果,专门的预览函数可以提高性能,并且有利于以后更轻松地设置多个预览。

五.Compose组件配置属性

上文中我们用到了Compose提供的Text组件,既然是文本组件肯定存在文本属性配置, 我们知道在Jetpack Compose 所有的组件都是 可以组合函数,所以Text 也不例外,源码如下:

@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 = AmbientTextStyle.current
) {
    ……
}

因此我们在使用Text组件时可以对其属性进行配置。
例如配置文字颜色:

Text("Hello Compose", color = Color.Blue)

例如配置文字字号:

Text("Hello Compose", fontSize=20.sp)

通过这些属性我们就可以配置出各式各样不同的文本显示效果。

六.Compose组件中的Modifier

在上文中我们可以看到Text组件接收一个Modifier的参数, Modifier, 顾名思义就是一个修饰器,用于装饰Compose UI元素或向其添加行为。每个 Compose 组件都会提供一个Modifier 参数用于修改样式

1.经常用到的Modifier属性

借助Modifier 参数可以控制 组件的行为和外观 如大小,背景等,还可以添加一些交互,如点击、滑动等。关于Modifier相关的设置实在是太多,在这里只介绍会经常用到的,更多Modifier学习

Text(
    "Android",
    modifier = Modifier
        .padding(10.dp)//设置padding
        .size(100.dp)//设置大小
        .background(Color.Gray)//设置背景
        .clickable(onClick = {})//添加点击事件
)
1.配置尺寸
  • Modifier.fillMaxHeight() // 填充整个父组件的高度。
  • Modifier.fillMaxWidth() // 填充整个父组件的宽度。
  • Modifier.fillMaxSize() // 填充整个父组件的宽和高 类似于mach_parent
  • Modifier.width(2.dp) // 设置宽度
  • Modifier.height(3.dp) // 设置高度
  • Modifier.size(4.dp, 5.dp) // 设置高度和宽度
2.配置重力
  • Modifier.gravity(Alignment.CenterHorizontally) // 横向居中
  • Modifier.gravity(Alignment.Start) // 横向居左
  • Modifier.gravity(Alignment.End) // 横向居右
3.配置边距Padding
  • Modifier.padding(10.dp) //设置上下左右边距为同一值
  • Modifier.padding(10.dp, 11.dp, 12.dp, 13.dp) //分别为上下左右边距值
  • Modifier.padding(10.dp, 11.dp) //分别为上下和左右边距值
4.配置偏移量
  • Modifier.offset(x=10.dp,y=10.dp) //要相对于原始位置放置布局,请添加 offset 修饰符,并在 x 轴和 y 轴中设置偏移量。偏移量可以是正数,也可以是非正数。

这里设置的值必须为DpCompose为我们在Int中扩展了一个方法dp,帮我们转换成Dp

2.Modifier属性调用顺序

Modifier是利用 kotlin 扩展函数实现的,每个方法的返回值都是Modifier 因此可以实现链式调用。由于每个函数都会对上一个函数返回的 Modifier 进行更改,因此先后顺序会影响最终结果。
例如:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Column {
                Text(
                    "Hello Compose One",
                    fontSize = 20.sp,
                    modifier = Modifier
                        .padding(10.dp)
                        .clickable(onClick = {})
                        .widthIn(100.dp, 200.dp)

                )
                Text(
                    "Hello Compose Two",
                    fontSize = 20.sp,
                    modifier = Modifier
                        .clickable(onClick = {})
                        .padding(10.dp)
                        .widthIn(100.dp, 200.dp)
                )
            }
        }
    }
}

我们给Modifier设置的padding边距和clickable点击事件的先后顺序不同,会导致组件的可点击区域也会不一样:

modifier 只能设置 padding,没有 margin 属性。先设置了size尺寸再设置padding就是设置控件的内边距,先设置padding再设置size尺寸就是设置组件的外边距。所以,在 Modifier 中设置 padding 的次序很重要。

七.Compose常用的布局容器

1.Column垂直布局容器

添加Column,使布局垂直排列

Column {
  Text("张飞")
  Text("关羽")
}

Column源码:

@Composable
inline fun Column(
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: @Composable ColumnScope.() -> Unit
) {
    ...
}

Column 有两个属性 verticalArrangement 和 horizontalAlignment 来控制 child 的对齐摆放方式。

2.Row横向布局容器

Row {
    Text("张飞")
    Text("关羽")
    }


Row源码:

@Composable
inline fun Row(
    modifier: Modifier = Modifier,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    content: @Composable RowScope.() -> Unit
) {
  ...
}

Row 有两个属性 horizontalArrangement 和 verticalAlignment 来控制 child 的对齐摆放方式。

2.Box堆叠布局容器

类似于Android View 体系中的 FrameLayout

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Box {
                Box(
                    Modifier
                        .size(200.dp, 200.dp)
                        .background(Color.Blue))
                Box(
                    Modifier
                        .size(100.dp, 100.dp)
                        .background(Color.Red))
            }
        }
    }
}


Box源码:

@Composable
inline fun Box(
    modifier: Modifier = Modifier,//修饰符
    contentAlignment: Alignment = Alignment.TopStart,//对齐方法
    propagateMinConstraints: Boolean = false,
    content: @Composable BoxScope.() -> Unit
) {
    ...
}

Box 有个属性contentAlignment 来控制 child 的对齐摆放方式。

参考资料:
Compose UI官方文档
compose资料

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jetpack-Compose之一基础使用 的相关文章

  • 如何引导用户为我的应用程序启用辅助功能服务

    我知道不可能以编程方式启用应用程序的辅助功能服务 因此我想将用户引导至此屏幕 System settings gt Accessibility gt app name gt enable disable screen 那可能吗 您可以将它们
  • 虹膜和面部识别生物识别技术

    In blog Android P 中更好的生物识别技术 https android developers googleblog com 2018 06 better biometrics in android p html他们说 为了确保
  • 设置文本并从剪贴板获取文本[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 在Android中 我需要一些代码来
  • 使用 hisorian.py 时显示“找不到结束时间”

    我正在尝试收集我的应用程序的电池统计信息 运行指定的所有命令后http developer android com tools performance batterystats battery historian index html ht
  • 如何使用MonkeyDevice.instrument?

    嗨 大家好 我正在尝试从 MonkeyRunner 脚本运行我的测试仪器之一 不幸的是我无法让它工作 我尝试使用不同的参数变量调用 MonkeyDevice instrument 但没有成功 我试过了 设备 MonkeyRunner wai
  • BroadcastReceiver未收到警报广播

    我有一个设置新的重复警报的代码 在生产中我将使用 inexactRepeating 但是我注册的用于处理它的 BroadCastReceiver 没有被调用 这是我设置闹钟的代码 newAlarmPeriod 5000 For debugg
  • Android Http url 连接在 getInputstream 抛出文件未找到异常

    我正在尝试将一些 json 字符串发布到休息服务器 但在获取输入流时遇到 java 文件未找到异常 这是我的代码 package com muzima view sample activities import javax servlet
  • Webview 不显示带有颜色的文本

    在我的应用程序中 我在 webview 中显示一些 Html 内容 String webViewConent this is some span style color 2ecc71 sample span string webView l
  • 原生编程对于移动开发有何优势?

    我需要为一家公司在一些主要的移动操作系统上开发应用程序 特别是 iOS Android 和 WP7 我最初计划为三种不同的操作系统编写三个独立的应用程序 每个应用程序都使用本机 SDK 然而 这样做有什么好处吗 有许多可用的跨平台工具 Se
  • 从服务(IntentService)和活动执行的AsyncTask - 有区别吗?

    从 Activity 或 IntentService 启动 AsyncSync 之间有什么区别吗 我正在构建一个通过 http 下载和上传文件的应用程序 我为每次传输使用带有进度条的自定义通知布局 我选择并行传输或将它们放入队列 您会推荐哪
  • Android Facebook SDK - 无法接收访问令牌

    我正在尝试在我的 Android 应用程序中使用 Facebook SDK 这是片段 Facebook myFacebook new Facebook 123456789012345 myFacebook authorize LogInSc
  • 安装应用程序时复制 SD 卡上的文本文件?

    我正在开发一款安卓游戏 我想在用户第一次安装游戏时将文本文件复制到外部 SD 卡 文本文件对于正确运行游戏非常重要 我怎样才能做到这一点 我应该将文本文件放在 Eclipse 源项目中的哪里 以便当我构建 apk 文件时 我的文本文件也会捆
  • 在 Android 应用程序中读取 CSV 文件

    我正在开发一个概念验证应用程序 以便我可以在我正在制作的更大的应用程序中实现该功能 我对 Java 和 Android 开发有点陌生 但希望这个问题不会太简单或太复杂 基本上 我试图从 CSV 文件中读取字符串列表 并使其可用于在应用程序的
  • RecyclerView OnClick 位置

    我正在尝试获取我的点击项目的位置RecyclerView 然而 这有点奇怪 只让我在点击时记录位置 而不让我做一个Toast的位置 看这里 public class MainAdapter extends RecyclerView Adap
  • 我可以启动 AndroidManifst.xml 文件中未指定的新活动吗

    我正在尝试执行一些动态代码 然后加载一个新类 该类应该是Activity我想启动它 但使用常规startActivity Intent 想要Activity在 AndroidManifest xml 文件中 声明 有什么线索吗 您无法启动未
  • 抱歉,该视频无法在视频视图中播放?

    freinds 我正在使用以下代码在我的应用程序中显示 mp4 视频 并面临以下问题 我在 google 和 stackoverflow 上看到了很多与这个问题相关的帖子 但每个人都给出了自己的建议 并且没有共同的答案 1 我在模拟器中看不
  • 如何将 logcat 输出复制到剪贴板?

    我正在 Eclipse 中开发 Android 应用程序 如何将 logcat 消息发送到剪贴板 Select the message and press ctrl c You can save it in a text file usin
  • 如何在我的 Android 库 (AAR) 中包含 proguard 配置

    Android 库 根据AAR 文件规范 http tools android com tech docs new build system aar format 包含一个 proguard txt 文件 我的理解是 该文件声明了如何正确地
  • Android Google Maps V2 当前位置纬度经度 NullPointerException

    有很多类似的问题 但我没有找到解决我的问题的方法 setUpMap方法是 private void setUpMap BitmapDescriptor iconm BitmapDescriptorFactory fromResource R
  • Android 并获取 id 转换为字符串的视图

    在 Android 项目的 Java 代码中 如果您想要视图资源的引用 您可以执行以下操作 View addButton findViewById R id button 0 在上面的 R id button 0 不是一个字符串 是否可以通

随机推荐

  • Unity2D敌人/怪物AI控制 第一期

    AI 原地巡逻自动攻击型 AI会在横版地图上向左向右移动 移动一段距离后会原地停止移动 等待一段时间后 会随机向左或向右移动 以此循环 其中AI移动速度 移动时间 停留时间均可以自行调控 当人物进入怪物攻击范围后 会自动面向人物进行攻击 攻
  • 网络编程(20)—— 广播的编程实现

    一 广播和多播的区别 广播是向同一网络中所有主机传播数据的一种方式 它和多播的主要区别在于 1 从范围上来说 多播即使在跨越不同网络的情况下 只要加入多播组就能接受数据 而广播只能向同一网络中的主机传输数据 这种网络可以是发送者所在的网络
  • 一次完整的渗透测试流程,网站渗透存在哪些漏洞和隐藏的风险?

    渗透测试 渗透测试就是利用我们所掌握的渗透知识 对网站进行一步一步的渗透 发现其中存在的漏洞和隐藏的风险 然后撰写一篇测试报告 提供给我们的客户 客户根据我们撰写的测试报告 对网站进行漏洞修补 以防止黑客的入侵 渗透测试的前提是我们得经过用
  • LNK2005: _DllMain@12 already defined in LIBCMTD.lib(dllmain.obj)

    今天使用VS2003创建一个MFC 的dll工程时 出现以下错误 VPR error LNK2005 DllMain 12 already defined in LIBCMTD lib dllmain obj VPR error LNK20
  • 安全形势不容乐观 信息安全调查揭露五大误区

    日前 信息周刊 研究部和国际商业机器公司 IBM 合作进行了2008年 中国信息安全调查 这也是 信息周刊 以 11 年全球信息安全调查为基础 在中国开展的第四次安全调查 调查结果全面揭示了当前不容乐观的安全形势 对首席信息官 CIO 而言
  • Arthas 常用命令

    官方文档 Arthas Install Arthas 3 5 5 文档 安装 Arthas 是阿里开源的一款 linux mac 上性能问题排查工具 文档链接 Arthas 用户文档 Arthas 3 5 5 文档 这个里边具体步骤和指令讲
  • 数据链路层:ARP协议详解(绝对经典)

    ARP协议定义 地址解析协议 工作在数据链路层 在本层和硬件接口联系 同时向上层提供服务 IP数据包常通过以太网发送 以太网设备不识别32位IP地址 他们是以48位以太网地址传输以太网数据包的 因此需要IP转化为以太网目的地址 ARP协议用
  • Thread Pool 线程池

    Thread Pool 本文基于经典的99行代码 稍加修改使其支持C 20 并增加了wait与join功能 pragma once include
  • vue中使用drag事件左右拖动div,改变宽高大小

    实现思路 1 使用上左 top left 上 top 上右 top right 等6个小点实现拖动效果 2 拖动时记录起始点 结束点 startPoint x 0 y 0 开始坐标 拖动改变定位 endPoint x 0 y 0 结束坐标
  • 面试题 08.10. 颜色填充

    面试题 08 10 颜色填充 https leetcode cn com problems color fill lcci 难度简单12收藏分享切换为英文关注反馈 编写函数 实现许多图片编辑软件都支持的 颜色填充 功能 待填充的图像用二维数
  • Java多线程之间的通信

    重点 等待 gt 执行业务 gt 通知其他线程 package com liu pc 线程之间通讯问题 等待唤醒 通知唤醒 线程交替执行 A B操作同一个变量 A 1 B 1 public class A public static voi
  • virtual channels 虚拟通道——mipi协议

    1 虚拟通道ID字段 最多可以支持4个外设 2 需要 DSI Hub 无法将多个显示器连接到同一总线 3 或者某个显示设备支持使用虚拟通道 设备本身由多个物理驱动器控制显示面板的不同区域 这个显示器就可以使用虚拟通道将数据发送到各个驱动器
  • 【数据库原理及应用教程(第4版

    文章目录 一 选择题 二 填空题 三 设计题 四 简答题 Reference 一 选择题 1 2 3 4 5 6 7 8 9 10 B C C A C B C B D C 11 12 13 14 15 16 17 18 19 20 D B
  • bzoj1110 [POI2007]砝码Odw 贪心+进制拆分

    题意就不说了 一开始居然在想直接dp 看到是整数倍我的内心居然毫无波动 真是傻的不行了 因为是整数倍 那我们可以把一个容器用砝码的重量做为进制拆分 然后从小到大一个个填就可以了 贪心策略肯定是最优的 具体如何拆分看hzwer www htt
  • LSP和Hooks拦截

    分层服务提供者 英语 Layered Service Provider 缩写LSP 是一项已被弃用的Microsoft Windows中Winsock 2服务提供者接口 SPI 的特性 它也被称为分层服务提供商或分层服务提供程序 分层服务提
  • Mybatis-plus中操作JSON字段

    1 实体类上要加上自动映射 TableName value school autoResultMap true 2 json字段上加上json处理器 TableField value cover url typeHandler Jackso
  • 使用nmcli命令配置虚拟机网络

    简述 什么是nmcli Description nmcli is a command line tool for controlling NetworkManager and reporting network status It can
  • Mybatis 获取当前序列和下一个序列值 以及在一个方法中写多条SQL 语句

    目录 1 Mybatis 获取当前序列和下一个序列值 2 Mybatis 在一个方法中写多条SQL 语句 1 Mybatis 获取当前序列和下一个序列值 获取当前序列值 select XXX sequence currval from du
  • 电子信息工程毕设题目选题大全

    文章目录 1前言 2 如何选题 3 选题方向 3 1 嵌入式开发方向 3 2 物联网方向 3 3 移动通信方向 3 4 人工智能方向 3 5 算法研究方向 3 6 移动应用开发方向 3 7 网络通信方向 3 8 学长作品展示 4 最后 1前
  • Jetpack-Compose之一基础使用

    一 命令式UI和申明式UI 如果之前有了解或者使用果Flutter 应该会对命令式UI这种架构不陌生 目前申明式UI确实是很火包含Flutter SwiftUI JetpackCompose都使用了该种方式 2021年7月底 Google