kotlin中的模块化结构组件及工作原理

2025-03-15 13:50

本文主要是介绍kotlin中的模块化结构组件及工作原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《kotlin中的模块化结构组件及工作原理》本文介绍了Kotlin中模块化结构组件,包括ViewModel、LiveData、Room和Navigation的工作原理和基础使用,本文通过实例代码给大家...

模块化结构组件包含ViewModel、LiveData、Room 和 Navigation ,我将讲解它们的工作原理和基础使用。

ViewModel 工作原理

  • 创建与存储机制:当调用 ViewModelProvider 的 get 方法获取 ViewModel 实例时,ViewModelProvider 会先检查 ViewModelStore 中是否已存在该类型的实例。若存在则直接返回,若不存在则使用 ViewModelProvider.Factory 创建新实例并存储在 ViewModelStore 中。每个 Activity 和 Fragment 都有各自对应的 ViewModelStore,用于管理其内部的 ViewModel 实例。
  • 生命周期管理ViewModel 的生命周期与关联的 Activity 或 Fragment 紧密相关,但又有区别。在配置更改(如屏幕旋转)时,Activity 或 Fragment 会重新创建,而 ViewModelStore China编程会被保留,所以 ViewModel 实例也得以保留,从而保证数据的一致性。当 Activity 或 Fragment 被销毁(非因配置更改)时,ViewModelStore 会调用 clear 方法,进而调用 ViewModel 的 onCleared 方法,让开发者可以在此进行资源释放操作。

ViewModel 通过 ViewModelStore 存储实例,在配置更改时保留数据,在关联组件非配置更改销毁时释放资源。 

// 定义 ViewModel 类
import androidx.lifecycle.ViewModel
import androidx.lifecycle.MutableLiveData
class NewsViewModel : ViewModel() {
    // 定义 LiveData 存储新闻列表
    private val _newsList = MutableLiveData<List<String>>()
    val newsList: LiveData<List<String>> = _newsList
    init {
        // 模拟从网络数据库获取新闻数据
        fetchNews()
    }
    private fun fetchNews() {
        // 这里可以替换为真实的网络请求或数据库查询
        val mockNews = listOf("新闻1", "新闻2", "新闻3")
        _newsList.value = mockNews
    }
}
// 在 Activity 中使用 ViewModel
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
    private lateinit var newsViewModel: NewsViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView{"name":"GodelPlugin","parameters":{"input":"\"setContentView(R.layout.activity_main)\""}}<|FunctionExecuteEnd|><|FunctionExecuteResult|>setContentView(R.layout.activity_main)<|FunctionExecuteResultEnd|>
        // 获取 ViewModel 实例
        newsViephpwModel = ViewModelProvider(this).get(NewsViewModel::class.Java)
        // 观察 LiveData 数据变化
        newsViewModel.newsList.observe(this, { news ->
            // 更新 UI
            news.forEach {
                textView.append("$it\n")
            }
        })
    }
}

当屏幕旋转等配置更改时,MainActivity 重新创建,但 NewsViewModel 实例会从 ViewModelStore 中取出,数据得以保留。 

LiveData 工作原理

  • 数据持有与观察者管理LiveData 内部维护着一个数据对象和一个观察者列表。当调用 observe 方法注册观察者时,会将 LifecycleOwner 和 Observer 包装成 LifecycleBoundObserver 对象并添加到观察者列表中。
  • 生命周期感知LifecycleBoundObserver 实现了 LifecycleEventObserver 接口,能够监听 LifecycleOwner 的生命周期变化。当 LifecycleOwner 进入活跃状态(STARTED 或 RESUMED)时,LiveData 会将最新数据发送给该观察者;当 LifecycleOwner 进入销毁状态(DESTROYED)时,LiveData 会自动移除该观察者,避免内存泄漏。
  • 数据更新通知:当调用 setValue(主线程)或 postValue(子线程)方法更新数据时,LiveData 会检查所有观察者的生命周期状态,只有处于活跃状态的观察者才会收到 onChanged 方法的调用,从而更新 UI。

 LiveData 持有数据,通过 LifecycleBoundObserver 感知 LifecycleOwner 生命周期,仅在活跃状态时通知观察者。

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
    private val liveData = MutableLiveData<String>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView{"name":"GodelPlugin","parameters":{"input":"\"setContentView(R.layout.activity_main)\""}}<|FunctionExecuteEnd|><|FunctionExecuteResult|>setContentView(R.layout.activity_main)<|FunctionExecuteResu编程China编程ltEnd|>
        // 注册观察者
        liveData.observe(this, Observer { data ->
            // 处理数据变化
            textView.text = data
        })
        // 更新数据
        liveData.value = "新数据"
    }
}

liveData.observe 注册时将 this(即 MainActivity 作为 LifecycleOwner)和 Observer 包装,当 MainActivity 处于活跃状态且 liveData 数据更新时,Observer 的 onChanged 方法被调用。 

Room 工作原理

  • 抽象层封装:Room 提供了一个抽象层,开发者通过定义实体类(使用 @Entity 注解)、数据访问对象(DAO,使用 @Dao 注解)和数据库类(使用 @Database 注解)来描述数据库结构和操作。实体类对应数据库表,DAO 定义了对数据库的增删改查操作,数据库类则管理数据库的版本和 DAO 实例。
  • 编译时处理:在编译时,Room 会根据开发者定义的注解生成相应的 SQLite 语句和实现代码。这样可以在编译阶段就发现数据库操作中的错误,提高开发效率和代码的健壮性。
  • 线程管理:Room 默认不允许在主线程中执行数据库操作,因为数据库操作通常是耗时的,可能会导致 UI 卡顿。因此,Room 会将数据库操作放在后台线程中执行,开发者可以使用 suspend 函数(在 Kotlin 中)或自定义线程池来处理异步操作。

 Room 通过注解定义数据库结构和操作,编译时生成 SQL 语句和实现代码,默认在后台线程执行操作。

