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()
                    [email protected]
                }

                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>>类型

猜你喜欢

转载自blog.csdn.net/mp624183768/article/details/126803436