kotlin与MVVM的结合使用总结(二)

打印 上一主题 下一主题

主题 978|帖子 978|积分 2934

  在 MVVM(Model - View - ViewModel)架构中,M 层即 Model 层,主要负责数据的管理、存储和获取,它与业务逻辑和数据处理处罚相关。在 Kotlin 中实现 MVVM 的 M 层,通常会涉及数据类的界说、数据的本地存储与远程获取等操纵,以下是详细的实现讲解:
1. 界说数据类

数据类是 Kotlin 中非常方便的特性,用于简洁地界说数据模型。它会自动天生 equals()、hashCode()、toString() 等方法。以下是一个简单的用户数据类示例:
  1. data class User(
  2.     val id: Int,
  3.     val name: String,
  4.     val age: Int,
  5.     val email: String
  6. )
复制代码
这个数据类 User 表现一个用户的基本信息,包含 id、name、age 和 email 四个属性。
2. 本地数据存储

如果需要将数据存储在本地,可以使用 Android 的 Room 数据库。Room 是 Android 官方提供的一个抽象层,用于在 SQLite 数据库上举行对象映射,结合 Kotlin 可以更方便地操纵数据库。
2.1 界说实体类

首先,要确保数据类符合 Room 的实体类要求,添加 @Entity 注解:
  1. import androidx.room.Entity
  2. import androidx.room.PrimaryKey
  3. @Entity(tableName = "users")
  4. data class User(
  5.     @PrimaryKey val id: Int,
  6.     val name: String,
  7.     val age: Int,
  8.     val email: String
  9. )
复制代码
这里的 @Entity 注解指定了该数据类对应数据库中的 users 表,@PrimaryKey 注解指定了 id 作为主键。
2.2 界说 DAO(数据访问对象)

DAO 用于界说数据库操纵的方法,使用 @Dao 注解:
  1. import androidx.room.Dao
  2. import androidx.room.Insert
  3. import androidx.room.Query
  4. @Dao
  5. interface UserDao {
  6.     @Insert
  7.     suspend fun insertUser(user: User)
  8.     @Query("SELECT * FROM users WHERE id = :id")
  9.     suspend fun getUserById(id: Int): User?
  10. }
复制代码
在这个 DAO 中,@Insert 注解表现插入操纵,@Query 注解用于自界说查询操纵。留意方法使用了 suspend 关键字,以便在协程中调用。
2.3 界说数据库

使用 @Database 注解界说数据库:
  1. import androidx.room.Database
  2. import androidx.room.RoomDatabase
  3. @Database(entities = [User::class], version = 1)
  4. abstract class AppDatabase : RoomDatabase() {
  5.     abstract fun userDao(): UserDao
  6. }
复制代码
这里指定了数据库包含的实体类为 User,版本号为 1,并提供了获取 UserDao 的抽象方法。
3. 远程数据获取

如果需要从网络获取数据,可以使用 Retrofit 库。Retrofit 是一个类型安全的 HTTP 客户端,结合 Kotlin 协程可以高效地举行网络请求。
3.1 界说 API 接口

  1. import retrofit2.http.GET
  2. import retrofit2.http.Path
  3. interface UserApiService {
  4.     @GET("users/{id}")
  5.     suspend fun getUserById(@Path("id") id: Int): User
  6. }
复制代码
这个接口界说了一个获取用户信息的方法,使用 @GET 注解指定请求的 URL,@Path 注解用于替换 URL 中的参数。
3.2 创建 Retrofit 实例


  1. import retrofit2.Retrofit
  2. import retrofit2.converter.gson.GsonConverterFactory
  3. object RetrofitClient {
  4.     private const val BASE_URL = "https://example.com/api/"
  5.     val instance: Retrofit by lazy {
  6.         Retrofit.Builder()
  7.            .baseUrl(BASE_URL)
  8.            .addConverterFactory(GsonConverterFactory.create())
  9.            .build()
  10.     }
  11.     val userApiService: UserApiService by lazy {
  12.         instance.create(UserApiService::class.java)
  13.     }
  14. }
复制代码
这里创建了一个 Retrofit 实例,并通过 create() 方法创建了 UserApiService 的实例。
4. 堆栈(Repository)模式

