Android开发常用外部组件及使用指南(下)
文章目录
- 八、响应式编程组件
- 1. RxJava
- 1.1 引入依赖
- 1.2 基本使用
- 2. Kotlin协程与Flow
- 2.1 基本使用
- 九、测试组件
- 1. JUnit
- 1.1 基本使用
- 2. Mockito
- 2.1 引入依赖
- 2.2 基本使用
- 3. Espresso
- 3.1 引入依赖
- 3.2 基本使用
- 十、性能优化组件
- 1. LeakCanary
- 1.1 引入依赖
- 1.2 基本使用
- 2. Chucker
- 2.1 引入依赖
- 2.2 基本使用
- 十一、安全组件
- 1. EncryptedSharedPreferences
- 1.1 引入依赖
- 1.2 基本使用
- 2. SQLCipher
- 2.1 引入依赖
- 2.2 基本使用
- 十二、其他实用组件
- 1. Timber
- 1.1 引入依赖
- 1.2 基本使用
- 2. WorkManager
- 2.1 引入依赖
- 2.2 基本使用
- 十三、组件化架构
- 1. 模块化设计
- 2. 模块间通信
- 2.1 接口暴露
- 2.2 使用路由框架
- ARouter引入
- ARouter使用
- 十四、Jetpack组件
- 1. ViewModel
- 1.1 基本使用
- 2. LiveData
- 2.1 基本使用
- 3. DataBinding
- 3.1 启用DataBinding
- 3.2 基本使用
- 4. Navigation
- 4.1 引入依赖
- 4.2 基本使用
- 十五、跨平台开发框架
- 1. Flutter模块集成
- 1.1 添加Flutter模块
- 1.2 配置settings.gradle
- 1.3 添加依赖
- 1.4 使用FlutterFragment
- 2. KMM (Kotlin Multiplatform Mobile)
- 2.1 项目结构
- 2.2 共享模块build.gradle
- 2.3 共享代码示例
八、响应式编程组件
1. RxJava
RxJava是一个基于观察者模式的异步编程库。
1.1 引入依赖
implementation "io.reactivex.rxjava3:rxjava:3.1.3"
implementation "io.reactivex.rxjava3:rxandroid:3.0.0"
implementation "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
1.2 基本使用
// 创建Observable
val observable = Observable.create<String> { emitter ->emitter.onNext("Hello")emitter.onNext("World")emitter.onComplete()
}// 操作符链式调用
observable.map { it.length }.filter { it > 3 }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe({ length -> println("Length: $length") },{ error -> println("Error: $error") },{ println("Completed") })// 与Retrofit结合
interface ApiService {@GET("users")fun getUsers(): Observable<List<User>>
}apiService.getUsers().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe({ users ->// 处理用户列表}, { error ->// 处理错误})
2. Kotlin协程与Flow
Kotlin协程是官方推荐的异步解决方案,Flow是响应式流实现。
2.1 基本使用
// 协程作用域
lifecycleScope.launch {val result = withContext(Dispatchers.IO) {// IO操作"Result"}// 更新UItextView.text = result
}// Flow基本使用
fun getNumbers(): Flow<Int> = flow {for (i in 1..10) {delay(100)emit(i)}
}lifecycleScope.launch {getNumbers().filter { it % 2 == 0 }.map { it * it }.collect { number ->println(number)}
}// 与Room结合
@Dao
interface UserDao {@Query("SELECT * FROM users")fun getUsers(): Flow<List<User>>
}viewModelScope.launch {userDao.getUsers().collect { users ->// 自动接收数据库变化}
}
九、测试组件
1. JUnit
Java单元测试框架,Android开发的基础测试工具。
1.1 基本使用
class ExampleUnitTest {@Testfun addition_isCorrect() {assertEquals(4, 2 + 2)}@Testfun `test user creation`() {val user = User(1, "John", 30)assertThat(user.name, `is`("John"))assertThat(user.age, greaterThan(20))}
}
2. Mockito
Mock框架,用于创建测试替身。
2.1 引入依赖
testImplementation "org.mockito:mockito-core:4.3.1"
testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"
2.2 基本使用
class UserServiceTest {@Testfun `should return user by id`() {// 创建mockval userRepository = mock<UserRepository>()// 设置mock行为whenever(userRepository.getUser(1)).thenReturn(User(1, "John", 30))// 创建被测试对象val userService = UserService(userRepository)// 执行测试val user = userService.getUser(1)// 验证结果assertEquals("John", user.name)verify(userRepository).getUser(1)}
}
3. Espresso
UI测试框架,用于模拟用户操作。
3.1 引入依赖
androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
androidTestImplementation "androidx.test:runner:1.4.0"
androidTestImplementation "androidx.test:rules:1.4.0"
3.2 基本使用
@RunWith(AndroidJUnit4::class)
class MainActivityTest {@get:Ruleval activityRule = ActivityScenarioRule(MainActivity::class.java)@Testfun testLoginButton() {// 输入文本onView(withId(R.id.username)).perform(typeText("user"), closeSoftKeyboard())onView(withId(R.id.password)).perform(typeText("pass"), closeSoftKeyboard())// 点击按钮onView(withId(R.id.login)).perform(click())// 验证结果onView(withId(R.id.result)).check(matches(withText("Login successful")))}
}
十、性能优化组件
1. LeakCanary
内存泄漏检测工具。
1.1 引入依赖
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
1.2 基本使用
// 无需初始化代码,自动工作
// 当检测到内存泄漏时,会显示通知
2. Chucker
网络请求监控工具。
2.1 引入依赖
debugImplementation "com.github.chuckerteam.chucker:library:3.5.2"
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:3.5.2"
2.2 基本使用
val client = OkHttpClient.Builder().addInterceptor(ChuckerInterceptor(context)).build()
十一、安全组件
1. EncryptedSharedPreferences
加密的SharedPreferences实现。
1.1 引入依赖
implementation "androidx.security:security-crypto:1.1.0-alpha03"
1.2 基本使用
val masterKey = MasterKey.Builder(context).setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build()val sharedPreferences = EncryptedSharedPreferences.create(context,"secret_shared_prefs",masterKey,EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)with(sharedPreferences.edit()) {putString("api_key", "secret-api-key")apply()
}val apiKey = sharedPreferences.getString("api_key", null)
2. SQLCipher
SQLite数据库加密解决方案。
2.1 引入依赖
implementation 'net.zetetic:android-database-sqlcipher:4.5.0'
2.2 基本使用
val factory = SupportFactory("database-password".toByteArray())
val database = SQLiteDatabase.openOrCreateDatabase(context.getDatabasePath("encrypted.db"),"database-password",null,factory
)// 或者与Room一起使用
Room.databaseBuilder(context, AppDatabase::class.java, "encrypted.db").openHelperFactory(factory).build()
十二、其他实用组件
1. Timber
日志工具,比Android原生Log更强大。
1.1 引入依赖
implementation 'com.jakewharton.timber:timber:5.0.1'
1.2 基本使用
// Application中初始化
if (BuildConfig.DEBUG) {Timber.plant(Timber.DebugTree())
}// 使用
Timber.d("Debug message")
Timber.i("User %s logged in", userName)
Timber.e(exception, "Error while fetching data")
2. WorkManager
后台任务调度库。
2.1 引入依赖
implementation "androidx.work:work-runtime-ktx:2.7.1"
2.2 基本使用
// 定义Worker
class UploadWorker(appContext: Context, workerParams: WorkerParameters) : CoroutineWorker(appContext, workerParams) {override suspend fun doWork(): Result {val data = inputData.getString("data_key")// 执行上传操作return Result.success()}
}// 调度工作
val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>().setInputData(workDataOf("data_key" to "value")).setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()).build()WorkManager.getInstance(context).enqueue(uploadWorkRequest)// 观察工作状态
WorkManager.getInstance(context).getWorkInfoByIdLiveData(uploadWorkRequest.id).observe(this) { workInfo ->when (workInfo?.state) {WorkInfo.State.SUCCEEDED -> { /* 处理成功 */ }WorkInfo.State.FAILED -> { /* 处理失败 */ }else -> { /* 其他状态 */ }}}
十三、组件化架构
1. 模块化设计
大型项目通常采用模块化设计,常见模块划分:
- app: 主模块,包含应用入口
- core: 核心模块,包含基础功能
- feature-xxx: 功能模块,按功能划分
- data: 数据模块,包含数据源和仓库
- domain: 领域模块,包含业务逻辑
2. 模块间通信
2.1 接口暴露
// 在core模块定义接口
interface UserService {fun getUser(id: Int): User
}// 在data模块实现
class UserServiceImpl @Inject constructor(private val userRepository: UserRepository
) : UserService {override fun getUser(id: Int): User {return userRepository.getUser(id)}
}// 在feature模块使用
class UserViewModel @Inject constructor(private val userService: UserService
) : ViewModel()
2.2 使用路由框架
如ARouter或Navigation组件。
ARouter引入
// 模块级build.gradle
kapt {arguments {arg("AROUTER_MODULE_NAME", project.getName())}
}dependencies {implementation 'com.alibaba:arouter-api:1.5.2'kapt 'com.alibaba:arouter-compiler:1.5.2'
}
ARouter使用
// 1. 初始化
ARouter.init(application)// 2. 定义路由路径
@Route(path = "/user/detail")
class UserDetailActivity : AppCompatActivity()// 3. 跳转
ARouter.getInstance().build("/user/detail").withInt("id", 123).navigation()// 4. 服务发现
val userService = ARouter.getInstance().build("/service/user").navigation() as UserService
十四、Jetpack组件
1. ViewModel
管理界面相关数据,生命周期感知。
1.1 基本使用
class MyViewModel : ViewModel() {private val _data = MutableLiveData<String>()val data: LiveData<String> = _datafun loadData() {viewModelScope.launch {val result = repository.fetchData()_data.value = result}}
}// Activity/Fragment中
private val viewModel by viewModels<MyViewModel>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)viewModel.data.observe(this) { data ->// 更新UI}viewModel.loadData()
}
2. LiveData
生命周期感知的数据持有者。
2.1 基本使用
val currentUser: LiveData<User> = userRepository.getUser()// 观察
currentUser.observe(this) { user ->// 更新UI
}// 转换
val userName = Transformations.map(currentUser) { user ->user.name
}// 合并
val userAndPosts = MediatorLiveData<Pair<User, List<Post>>>().apply {addSource(currentUser) { user ->value = user to (value?.second ?: emptyList())}addSource(posts) { posts ->value = (value?.first ?: User()) to posts}
}
3. DataBinding
声明式地将布局与数据绑定。
3.1 启用DataBinding
android {buildFeatures {dataBinding true}
}
3.2 基本使用
<!-- 布局文件 -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variable name="user" type="com.example.User"/><variable name="viewModel" type="com.example.MyViewModel"/></data><LinearLayout><TextViewandroid:text="@{user.name}"android:onClick="@{() -> viewModel.onUserClick()}"/></LinearLayout>
</layout>
// Activity中
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)binding.user = user
binding.viewModel = viewModel
binding.lifecycleOwner = this
4. Navigation
简化Fragment导航。
4.1 引入依赖
implementation "androidx.navigation:navigation-fragment-ktx:2.3.5"
implementation "androidx.navigation:navigation-ui-ktx:2.3.5"
4.2 基本使用
<!-- nav_graph.xml -->
<navigation xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"app:startDestination="@id/homeFragment"><fragmentandroid:id="@+id/homeFragment"android:name="com.example.HomeFragment"><actionandroid:id="@+id/action_home_to_detail"app:destination="@id/detailFragment"/></fragment><fragmentandroid:id="@+id/detailFragment"android:name="com.example.DetailFragment"><argumentandroid:name="itemId"app:argType="integer"/></fragment>
</navigation>
// 导航到详情页
findNavController().navigate(R.id.action_home_to_detail,bundleOf("itemId" to 123)
)// 接收参数
val args by navArgs<DetailFragmentArgs>()
val itemId = args.itemId
十五、跨平台开发框架
1. Flutter模块集成
在现有Android应用中集成Flutter模块。
1.1 添加Flutter模块
# 在Android项目同级目录
flutter create -t module --org com.example my_flutter_module
1.2 配置settings.gradle
include ':app'
setBinding(new Binding([gradle: this]))
evaluate(new File(settingsDir.parentFile,'my_flutter_module/.android/include_flutter.groovy'
))
1.3 添加依赖
dependencies {implementation project(':flutter')
}
1.4 使用FlutterFragment
val flutterFragment = FlutterFragment.createDefault()
supportFragmentManager.beginTransaction().add(R.id.fragment_container, flutterFragment).commit()
2. KMM (Kotlin Multiplatform Mobile)
使用Kotlin开发跨平台共享代码。
2.1 项目结构
project/
├── androidApp/ # Android应用模块
├── iosApp/ # iOS应用模块
└── shared/ # 共享代码模块
2.2 共享模块build.gradle
plugins {id 'org.jetbrains.kotlin.multiplatform'
}kotlin {android()ios()sourceSets {commonMain {dependencies {implementation kotlin('stdlib-common')// 其他通用依赖}}androidMain {dependencies {implementation kotlin('stdlib')// Android特定依赖}}iosMain {// iOS特定依赖}}
}
2.3 共享代码示例
// shared/src/commonMain/kotlin/Platform.kt
expect class Platform() {val platform: String
}// shared/src/androidMain/kotlin/Platform.kt
actual class Platform actual constructor() {actual val platform: String = "Android ${android.os.Build.VERSION.SDK_INT}"
}// shared/src/iosMain/kotlin/Platform.kt
actual class Platform actual constructor() {actual val platform: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}