Android开发:Jetpack Compose编程知识全汇总 (含详细实例讲解)

上面的参数都是可选参数,还有像背景设置等的参数并不是对实际的App进行设置,只是对Preview中的背景进行设置,为了更容易看清布局。

@Preview(showBackground = true)

@Composable fun DefaultPreview() {

ComposeDemoTheme {

Greeting(“Android”)

}

}

当更改跟UI相关的代码时,会显示如下图的一个横条通知,点击Build&Refresh即可更新显示所更改代码的UI。

setContent

该方法作用是和zaiLayout/View中的setContentView是一样的。setContent的方法也是有@Compose注解的方法。所以,在setContent中写入关于UI的@Compopse方法,即可在Activity中显示。

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContent {

Text(“Hello world!”)

}

}

Modifier

该类是各个Compose的UI组件一定会用到的一个类。它是被用于设置UI的摆放位置,padding等修饰信息的类。关于Modifier相关的设置较多,在这里只介绍会经常用到的。

Modifier.padding(10.dp) // 给上下左右设置成同一个值

Modifier.padding(10.dp, 11.dp, 12.dp, 13.dp) // 分别为上下左右设值

Modifier.padding(10.dp, 11.dp) // 分别为上下和左右设值

Modifier.padding(InnerPadding(10.dp, 11.dp, 12.dp, 13.dp))// 分别为上下左右设值

Modifier.fillMaxHeight() // 填充整个宽度

Modifier.fillMaxHeight() // 填充整个高度

Modifier.fillMaxSize() // 填充整个宽度和高度

Modifier.width(2.dp) // 设置宽度

Modifier.height(3.dp) // 设置高度

Modifier.size(4.dp, 5.dp) // 设置高度和宽度

Modifier.widthIn(2.dp) // 设置最大宽度

Modifier.heightIn(3.dp) // 设置最大高度

Modifier.sizeIn(4.dp, 5.dp, 6.dp, 7.dp) // 设置最大最小的宽度和高度

Modifier.gravity(Alignment.CenterHorizontally) // 横向居中

Modifier.gravity(Alignment.Start) // 横向居左

Modifier.gravity(Alignment.End) // 横向居右

Modifier.rtl // 从右到左 Modifier.ltr // 从左到右

Modifier.plus(otherModifier) // 把otherModifier的信息加入到现有的modifier中

// Modifier的方法都返回Modifier的实例的链式调用,所以只要连续调用想要使用的方法即可。

@Composable fun Greeting(name: String) {

Text(text = “Hello $name!”, modifier = Modifier.padding(20.dp).fillMaxWidth())

}

Column,Row

Column和Row可以理解为在View/Layout体系中的纵向和横向的ViewGroup

Column(

verticalArrangement:Arrangement // 控制纵向布局关系

horizontalAlignment:Alignment // 控制横向对齐关系

)

Row(

horizontalArrangement:Alignment // 控制横向布局关系

verticalAlignment:Arrangement // 控制纵向对齐关系

)

@Composable

fun TestColumnRow() {

Column(

modifier = Modifier.fillMaxHeight().background(Color.Yellow),

verticalArrangement = Arrangement.SpaceBetween,

horizontalAlignment = Alignment.Start

) {

Text(text = “java”)

Text(text = “android”)

Text(text = “python”)

}

Row(

modifier = Modifier.fillMaxWidth().background(Color.LightGray),

verticalAlignment = Alignment.Top,

horizontalArrangement = Arrangement.SpaceBetween

) {

Text(text = “java”)

Text(text = “android”)

Text(text = “python”)

}

}

四、进阶使用

状态管理

所有 Android 应用都有核心界面更新循环,如下所示:

Compose 专为单向数据流而打造。这是一种状态向下流动而事件向上流动的设计。

使用单向数据流的应用的界面更新循环如下所示:

事件:事件由界面的一部分生成并且向上传递。

更新状态:事件处理脚本可以更改状态。

显示状态:状态会向下传递,界面会观察新状态并显示该状态。

举两个例子展示:

//内部状态管理

@Composable

fun CounterInner() {

val count = remember { mutableStateOf(0) }

Button(onClick = { count.value += 1 })

{

Text(text = “Count: ${count.value}”)

}

}

解释一下上图的数据流情况