为了同一管理本地和远程数据的获取,通常会使用堆栈模式。堆栈类负责调和数据的来源,根据需要从本地数据库或远程服务器获取数据。
  1. class UserRepository(
  2.     private val userDao: UserDao,
  3.     private val userApiService: UserApiService
  4. ) {
  5.     suspend fun getUserById(id: Int): User? {
  6.         // 先从本地数据库获取数据
  7.         var user = userDao.getUserById(id)
  8.         if (user == null) {
  9.             // 如果本地没有数据,从网络获取
  10.             user = userApiService.getUserById(id)
  11.             if (user != null) {
  12.                 // 将从网络获取的数据保存到本地数据库
  13.                 userDao.insertUser(user)
  14.             }
  15.         }
  16.         return user
  17.     }
  18. }
复制代码
 在这个堆栈类中,getUserById 方法首先尝试从本地数据库获取用户数据,如果本地没有则从网络获取,并将获取到的数据保存到本地数据库。
  总结(M层)

  通过以上步调,我们在 Kotlin 中实现了 MVVM 架构的 M 层。主要包罗数据类的界说、本地数据存储(使用 Room)、远程数据获取(使用 Retrofit)以及堆栈模式的应用,这样可以有效地管理数据的来源和流向,进步代码的可维护性和可测试性。
下一层:V层  
  以下将详细介绍在 Kotlin 中实现 MVVM 架构里 V 层(View 层)的完整步调,并给出相应代码示例。V 层主要负责展示 UI 以及处理处罚用户交互,通常由 Activity 或 Fragment 实现。
项目准备

确保在 build.gradle 文件中添加必要依赖:
  1. dependencies {
  2.     // ViewModel 和 LiveData
  3.     implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
  4.     implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
  5.     // ViewBinding
  6.     android {
  7.         buildFeatures {
  8.             viewBinding = true
  9.         }
  10.     }
  11.     // Kotlin 协程
  12.     implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
  13. }
复制代码
界说布局文件

在 res/layout 目次下创建 activity_main.xml 文件,用于界说界面布局
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:orientation="vertical"
  6.     android:padding="16dp">
  7.     <EditText
  8.         android:id="@+id/et_input"
  9.         android:layout_width="match_parent"
  10.         android:layout_height="wrap_content"
  11.         android:hint="请输入内容" />
  12.     <Button
  13.         android:id="@+id/btn_send"
  14.         android:layout_width="wrap_content"
  15.         android:layout_height="wrap_content"
  16.         android:text="发送" />
  17.     <TextView
  18.         android:id="@+id/tv_result"
  19.         android:layout_width="wrap_content"
  20.         android:layout_height="wrap_content"
  21.         android:textSize="18sp"
  22.         android:paddingTop="16dp" />
  23. </LinearLayout>
复制代码
创建 ViewModel

ViewModel 负责处理处罚业务逻辑和数据管理,以下是 MainViewModel 的实现:
  1. import androidx.lifecycle.LiveData
  2. import androidx.lifecycle.MutableLiveData
  3. import androidx.lifecycle.ViewModel
  4. class MainViewModel : ViewModel() {
  5.     private val _result = MutableLiveData<String>()
  6.     val result: LiveData<String> = _result
  7.     fun processInput(input: String) {
  8.         // 简单处理输入,这里只是将输入内容反转
  9.         val processed = input.reversed()
  10.         _result.value = processed
  11.     }
  12. }
复制代码
创建 Activity 作为 V 层

使用 Kotlin 实现 MainActivity 作为 View 层,通过 ViewBinding 绑定视图,观察 ViewModel 中的数据变革并处理处罚用户交互:
  1. import android.os.Bundle
  2. import androidx.appcompat.app.AppCompatActivity
  3. import androidx.lifecycle.Observer
  4. import androidx.lifecycle.ViewModelProvider
  5. import com.example.mvvmexample.databinding.ActivityMainBinding
  6. class MainActivity : AppCompatActivity() {
  7.     private lateinit var binding: ActivityMainBinding
  8.     private lateinit var viewModel: MainViewModel
  9.     override fun onCreate(savedInstanceState: Bundle?) {
  10.         super.onCreate(savedInstanceState)
  11.         // 使用 ViewBinding 绑定布局
  12.         binding = ActivityMainBinding.inflate(layoutInflater)
  13.         setContentView(binding.root)
  14.         // 获取 ViewModel 实例
  15.         viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
  16.         // 设置按钮点击事件监听器
  17.         binding.btnSend.setOnClickListener {
  18.             // 获取输入框中的内容
  19.             val input = binding.etInput.text.toString()
  20.             // 调用 ViewModel 的方法处理输入
  21.             viewModel.processInput(input)
  22.         }
  23.         // 观察 ViewModel 中的数据变化
  24.         viewModel.result.observe(this, Observer { result ->
  25.             // 更新 UI 显示处理结果
  26.             binding.tvResult.text = "处理结果: $result"
  27.         })
  28.     }
  29. }