// 定义实体类
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "news")
data class News(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    val title: String
)
// 定义 DAO
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
@Dao
interface NewsDao {
    @Insert
    suspend fun insertNews(news: News)
    @Query("SELECT * FROM news")
    suspend fun getAllNews(): List<News>
}
// 定义数据库类
import androidx.room.Database
import andChina编程roidx.room.RoomDatabase
@Database(entities = [News::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun newsDao(): NewsDao
}
// 在 ViewModel 中使用 Room
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class NewsViewModel : ViewModel() {
    private val database = Room.databaseBuilder(
        applicationContext,
        AppDatabase::class.java,
        "news-database"
    ).build()
    private val newsDao = database.newsDao()
    fun insertNews(news: News) {
        viewModelScope.launch {
            newsDao.insertNews(news)
        }
    }
    fun getAllNews() {
        viewModelScope.launch {
            val newsList = newsDao.getAllNews()
            // 处理获取到的新闻列表
        }
    }
}

编译时,Room 会根据 @Entity@Dao 和 @Database 注解生成操作数据库的 SQL 语句和实现代码,suspend 函数保证数据库操作在后台线程执行。 

Navigation 工作原理

  • 导航图定义:开发者通过 XML 文件定义导航图,导航图中包含了应用的所有目的地(如 Fragment)、动作(用于在目的地之间导航)和参数传递规则。每个目的地都有唯一的标识符,动作则定义了从一个目的地到另一个目的地的导航路径。
  • 导航控制器管理NavController 是 Navigation 组件的核心,负责管理导航操作。它会根据导航图中的定义,处理目的地之间的切换和参数传递。在 Activity 或 Fragment 中,可以通过 findNavController 方法获取 NavController 实例,然后调用其 navigate 方法进行导航。
  • Back Stack 管理NavController 维护了一个返回栈(Back Stack),用于记录导航历史。当用户点击返回按钮时,NavController 会从返回栈中弹出上一个目的地,实现返回操作。开发者可以通过配置导航图中的 popUpTo 和 popUpToInclusive 属性来控制返回栈的行为。

Navigation 通过导航图定义目的地和动作,NavController 管理导航和返回栈。

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/firstFragment">
    <fragment
   javascript     android:id="@+id/firstFragment"
        android:name="com.example.myapp.FirstFragment"
        android:label="First Fragment">
        <action
            android:id="@+id/action_firstFragment_to_secondFragment"
            app:destination="@id/secondFragment" />
    </fragment>
    <fragment
        android:id="@+id/secondFragment"
        android:name="com.example.myapp.SecondFragment"
        android:label="Second Fragment" />
</navigation>

在 Activity 中设置导航宿主

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/navigation_graph" />

在 Fragment 中进行导航

import androidx.fragment.app.Fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
class FirstFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_first, container, false)
        view.findViewById<Button>(R.id.navigateButton).setOnClickListener {
            // 导航到 SecondFragment
            findNavController().navigate(R.id.action_firstFragment_to_secondFragment)
        }
        return view
    }
}

 NavController 根据导航图中的定义,处理从 FirstFragment 到 SecondFragment 的导航,同时管理返回栈以支持返回操作。

 总结:

  ViewModel 通过 ViewModelStore 管理 UI 数据并在配置变更时保持状态,LiveData 实现生命周期感知的可观察数据更新,Room 作为 SQLite ORM 自动生成数据库操作代码并处理线程,Navigation 利用导航图和 NavController 管理多 Fragment 导航,共同构建响应式、可维护的 Android 应用架构。

到此这篇关于kotlin中的模块化结构组件的文章就介绍到这了,更多相关kotlin模块化结构组件内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于kotlin中的模块化结构组件及工作原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153762

相关文章

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

MyBatis-Plus 与 Spring Boot 集成原理实战示例

《MyBatis-Plus与SpringBoot集成原理实战示例》MyBatis-Plus通过自动配置与核心组件集成SpringBoot实现零配置,提供分页、逻辑删除等插件化功能,增强MyBa... 目录 一、MyBATis-Plus 简介 二、集成方式(Spring Boot)1. 引入依赖 三、核心机制

Kotlin 枚举类使用举例

《Kotlin枚举类使用举例》枚举类(EnumClasses)是Kotlin中用于定义固定集合值的特殊类,它表示一组命名的常量,每个枚举常量都是该类的单例实例,接下来通过本文给大家介绍Kotl... 目录一、编程枚举类核心概念二、基础语法与特性1. 基本定义2. 带参数的枚举3. 实现接口4. 内置属性三、

redis和redission分布式锁原理及区别说明

《redis和redission分布式锁原理及区别说明》文章对比了synchronized、乐观锁、Redis分布式锁及Redission锁的原理与区别,指出在集群环境下synchronized失效,... 目录Redis和redission分布式锁原理及区别1、有的同伴想到了synchronized关键字

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

setsid 命令工作原理和使用案例介绍

《setsid命令工作原理和使用案例介绍》setsid命令在Linux中创建独立会话,使进程脱离终端运行,适用于守护进程和后台任务,通过重定向输出和确保权限,可有效管理长时间运行的进程,本文给大家介... 目录setsid 命令介绍和使用案例基本介绍基本语法主要特点命令参数使用案例1. 在后台运行命令2.

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分