D26 / 要怎麽放 Compose 进我的专案? - Compose View

今天大概会聊到的范围

  • ComposeView

之前有介绍过 Compose 中的 AndroidView ,是一个可以在 Compose 中放入一般 Android View 。那如果我们要在一般的 Android 专案中放入 Compose 呢? 有几个方法可以在原先 Android 的专案中加入 Compose

环境配置

之前有介绍过 Compose compiler 的运作机制,那些转换都是透过 Kotlin 在 1.5 新增的 JVM IR compiler backend 。另外,Android Studio 也只有在 Arctic Fox 之後的版本才有支援 Compose、Android Build Tool 也需要在 7.0 以上:

// project-level build.gradle

buildscript {
    ...
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0"
        ...
    }
}

// module-level build.gradle 

android {

    ... 

    kotlinOptions {
        jvmTarget = '1.8'
        useIR = true
    }

    buildFeatures {
        compose true
    }

    composeOptions {
        kotlinCompilerExtensionVersion compose_version
        kotlinCompilerVersion '1.5.10'
    }
    
    ...
}

准备就绪,开始导入 Compose 吧!先加入 Compose 相关的 library:

dependencies {
    // Integration with activities
    implementation 'androidx.activity:activity-compose:1.3.1'
    // Compose Material Design
    implementation 'androidx.compose.material:material:1.0.1'
    // Animations
    implementation 'androidx.compose.animation:animation:1.0.1'
    // Tooling support (Previews, etc.)
    implementation 'androidx.compose.ui:ui-tooling:1.0.1'
    // Integration with ViewModels
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07'
    // UI Tests
    androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.0.1'
}

Use setContent

如果整个页面都可以使用 Compose 来建制的话,我们可以用我们学习 Compose 以来常常见到的好朋友 setContent function 来加入 Composable:

// 记得要加入 'androidx.activity:activity-compose:1.3.1'

class InteropActivity : AppCompatActivity() { // <-- 一般的 AppCompactActivity 就有继承 ComponentActivity
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {    // <-- setContent 是 compose 在 ComponentActivity 身上加上的 extension fucntion    
            ComposeScreen()    // <--- 这里就可以放 Composable 了
        }
    }
}

Use ComposeView

如果只有 Activity 中的某个部分想转成 Compose,在 xml 中使用 ComposeView :

// in xml

<LinearLayout ...>

    ...

    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/interopComposeView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    ...

</LinearLayout>


// in activity 

class InteropActivity : AppCompatActivity() {
    
    private lateinit var binding: ActivityInteropBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityInteropBinding.inflate(layoutInflater)        // <-- 这里是用 ViewBinding。一般的 findViewById 也可以喔
        val root = binding.root


        binding.interopComposeView.setContent {
            // composable        // ComposeView 有 setContent  function 可以放入 composable
        }
        
        
        setContentView(root)
    }
}

Dispose Strategy

没特别设定的话,ComposeView 会在 该 View detach window 时触发 dispose。但是这可能不是期望的行为,例如在 Fragment 中我们可能希望跟着 Fragment 的 Lifecycle。

ComposeView 有 setViewCompositionStrategy function 可以使用,调整 dispose 的策略:

  • DisposeOnLifecycleDestroyed 可以让 Compose 跟着 LifecycleOwner
  • DisposeOnViewTreeLifecycleDestroyed 则是在 LifecycleOwner 不方便取得时,直接透过 ViewTree 判断适当的 dispose 时机

就这样,把 ComposeView 当成一般的 View 放在 Android 内,再配合之前研究到的 AndroidView 就可以慢慢将计有专案 migrate 到 Compose 上罗!


Reference:


<<:  Day24【Web】网路传输协定:TCP 与 UDP

>>:  JS 25 - 举一反三,扩充专属於自己的函式库!

SQL MD5 加密 & C# BASE64

C# BASE64 原由:厂商丢了编成 Base64 字串的东西来,接到後,要把它还原. strin...

CSS微动画 - Animation也会影响网页效能?

Q: 终於要讲效能了! A: 以Loading为范例讲黑~ Animation Loading 直...

【零基础成为 AI 解梦大师秘笈】Day27 - 周易解梦之人工智慧(8)

人工智慧8 前言 系列文章简介 大家好,我们是 AI . FREE Team - 人工智慧自由团队,...

Day27 Javascript元件库 Jquery介绍

今天要接触我们的Javascript,让网页更多动画,互动性,不是一个只有图片跟文字的死板网页,而J...

Windows Web Form(C#) import Web API

Windows Web Form(C#) import Web API     步骤一 :先新增或使...