复制代码
代码表明



  • ViewBinding 的使用

    • ActivityMainBinding.inflate(layoutInflater) 用于实例化绑定类,通过 setContentView(binding.root) 设置布局,之后可直接使用 binding 对象访问布局中的视图组件,如 binding.etInput、binding.btnSend 等。

  • ViewModel 的获取

    • ViewModelProvider(this).get(MainViewModel::class.java) 用于获取 MainViewModel 的实例,确保在 Activity 的生命周期内使用同一个 ViewModel 实例。

  • 用户交互处理处罚

    • 通过 binding.btnSend.setOnClickListener 为按钮设置点击事件监听器,当按钮被点击时,获取输入框中的内容并调用 ViewModel 的 processInput 方法举行处理处罚。

  • 数据观察

    • viewModel.result.observe(this, Observer { ... }) 用于观察 LiveData 的数据变革,当 LiveData 的值发生改变时,会触发 Observer 中的代码块,从而更新 UI。

使用 Fragment 作为 V 层(可选)

如果使用 Fragment 作为 V 层,实现方式类似:
创建布局文件 fragment_main.xml


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:orientation="vertical"
  6.     android:padding="16dp">
  7.     <EditText
  8.         android:id="@+id/et_input_fragment"
  9.         android:layout_width="match_parent"
  10.         android:layout_height="wrap_content"
  11.         android:hint="请输入内容" />
  12.     <Button
  13.         android:id="@+id/btn_send_fragment"
  14.         android:layout_width="wrap_content"
  15.         android:layout_height="wrap_content"
  16.         android:text="发送" />
  17.     <TextView
  18.         android:id="@+id/tv_result_fragment"
  19.         android:layout_width="wrap_content"
  20.         android:layout_height="wrap_content"
  21.         android:textSize="18sp"
  22.         android:paddingTop="16dp" />
  23. </LinearLayout>
复制代码
 创建 Fragment
  1. import android.os.Bundle
  2. import android.view.LayoutInflater
  3. import android.view.View
  4. import android.view.ViewGroup
  5. import androidx.fragment.app.Fragment
  6. import androidx.lifecycle.Observer
  7. import androidx.lifecycle.ViewModelProvider
  8. import com.example.mvvmexample.databinding.FragmentMainBinding
  9. class MainFragment : Fragment() {
  10.     private var _binding: FragmentMainBinding? = null
  11.     private val binding get() = _binding!!
  12.     private lateinit var viewModel: MainViewModel
  13.     override fun onCreateView(
  14.         inflater: LayoutInflater,
  15.         container: ViewGroup?,
  16.         savedInstanceState: Bundle?
  17.     ): View? {
  18.         // 使用 ViewBinding 绑定布局
  19.         _binding = FragmentMainBinding.inflate(inflater, container, false)
  20.         return binding.root
  21.     }
  22.     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  23.         super.onViewCreated(view, savedInstanceState)
  24.         // 获取 ViewModel 实例
  25.         viewModel = ViewModelProvider(requireActivity()).get(MainViewModel::class.java)
  26.         // 设置按钮点击事件监听器
  27.         binding.btnSendFragment.setOnClickListener {
  28.             val input = binding.etInputFragment.text.toString()
  29.             viewModel.processInput(input)
  30.         }
  31.         // 观察 ViewModel 中的数据变化
  32.         viewModel.result.observe(viewLifecycleOwner, Observer { result ->
  33.             binding.tvResultFragment.text = "处理结果: $result"
  34.         })
  35.     }
  36.     override fun onDestroyView() {
  37.         super.onDestroyView()
  38.         _binding = null
  39.     }
  40. }
复制代码
总结(V层)

通过以上步调,我们可以在 Kotlin 中使用 Activity 或 Fragment 作为 MVVM 架构的 V 层,借助 ViewBinding 绑定视图,使用 ViewModelProvider 获取 ViewModel 实例,处理处罚用户交互并观察 ViewModel 中的数据变革以更新 UI,实现视图和业务逻辑的分离,进步代码的可维护性和可测试性。
因为太多了,我就先讲解前两个层,下一节我将阐述最重要的VM层
谢谢观看!!!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

不到断气不罢休

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表