事件:当点击发生时候,会触发count.value

更新状态:mutableStateOf会进行处理,然后设置count的状态

显示状态:系统会调用count的观察器,并且界面会显示新状态

//支持其他可观察类型的状态管理

class CountViewModel : ViewModel() {

// LiveData holds state which is observed by the UI

// (state flows down from ViewModel)

private val _count = MutableLiveData(0)

val count: LiveData = _count

// onNameChanged is an event we’re defining that the UI can invoke

// (events flow up from UI)

fun onCountChanged(newCount: Int) {

_count.value = newCount

}

}

@Composable

fun Counter(countViewModel: CountViewModel = viewModel()) {

val observeAsState = countViewModel.count.observeAsState(0)

val count = observeAsState.value

Button(

colors = ButtonConstants.defaultButtonColors(backgroundColor = if (count > 5) Color.Green else Color.White),

onClick = { countViewModel.onCountChanged(count + 1) },

) {

Text(text = “I’ve been clicked $count times”)

}

}

解释一下上图的数据流情况

事件:当点击发生时候,会触发onCountChanged

更新状态:onCountChanged会进行处理,然后设置_count的状态

显示状态:系统会调用count的观察器,并且界面会显示新状态

状态提升
  • 无状态可组合项是指本身无法改变任何状态的可组合项。无状态组件更容易测试、发生的错误往往更少,并且更有可能重复使用。

  • 如果您的可组合项有状态,您可以通过使用状态提升使其变为无状态。

  • 状态提升是一种编程模式,在这种模式下,通过将可组合项中的内部状态替换为参数和事件,将状态移至可组合项的调用方。

  • 状态提升的过程可让您将单向数据流扩展到无状态可组合项。在这些可组合项的单向数据流示意图中,随着更多可组合项与状态交互,状态仍向下流动,而事件向上流动。

@Composable

fun Counter(countViewModel: CountViewModel = viewModel()) {

val observeAsState = countViewModel.count.observeAsState(0)

val count = observeAsState.value

ButtonCount(count = count, onCountChanged = { countViewModel.onCountChanged(it) })

}

@Composable

fun ButtonCount(

/* state */ count: Int,

/* event */ onCountChanged: (Int) -> Unit ) {

Button(

colors = ButtonConstants.defaultButtonColors(backgroundColor = if (count > 5) Color.Green else Color.White),

onClick = { onCountChanged(count + 1) },

) {

Text(text = “I’ve been clicked $count times”)

}

}

互操作
Android View中的Compose

如果想使用Compose的情况下,又不想迁移整个应用,可以在xml里面增加ComposeView,类似于占位符,然后在Actviity/fragment中寻找该控件并调用setContent方法即可,在该方法中即可使用compose相关属性

<androidx.constraintlayout.widget.ConstraintLayout

xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

tools:context=“.AndroidViewComposeActivity”>

<TextView

android:id=“@+id/hello_world”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:text=“Hello Android!”

app:layout_constraintTop_toTopOf=“parent” />

<androidx.compose.ui.platform.ComposeView

android:id=“@+id/compose_view_text”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

app:layout_constraintTop_toBottomOf=“@id/hello_world” />

<androidx.compose.ui.platform.ComposeView

android:id=“@+id/compose_view_img”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

app:layout_constraintTop_toBottomOf=“@id/compose_view_text” />

</androidx.constraintlayout.widget.ConstraintLayout>

class AndroidViewComposeActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_android_view_compose)

findViewById(R.id.compose_view_text).setContent {

MaterialTheme {

Text(“Hello Compose!”)

}

}

findViewById(R.id.compose_view_img).setContent {

val imageResource = imageResource(id = R.drawable.header)

val imageModifier = Modifier.preferredHeight(180.dp)

.fillMaxWidth()

.padding(16.dp)

.clip(RoundedCornerShape(4.dp))

MaterialTheme {

Image(

bitmap = imageResource,

modifier = imageModifier,

contentScale = ContentScale.Crop

)

}

}

}

}

Compose中的Android View

如果碰到在Compose环境中,想要使用Android的View视图的情况,只需要使用AndroidView函数即可

@Composable

