Android Kotlin Room 与Flow的应用 demo 添加数据并展示

Posted 安果移不动

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Kotlin Room 与Flow的应用 demo 添加数据并展示相关的知识,希望对你有一定的参考价值。

demo 添加数据并展示

 依赖

    implementation "androidx.activity:activity-ktx:1.5.1"
    implementation "androidx.fragment:fragment-ktx:1.5.2"

    implementation "androidx.room:room-runtime:2.4.3"
    implementation "androidx.room:room-ktx:2.4.3"

 

package com.example.android_flow_practice.db

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class User(
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "first_name") val firstName: String,
    @ColumnInfo(name = "last_name") val lastName: String
)
package com.example.android_flow_practice.db

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kotlinx.coroutines.flow.Flow

@Dao
interface UserDao 


    //两条冲突就会替换
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insert(user: User)

    @Query("SELECT * FROM user")
    fun getAll(): Flow<List<User>>

package com.example.android_flow_practice.db

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class AppDataBase : RoomDatabase() 
    abstract fun userDao(): UserDao

    companion object 
        private var instance:AppDataBase? = null

        fun getInstance(context: Context): AppDataBase 
            return instance ?: synchronized(this) 
                Room.databaseBuilder(context, AppDataBase::class.java,"user.db").build()
                    .also  instance = it 
            
        

    

数据库相关的准备好了

那么布局

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".fragment.UserFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/et_id"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="用户id" />

        <EditText
            android:id="@+id/et_first_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="姓" />

        <EditText
            android:id="@+id/et_last_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="名" />

    </LinearLayout>

    <Button
        android:id="@+id/bt_add_user"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="添加用户" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</LinearLayout>

再那么。对应的fragment

package com.example.android_flow_practice.fragment

import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView.LayoutManager
import com.example.android_flow_practice.R
import com.example.android_flow_practice.adapter.UserAdapter
import com.example.android_flow_practice.databinding.FragmentDownloadBinding
import com.example.android_flow_practice.databinding.FragmentUserBinding
import com.example.android_flow_practice.viewmodel.UserViewModel
import kotlinx.coroutines.flow.collect

class UserFragment : Fragment() 

    private val viewModel: UserViewModel by viewModels()

    private val mBinding: FragmentUserBinding by lazy 
        FragmentUserBinding.inflate(layoutInflater)
    

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? 
        // Inflate the layout for this fragment
        return mBinding.root
    

    private val TAG = "UserFragment"


    override fun onActivityCreated(savedInstanceState: Bundle?) 
        super.onActivityCreated(savedInstanceState)
        context?.let 

            mBinding.rv.layoutManager = LinearLayoutManager(it)

            mBinding.btAddUser.setOnClickListener 

                val uid = mBinding.etId.text.trim().toString();
                val firstName = mBinding.etFirstName.text.trim().toString();
                val lastName = mBinding.etLastName.text.trim().toString();
                if (TextUtils.isEmpty(firstName) || TextUtils.isEmpty(
                        lastName
                    )
                ) 
                    Toast.makeText(requireContext(), "数据不能为空", Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                

                viewModel.insert(
                    uid = uid.toInt(), firstName = firstName, lastName = lastName
                )


            


        
        context?.let 

            lifecycleScope.launchWhenCreated 
                viewModel.getAll().collect  value ->
                    Log.e(TAG, "onActivityCreated: value$value")
                    val adapter = UserAdapter(it)
                    mBinding.rv.adapter = adapter
                    adapter.setData(value)
                
            

        

    

里面用到了adapter。

package com.example.android_flow_practice.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.android_flow_practice.databinding.ItemUserBinding
import com.example.android_flow_practice.db.User

class UserAdapter(private val context: Context) : RecyclerView.Adapter<BindingViewHolder>() 

    private val data = ArrayList<User>()
    fun setData(data: List<User>) 
        this.data.clear()
        this.data.addAll(data);
        notifyDataSetChanged()
    

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder 
        val binding = ItemUserBinding.inflate(LayoutInflater.from(context), parent, false)
        return BindingViewHolder(binding = binding)
    

    override fun getItemCount(): Int 
        return data.size
    

    override fun onBindViewHolder(holder: BindingViewHolder, position: Int) 
        val item = data[position]
        val binding = holder.binding as ItemUserBinding
        binding.text.text = "$item.id, $item.firstName $item.lastName"

    

适配器又用到了viewHolder

package com.example.android_flow_practice.adapter

import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding


class BindingViewHolder(val binding: ViewBinding) : RecyclerView.ViewHolder(binding.root) 

再继续

rv用到的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:paddingVertical="4dp"
        android:textSize="26sp" />

</LinearLayout>

那么adapter的代码就完成了

最后数据封装在viewModel当中

package com.example.android_flow_practice.viewmodel

import android.app.Application
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import com.example.android_flow_practice.db.AppDataBase
import com.example.android_flow_practice.db.User
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import javax.security.auth.login.LoginException

class UserViewModel(app: Application) : AndroidViewModel(app) 
    private val TAG = "UserViewModel"
    fun insert(uid: Int, firstName: String, lastName: String) 
        viewModelScope.launch 
            AppDataBase.getInstance(getApplication()).userDao()
                .insert(User(uid, firstName, lastName))

            Log.e(TAG, "insert user :$uid")
        
    

    fun getAll(): Flow<List<User>> 
        return AppDataBase.getInstance(getApplication()).userDao().getAll()
            .catch  e -> e.printStackTrace() .flowOn(Dispatchers.IO)


    

至此 就完成了。

 

 自动查询数据并且将数据设置上去。。核心代码就这些

提供数据提供的也是Flow<List<User>>类型

 

以上是关于Android Kotlin Room 与Flow的应用 demo 添加数据并展示的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 协程Flow 异步流 ② ( 使用 Flow 异步流持续获取不同返回值 | Flow 异步流获取返回值方式与其它方式对比 | 在 Android 中使用 Flow 异步流下载文件 )

Kotlin 协程Flow 异步流 ② ( 使用 Flow 异步流持续获取不同返回值 | Flow 异步流获取返回值方式与其它方式对比 | 在 Android 中使用 Flow 异步流下载文件 )

Android的room数据库使用小结(kotlin)

Android Room Persistence 库和 Kotlin

官方推荐 Flow 取代 LiveData,有必要吗?

Kotlin-Flow常见场景下的使用