Compose

1、概述

Jetpack Compose 是用于构建原生界面的最新的 Android 工具包,采用声明式 UI 的设计,拥有更简单的自定义和实时的交互预览功能,由 Android 官方团队全新打造的 UI 框架。

官方文档

第三方文档

2、环境配置

2.1、新项目可以通过最新的Android studio直接新建Compose项目

2.2、支持Compose项目的具体配置如下

2.2.1、Android studio版本,最好使用最新版本,Android Studio Arctic Fox 或更高版本

2.2.2、Gradlec插件版本7.0 或更高版本

buildscript {

    ...

    dependencies {

        classpath "com.android.tools.build:gradle:7.0.0"

        ...

    }

}

2.2.3、kotlin版本,Kotlin 1.4.32 或更高版本,Compose仅支持kotlin语言

plugins {

    id 'org.jetbrains.kotlin:android' version '1.5.21'

}

2.2.4、build.gradle配置

build.gradle

android {

    compileSdk 31

    defaultConfig {

        applicationId "com.gala.composeexample"

        minSdk 21  //Compose最低支持api21,即Android5.0,因为Compose的库里面minSdkVersion是21

        targetSdk 31

        versionCode 1

        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        vectorDrawables {

            useSupportLibrary true

        }

    }

    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

        }

    }

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

    //本地jdk版本需要11或更高版本

    compileOptions {

        sourceCompatibility JavaVersion.VERSION_1_8

        targetCompatibility JavaVersion.VERSION_1_8

    }

    kotlinOptions {

        jvmTarget = '1.8'

        useIR = true

    }

    buildFeatures {

        // Enables Jetpack Compose for this module

        compose true

    }

    composeOptions {

        kotlinCompilerExtensionVersion compose_version

        kotlinCompilerVersion '1.5.21'

    }

    packagingOptions {

        resources {

            excludes += '/META-INF/{AL2.0,LGPL2.1}'

        }

    }

}

dependencies {

    implementation fileTree(include: ['*.jar'], dir: 'libs')

    implementation 'androidx.core:core-ktx:1.6.0'

    implementation 'androidx.appcompat:appcompat:1.3.1'

    implementation 'com.google.android.material:material:1.4.0'

    //Compose 布局、绘制、预览

    implementation "androidx.compose.ui:ui:$compose_version"

    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"

    //Compose 基于 Material Design 的风格化

    implementation "androidx.compose.material:material:$compose_version"

    //Compose 状态管理

    implementation "androidx.compose.runtime:runtime-livedata:$compose_version"

    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'

    implementation 'androidx.activity:activity-compose:1.3.1'

    testImplementation 'junit:junit:4.+'

    androidTestImplementation 'androidx.test.ext:junit:1.1.3'

    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"

    debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"

    implementation("io.coil-kt:coil-compose:1.4.0")

}

2、Compose的使用简单介绍

相比传统XML的setContentView,Compose使用了ComponentActivity的扩展方法setContent,方法最后还是调用了setContentView

setContent {

    ComposeExampleTheme {

        //是一个加了注解@Composable的方法

        MainCompose(mViewModel)

    }

}

//示例显示一个text

@Composable

fun Greeting(name: String) {

    Text(text = "Hello $name!")

}

JetPack-Compose 自定义了一个基础容器ComposeView ,以及其他扩展View - AndroidComposeView,并对其进行封装,对外提供了各种我们在上层所使用的各种组件或者容器。

在Compose中setContent后,其初始化了一个ComposeView,并且添加了一个AndroidComposeView,其承载了代码中所写的全部组件,并进行解析,最终绘制在了传统UI中。Compose只允许测量一次,不允许重复测量。Compose会先对整个组件树进行一次Intrinsic测量,然后再对整体进行正式的测量。这样开辟两个平行的测量过程,就可以避免因为层级增加而对同一个子组件反复测量所导致的测量时间的不断加倍了。在Compose里疯狂嵌套地写界面,和把所有组件全都写进同一层里面,性能是一样的!所以Compose没有布局嵌套问题。

3、state状态管理

由于 Compose 是声明式工具集,因此更新它的唯一方法是通过新参数调用同一可组合项。这些参数是界面状态的表现形式。每当状态更新时,都会发生重组。可以使用 remember 可组合项记住单个对象。系统会在初始组合期间将由 remember 计算的值存储在组合中,并在重组期间返回存储的值。示例如下,具体看官方文档

val defaultBitmap: Bitmap? = null

val qrBitmap = remember { mutableStateOf(defaultBitmap) }

...

//代码简略了,具体在demo中,qrBitmap的value值随着协程LaunchedEffect中加载结束会变动

val width = dimensionResource(R.dimen.dimen_300dp).value.toInt()

val height = dimensionResource(R.dimen.dimen_300dp).value.toInt()

val qrUrlStr = qrUrl.value ?: ""

LaunchedEffect(qrUrlStr, width, height) {

    QRUtils.createQRImage(qrUrlStr, width, height)

        .also { qrBitmap.value = it }

}

qrBitmap.value?.run {

    Image(

        painter = BitmapPainter(this.asImageBitmap()),

        contentDescription = null,

        modifier = Modifier

            .padding(top = dimensionResource(R.dimen.dimen_32dp))

            .size(

                dimensionResource(R.dimen.dimen_300dp),

                dimensionResource(R.dimen.dimen_300dp)

            ),

        contentScale = ContentScale.FillBounds

    )

} ?: run {

    Image(

        painter = painterResource(id = R.drawable.a_projection_def_logo),

        contentDescription = null,

        modifier = Modifier

            .padding(top = dimensionResource(R.dimen.dimen_32dp))

            .size(

                dimensionResource(R.dimen.dimen_300dp),

                dimensionResource(R.dimen.dimen_300dp)

            )

            .background(color = colorResource(R.color.color_f0f0f0)),

        contentScale = ContentScale.Inside

    )

}

4、和XML view的对比

4.1、包体大小对比

1、release混淆版本,Compose库大小大概0.5M

2、看一些Compose使用文章,项目完全使用Compose包体大小减少明显,主要在于方法数和layout减少

4.2、耗时分析对比,Compose比XML慢,能肉眼可见会黑一小会

4.2.1 Compose耗时分析

数据是在电视果设备上取的,使用Android studio自带的Profiler分析的,使用Compose的情况下,view显示耗时具体情况如下图,主要在于AndroidComposeView.onAttackedToWindow和onMeasure方法

4.2.2 Compose与XML耗时情况对比

同一个布局样式(项目中的投屏落地页,相对简单,层级不多),release版本,耗时对比统计结果如下(详细结果如图):

如上述表格数据:

  • 在电视果5SP(Android7.1)上,Compose比XML慢很多,每次启动清理不清理数据几乎差不多
  • 在小米10(Android11)上,每次清理数据的情况,Compose比XML略慢,layout相差50ms左右,draw相差20ms左右;不清理数据的情况,Compose和XML几乎是一样的,相差在10ms以内。不清理数据比清理数据快很多,应该是高Android版本有所缓存
  • 经对比,在高性能设备上Compose的view布局、绘制、渲染表现还可以,与XML相差不大,略慢一点

4.3 构建速度,由于demo小比较不明显

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值