Jetpack Compose 计数器应用示例
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.example.counterappcompose.ui.theme.CounterAppComposeTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// 设置主题
CounterAppComposeTheme {
// 创建一个 Surface 容器,使用背景颜色
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
CounterApp()
}
}
}
}
}
@Composable
fun CounterApp() {
// 使用 remember 和 mutableStateOf 创建可变状态
var count by remember { mutableStateOf(0) }
// 使用 Column 布局组件
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// 显示计数器值
Text(text = "Count: $count", style = MaterialTheme.typography.h4)
Spacer(modifier = Modifier.height(8.dp))
// 增加计数器值的按钮
Button(onClick = { count++ }) {
Text(text = "Increment")
}
}
}
传统的 Android View 系统计数器应用示例
界面布局代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp"
tools:context=".MainActivity">
<!-- 显示计数器值的 TextView -->
<TextView
android:id="@+id/textViewCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Count: 0"
android:textSize="32sp" />
<!-- 增加计数器值的按钮 -->
<Button
android:id="@+id/buttonIncrement"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Increment"
android:layout_marginTop="16dp" />
</LinearLayout>
逻辑代码
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private int count = 0;
private TextView textViewCount;
private Button buttonIncrement;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取 TextView 和 Button 的引用
textViewCount = findViewById(R.id.textViewCount);
buttonIncrement = findViewById(R.id.buttonIncrement);
// 设置按钮点击监听器
buttonIncrement.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 增加计数器值并更新 TextView
count++;
textViewCount.setText("Count: " + count);
}
});
}
}
主要区别和优劣对比
Jetpack Compose 优点
-
声明式 UI:
- 优点:使用声明式编程风格,更容易理解和维护。
- 示例:在
CounterAppCompose.kt
中,通过remember
和mutableStateOf
管理状态,UI 根据状态自动更新。
-
更少的样板代码:减少了大量的 XML 布局文件和
findViewById
的样板代码。- 示例:
CounterAppCompose.kt
文件中,整个 UI 仅使用几行代码实现。
- 示例:
-
热重载和实时预览:支持热重载和实时预览,大大加快了开发和调试的效率。
- 示例:在 Android Studio 中修改 Compose 代码时,可以立即看到预览变化,而不需要重新运行应用。
-
更容易的动画和过渡:提供了简洁而强大的动画 API,可以轻松实现复杂的动画效果。
- Jetpack Compose 提供了简洁而强大的动画 API,可以轻松实现复杂的动画效果。以下是一个使用
AnimatedVisibility
实现淡入淡出动画的示例。:
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @Composable fun AnimatedVisibilityDemo() { var visible by remember { mutableStateOf(true) } Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { // 使用 AnimatedVisibility 实现淡入淡出动画效果 AnimatedVisibility( visible = visible, enter = fadeIn(), exit = fadeOut() ) { Text("Hello, World!") } Spacer(modifier = Modifier.height(8.dp)) Button(onClick = { visible = !visible }) { Text("Toggle Visibility") } } }
- Jetpack Compose 提供了简洁而强大的动画 API,可以轻松实现复杂的动画效果。以下是一个使用
-
更好的可组合性:UI 组件是高度可组合的,可以轻松地将小组件组合成更复杂的 UI。
- 示例:
import androidx.compose.foundation.layout.Column import androidx.compose.material3.Text import androidx.compose.runtime.Composable @Composable fun Greeting(name: String) { Text(text = "Hello, $name!") } @Composable fun GreetingList(names: List<String>) { Column { // 将多个 Greeting 组件组合在一起 for (name in names) { Greeting(name = name) } } }
传统的 Android View 系统 优点
-
广泛使用和成熟:经过多年的发展和优化,具有良好的性能和稳定性。
- 示例:传统 View 系统在大多数应用中表现稳定,适用于各种场景。
-
丰富的资源和文档:大量的资源、文档和教程,使得学习和使用相对容易。
- 示例:开发者可以轻松找到各种教程和示例代码,解决问题。
-
兼容性好:与旧版本的 Android 系统和旧的库完全兼容。
- 示例:对于现有的大型项目,迁移成本较低,可以无缝集成。
Jetpack Compose 缺点
-
学习曲线:对于习惯了传统 View 系统的开发者来说,需要学习新的编程范式和 API。
- 示例:开发者需要掌握 Kotlin 和声明式编程,而不是依赖于 XML 和命令式编程。
-
生态系统相对较新:虽然 Jetpack Compose 发展迅速,但生态系统和社区支持相对传统 View 系统较新。
- 示例:一些旧的库和工具可能还不完全兼容,需要额外的工作来集成。
-
性能优化:对于复杂的 UI 和动画,可能需要更多的性能优化工作。
- 示例:在复杂动画和大数据列表的场景下,可能需要进行性能调优。
传统的 Android View 系统 缺点
-
繁琐的样板代码:需要编写大量的 XML 布局文件和样板代码(如
findViewById
)。- 示例:
MainActivity.java
和activity_main.xml
文件中,包含了大量的样板代码。
- 示例:
-
难以维护和扩展:随着应用规模的增长,UI 代码变得难以维护和扩展。
- 示例:复杂的布局和嵌套容易导致代码难以维护。
-
动画和过渡实现复杂:实现复杂的动画和过渡效果需要编写大量的代码,且难以调试。
- 示例:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- 显示文本的 TextView --> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, World!" android:layout_centerInParent="true" android:visibility="gone" /> <!-- 切换文本可见性的按钮 --> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Show/Hide Text" android:layout_below="@id/textView" android:layout_centerHorizontal="true" /> </RelativeLayout>
import android.os.Bundle; import android.view.View; import android.view.animation.AlphaAnimation; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private TextView textView; private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取 TextView 和 Button 的引用 textView = findViewById(R.id.textView); button = findViewById(R.id.button); // 设置按钮点击监听器 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 切换文本的可见性并设置动画效果 if (textView.getVisibility() == View.GONE) { textView.setVisibility(View.VISIBLE); AlphaAnimation animation = new AlphaAnimation(0.0f, 1.0f); animation.setDuration(500); textView.startAnimation(animation); } else { AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f); animation.setDuration(500); textView.startAnimation(animation); textView.setVisibility(View.GONE); } } }); } }