fun CustomView() {

val selectedItem = remember { mutableStateOf(0) }

val context = AmbientContext.current

val customView = remember {

// Creates custom view

Button(context).apply {

// Sets up listeners for View -> Compose communication

setOnClickListener {

selectedItem.value += 1

}

}

}

// Adds view to Compose

AndroidView({ customView }) {

view ->

// View’s been inflated - add logic here if necessary

// As selectedItem is read here, AndroidView will recompose

// whenever the state changes

// Example of Compose -> View communication

view.text = selectedItem.value.toString()

}

}

如果是需要使用xml的配置情况,也使用AndroidView函数即可

@Composable

fun CustomView2() {

val context = AmbientContext.current

val customView = remember {

// Creates custom view

View.inflate(context, R.layout.layout_custom_view, null)

}

AndroidView({ customView })

}

与通用库集成
ViewModel

从源码可看出,viewmodel函数底层也是通过ViewModelProvider进行获取的

@Composable

fun viewModel(

modelClass: Class,

key: String? = null,

factory: ViewModelProvider.Factory? = null )
VM = AmbientViewModelStoreOwner.current.get(modelClass, key, factory)
数据流

Compose也是适配Android主流的基于流的方案,如

  • LiveData.observeAsState()

  • Flow.collectAsState()

  • Observable.subscribeAsState()

在Compose中,LiveData.observeAsState()获取的State对象赋值给Text

@Composable

fun HelloScreen(helloViewModel: HelloViewModel = viewModel()) {

// by default, viewModel() follows the Lifecycle as the Activity or Fragment

// that calls HelloScreen(). This lifecycle can be modified by callers of HelloScreen.

// name is the current value of [helloViewModel.name]

// with an initial value of “”

val observeAsState = helloViewModel.name.observeAsState(“”)

Column {

Text(text = observeAsState.value)

TextField(

value = observeAsState.value,

onValueChange = { helloViewModel.onNameChanged(it) },

label = { Text(“Name”) }

)

}

}

异步操作

此处需要补充说明的是Compose的生命周期

Compose通过一系列Effect方法,实现生命周期函数

| Compose生命周期 | 说明 | 对应React |

| — | — | — |

| onActive | compose函数第一次被渲染到画面 | componentWillMount componentDidMount |

| onDispose | compose函数从画面上移除 | componentWillUnmount |

| onCommit | compose函数每次执行,画面重新渲染 | componentDidUpdate |

所以onCommit函数的使用类似于React的useEffect,支持可观察函数

@Suppress(“ComposableNaming”)

@Composable

/inline/

fun </reified/ V1> onCommit(

v1: V1,

/noinline/

callback: CommitScope.() -> Unit ) {

remember(v1) { PreCommitScopeImpl(callback) }

}

仅当v1发生变化时onCommit才会执行

举个例子使用异步操作

@Composable fun fetchImage(url: String): ImageAsset? {

// Holds our current image, and will be updated by the onCommit lambda below

var image by remember(url) { mutableStateOf<ImageAsset?>(null) }

onCommit(url) {

// This onCommit lambda will be invoked every time url changes

val listener = object : ExampleImageLoader.Listener() {

override fun onSuccess(bitmap: Bitmap) {

// When the image successfully loads, update our image state

image = bitmap.asImageAsset()

}

}

// Now execute the image loader

val imageLoader = ExampleImageLoader.get()

imageLoader.load(url).into(listener)

onDispose {

// If we leave composition, cancel any pending requests

imageLoader.cancel(listener)

}

}

// Return the state-backed image property. Any callers of this function

// will be recomposed once the image finishes loading

return image

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

image

七大模块学习资料:如NDK模块开发、Android框架体系架构…

image

2021大厂面试真题:

image

只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。

片转存中…(img-Fm1jnO6Y-1711917868599)]
[外链图片转存中…(img-g4Mdms8G-1711917868600)]
[外链图片转存中…(img-WZOTh3Zt-1711917868600)]
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-EhgicPmy-1711917868600)]

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

[外链图片转存中…(img-PhvOte2i-1711917868601)]

七大模块学习资料:如NDK模块开发、Android框架体系架构…

[外链图片转存中…(img-kBohPahN-1711917868601)]

2021大厂面试真题:

[外链图片转存中…(img-ynff9xAH-1711917868601)]

只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

  • 18
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值