前言:同事抱着极大的热情试用了compose,然后给我甩了一堆问题
看看这些问题击中你了没有
其性能?
理论性能优于传统写法(1.0的性能测试看这里)
(实际性能看起来稍差了一些,但应该可以通过androidx.profileInstaller
和更新版本去优化,1.2.0-alpha05版本后似乎lazyColumn性能得到了大优化,有没有大佬基于最新alpha版测试下?)
无惧布局层级的嵌套(constraintLayout现在只是一种布局方式,不再有其他优势)
复杂动画性能远优于传统写法(除非你用自定义view)
初始化性能理应比xml快,但目前可能稍慢一些(未实测,只看了之前版本的其他人的测试结果)
全部或者部分代码改用compose写将大大优化包体积
为什么连给Text设置fontSize都是实验性API?
用 Int.sp / Float.sp
16.sp
哪里有讲compose原理的课程?
微信公众号可以搜到一些文章
但我还是想推荐这个公众号和其中的这篇文章(作者看到记得联系我结下广告费):
compose里面怎么开线程
LaunchEffect(Unit){
//主线程协程块,自己在这里面切子线程
launch {
//子线程协程块
}
}
那——LaunchEffect中的launch块里能更新UI吗?
你且自由更新它!真有问题报错了再找解决方法!
怎么更新UI?
被mutableStateOf
/ mutablexxxOf
包裹的对象更新时会触发invalidate
使得界面刷新
var text by mutableStateOf("")
@Composable
fun Test() {
Text (text, Modifier.clickable{
text = "wow"
})
// 如果text定义在@Composable函数内部,其定义就应当写成这样
var text by remember { mutableStateOf("") }
除此之外的其他值只能在界面刷新时被 【顺便】 刷新
remember?
被remember的块包裹的区域在Composable生命周期内只执行一次
但remember可以通过写成remember (value1 ,可选value2...){}
的形式,对传入的value进行观察,当value改变时,其块包裹的区域会再次被执行
我没用过ViewModel
好说,获取它看这里——
- 在
@Composable
中
// 写法1
val viewModel = viewModel<MyViewModel>()
// 写法2
val viewModel : MyViewModel = viewModel()
- 在
koltin
中
// 这个context……看ViewModelProvider(ViewModelStore)的注释吧
val viewModel = ViewModelProvider(context).get(MyViewModel::java.class)
定义它看这里——
class MyViewModel : ViewModel() {
// 如果这个值的改变应该触发界面刷新,请使它基于mutableStatexxxOf
var contentOfText : String by mutableStateOf("")
}
多语言适配?
@Composable
中可以直接通过LocalContext.current
取到当前context,然后你懂的
——等等,你猜猜我在@Composable
中打‘local’看到了什么?
!!!你可以拿到这么多东西!
这一大堆东西里面,值得关注的还有LocalView
LocalDensity
,你懂的
多分辨率适配?
- 通过
context
拿定义了不同dimen的xml dp值 - 但我觉得我们也可以根据dimen的规则写一套自适应的Dp获取和计算方案 : )
使元素响应拖动?
var offsetOfText by remember { mutableStateOf( IntOffset.Zero ) }
Modifier
.offset{offsetOfText}
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
offsetOfText += dragAmount.round()
}
}
Modifier是顺序敏感的?
那为什么上面一串代码我改成这样也可以拖动?
var offsetOfText by remember { mutableStateOf( IntOffset.Zero ) }
Modifier
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
offsetOfText += dragAmount.round()
}
}
.offset{offsetOfText}
是可以,毕竟拖动事件的注册和进行offset又有什么关系呢?
但——会出现一个有意思的现象
描述一下就是:拖动监听区域将始终不会跟随offset值的改变而改变
也就是说:拖动监听区域将永远在初始位置,你每次需要从初始位置开始滑动才能触发拖曳响应
——没错,只有基于offset设置drag监听,才可以让监听跟随offset