📅  最后修改于: 2023-12-03 15:08:22.922000             🧑  作者: Mango
MVVM 是一种使用数据绑定的软件架构模式,是 Model-View-ViewModel(模型-视图-视图模型)的缩写。它是将我们的代码分为三个部分:
Room 是一个带有类型检查的 SQL 数据库,可以帮助我们轻松地在 Android 应用程序中存储数据。
在本文中,我们将讲解如何使用 MVVM 和 Room 数据库构建一个简单的 Note Android 应用程序。
首先,我们需要创建一个新的 Android Studio 项目。选择一个空的活动,并将其命名为 "Notes"。
要使用 Room 数据库,我们需要在项目中添加以下依赖项:
implementation "androidx.room:room-runtime:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
我们需要为 Note 对象创建一个实体类。实体类是一个在数据库中映射到表的 Java 类。它的属性对应于表中的列。
@Entity(tableName = "notes_table")
data class Note(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val title: String,
val content: String
)
在这里,我们使用了 @Entity 注释来指示这是一个实体类,并使用了 @PrimaryKey 注释来指定主键。
接下来,我们将创建一个 Data Access Object(DAO),它定义了我们可以执行的操作。
@Dao
interface NoteDao {
@Query("SELECT * FROM notes_table")
fun getNotes(): LiveData<List<Note>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertOrUpdate(note: Note)
@Delete
suspend fun delete(note: Note)
}
在这里,我们使用了 @Dao 注释来指示这个接口是一个 DAO。
对于查询,我们使用 @Query 注释来指定 SQL 查询。
对于插入,我们使用 @Insert 注释来指定插入操作,并使用 @OnConflict 注释来指定当记录已经存在时应该执行的操作。
对于删除,我们使用 @Delete 注释来指定删除操作。
我们也使用了 suspend 关键字来指示这些操作是挂起函数,因为它们将在后台线程中运行。
我们需要创建一个 Room 数据库,它将包含我们的 Note 对象。
@Database(entities = [Note::class], version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDao
companion object {
@Volatile
private var INSTANCE: NoteDatabase? = null
fun getDatabase(context: Context): NoteDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java,
"note_database"
).build()
INSTANCE = instance
instance
}
}
}
}
在这里,我们使用了 @Database 注释来指示这个类是一个 Room 数据库,并指定了它所包含的实体类和版本号。
我们定义了一个 getDatabase 函数,它将返回 NoteDatabase 对象。该函数使用单例模式来确保在整个应用程序中只创建一个实例。
我们将创建一个 ViewModel 类,它将用来管理 Note 对象的生命周期和状态。
class NoteViewModel(application: Application) : AndroidViewModel(application) {
private val noteDao = NoteDatabase.getDatabase(application).noteDao()
val notes = noteDao.getNotes()
fun insertOrUpdate(note: Note) {
viewModelScope.launch(Dispatchers.IO) {
noteDao.insertOrUpdate(note)
}
}
fun delete(note: Note) {
viewModelScope.launch(Dispatchers.IO) {
noteDao.delete(note)
}
}
}
在这里,我们继承了 AndroidViewModel,并使用了 NoteDatabase.getDatabase 函数来获得 NoteDao 对象。我们使用 LiveData<List
我们为 insertOrUpdate 和 delete 函数使用了协程来将它们从主线程移动到后台线程。
我们将在布局文件中创建一个 RecyclerView 来显示所有 Note 对象。
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/notes_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
我们需要为 RecyclerView 创建一个适配器。适配器是将数据集绑定到 RecyclerView 上的关键组件之一。
class NotesRecyclerViewAdapter(private val notes: List<Note>, private val viewModel: NoteViewModel) : RecyclerView.Adapter<NotesRecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.note_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val note = notes[position]
holder.titleView.text = note.title
holder.contentView.text = note.content
holder.itemView.setOnClickListener {
val action = NotesFragmentDirections.actionNotesFragmentToNoteDetailFragment(note)
it.findNavController().navigate(action)
}
holder.itemView.setOnLongClickListener {
viewModel.delete(note)
true
}
}
override fun getItemCount() = notes.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val titleView: TextView = itemView.findViewById(R.id.note_item_title)
val contentView: TextView = itemView.findViewById(R.id.note_item_content)
}
}
在这里,我们定义了一个 ViewHolder 类,它包含我们在 RecyclerView 中显示的每个 item 的视图。
我们为 onCreateViewHolder 函数和 onBindViewHolder 函数定义了实现。onCreateViewHolder 函数用于创建 ViewHolder 对象,而 onBindViewHolder 函数用于将数据绑定到 ViewHolder 上。
我们为 getItemCount 函数返回列表项数量。
我们将使用 Navigation 组件构建 NotesFragment 和 NoteDetailFragment。
<fragment
android:id="@+id/nav_notes"
android:name="com.example.notes.ui.notes.NotesFragment"
android:label="Notes"
tools:layout="@layout/fragment_notes" >
<action
android:id="@+id/action_notes_to_noteDetail"
app:destination="@id/noteDetailFragment" />
</fragment>
<fragment
android:id="@+id/noteDetailFragment"
android:name="com.example.notes.ui.notes.NoteDetailFragment"
android:label="Note Detail"
tools:layout="@layout/fragment_note_detail" >
<argument
android:name="note"
app:argType="com.example.notes.data.Note" />
</fragment>
我们将使用 NotesFragment 来显示所有 Note 对象,并使用 NoteDetailFragment 来显示特定的 Note 对象。
class NotesFragment : Fragment() {
private lateinit var viewModel: NoteViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_notes, container, false)
val recyclerView: RecyclerView = view.findViewById(R.id.notes_recyclerview)
val adapter = NotesRecyclerViewAdapter(emptyList(), viewModel)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(requireContext())
viewModel.notes.observe(viewLifecycleOwner, Observer {
adapter.notes = it
})
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(requireActivity()).get(NoteViewModel::class.java)
}
}
在这里,我们定义了一个 NotesFragment 类,并在 onCreateView 函数中创建了一个 RecyclerView 和一个 NotesRecyclerViewAdapter。
我们使用 ViewModelProvider 来获取 NoteViewModel 并将其存储在 viewModel 变量中。
我们在 onViewCreated 函数中获取 ViewModelProvider 并将其存储在 viewModel 变量中。
我们观察 LiveData<List
class NoteDetailFragment : Fragment() {
private lateinit var viewModel: NoteViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_note_detail, container, false)
val args: NoteDetailFragmentArgs by navArgs()
val note = args.note
val titleEditText: EditText = view.findViewById(R.id.note_detail_title_edittext)
val contentEditText: EditText = view.findViewById(R.id.note_detail_content_edittext)
titleEditText.setText(note.title)
contentEditText.setText(note.content)
view.findViewById<Button>(R.id.update_button).setOnClickListener {
note.title = titleEditText.text.toString()
note.content = contentEditText.text.toString()
viewModel.insertOrUpdate(note)
it.findNavController().navigateUp()
}
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(requireActivity()).get(NoteViewModel::class.java)
}
}
在这里,我们定义了一个 NoteDetailFragment 类,并在 onCreateView 函数中获取我们的 Note 对象和 EditText。
我们为 "update" 按钮设置了点击事件,以更新我们的 Note 对象,并使用 ViewModel 将其保存到数据库中。
我们使用 ViewModelProvider 来获取 NoteViewModel 并将其存储在 viewModel 变量中。
在本文中,我们讲解了如何使用 MVVM 和 Room 数据库构建一个简单的 Note Android 应用程序。我们创建了一个实体类、DAO、数据库、ViewModel、布局文件、RecyclerViewAdapter 和两个 Fragment。我们将它们连接起来以构建一个完整的应用程序,使我们可以在 Android 设备上记录和查看笔记。