Android 笔记 App3:添加笔记创建和编辑功能

133 阅读2分钟

添加笔记创建和编辑功能

我们将逐步实现笔记的创建和编辑功能。以下是详细的实现步骤:


1. 数据模型

首先,定义一个 Note 数据类来表示笔记。

Note.kt

package com.nemo.notes.model

import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.Date

@Entity(tableName = "notes")
data class Note(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val title: String,
    val content: String,
    val createdAt: Date = Date(),
    val updatedAt: Date = Date()
)

2. 数据库访问对象 (DAO)

定义一个 NoteDao 接口来操作数据库。

NoteDao.kt

package com.nemo.notes.database  
  
import androidx.room.Dao  
import androidx.room.Delete  
import androidx.room.Insert  
import androidx.room.Query  
import androidx.room.Update  
import com.nemo.notes.model.Note  
import kotlinx.coroutines.flow.Flow  
  
@Dao  
interface NoteDao {  
    @Query("SELECT * FROM notes ORDER BY updatedAt DESC")  
    fun getAllNotes(): Flow<List<Note>>  
  
    @Insert  
    suspend fun insert(note: Note): Long  
  
    @Update  
    suspend fun update(note: Note): Int  
  
    @Query("DELETE FROM notes WHERE id = :noteId")  
    suspend fun delete(noteId: Long): Int  
  
    @Delete  
    suspend fun delete(note: Note): Int  
}

3. 数据库

创建一个 NoteDatabase 类来管理数据库。

NoteDatabase.kt

package com.nemo.notes.database

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.notes.model.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
            }
        }
    }
}

4. 仓库

创建一个 NoteRepository 类来管理数据操作。

NoteRepository.kt

package com.nemo.notes.repository

import com.example.notes.database.NoteDao
import com.example.notes.model.Note
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class NoteRepository @Inject constructor(
    private val noteDao: NoteDao
) {
    fun getAllNotes(): Flow<List<Note>> = noteDao.getAllNotes()

    suspend fun insert(note: Note) = noteDao.insert(note)

    suspend fun update(note: Note) = noteDao.update(note)

    suspend fun delete(noteId: Long) = noteDao.delete(noteId)
}

5. ViewModel

创建一个 NoteViewModel 类来管理 UI 数据。

NoteViewModel.kt

package com.nemo.notes.viewmodel  
  
import androidx.lifecycle.ViewModel  
import androidx.lifecycle.viewModelScope  
import com.nemo.notes.model.Note  
import com.nemo.notes.repository.NoteRepository  
import dagger.hilt.android.lifecycle.HiltViewModel  
import kotlinx.coroutines.flow.Flow  
import kotlinx.coroutines.launch  
import javax.inject.Inject  
  
@HiltViewModel  
class NoteViewModel @Inject constructor(  
    private val repository: NoteRepository  
) : ViewModel() {  
  
    val allNotes: Flow<List<Note>> = repository.getAllNotes()  
  
    fun insert(note: Note) = viewModelScope.launch {  
        repository.insert(note)  
    }  
  
    fun update(note: Note) = viewModelScope.launch {  
        repository.update(note)  
    }  
  
    fun addNote(note: Note) {  
        viewModelScope.launch {  
            repository.insert(note)  
        }  
    }  
  
    fun delete(noteId: Long) = viewModelScope.launch {  
        repository.delete(noteId)  
    }  
}

6. UI 界面

6.1 笔记列表界面

NoteListScreen.kt
package com.nemo.notes.ui

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.example.notes.model.Note
import com.example.notes.viewmodel.NoteViewModel

@Composable
fun NoteListScreen(navController: NavController, viewModel: NoteViewModel) {
    val notes by viewModel.getAllNotes().collectAsState(initial = emptyList())

    Column(modifier = Modifier.padding(16.dp)) {
        Text(text = "My Notes", style = MaterialTheme.typography.headlineMedium)
        LazyColumn {
            items(notes) { note ->
                Card(
                    onClick = { navController.navigate("noteEdit/${note.id}") },
                    modifier = Modifier.padding(8.dp)
                ) {
                    Column(modifier = Modifier.padding(16.dp)) {
                        Text(text = note.title, style = MaterialTheme.typography.titleMedium)
                        Text(text = note.content, style = MaterialTheme.typography.bodyMedium)
                    }
                }
            }
        }
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = { navController.navigate("noteEdit/${note.id}") },
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("Add New Note")
        }
    }
}

6.2 笔记编辑界面

NoteEditScreen.kt
package com.nemo.notes.ui  
  
import androidx.compose.foundation.layout.Column  
import androidx.compose.foundation.layout.Spacer  
import androidx.compose.foundation.layout.fillMaxWidth  
import androidx.compose.foundation.layout.height  
import androidx.compose.foundation.layout.padding  
import androidx.compose.material3.Button  
import androidx.compose.material3.ExperimentalMaterial3Api  
import androidx.compose.material3.Text  
import androidx.compose.material3.TextField  
import androidx.compose.runtime.Composable  
import androidx.compose.runtime.LaunchedEffect  
import androidx.compose.runtime.mutableStateOf  
import androidx.compose.runtime.remember  
import androidx.compose.ui.Modifier  
import androidx.compose.ui.unit.dp  
import androidx.navigation.NavController  
import com.nemo.notes.model.Note  
import com.nemo.notes.viewmodel.NoteViewModel  
  
@OptIn(ExperimentalMaterial3Api::class)  
@Composable  
fun NoteEditScreen(  
    navController: NavController,  
    viewModel: NoteViewModel,  
    noteId: Long?  
) {  
    val note = remember { mutableStateOf(Note(title = "", content = "")) }  
  
    if (noteId != null) {  
        LaunchedEffect(noteId) {  
            viewModel.allNotes.collect { notes ->  
                notes.find { it.id == noteId }?.let { note.value = it }  
            }        }    }  
  
    Column(modifier = Modifier.padding(16.dp)) {  
        TextField(  
            value = note.value.title,  
            onValueChange = { note.value = note.value.copy(title = it) },  
            label = { Text("Title") },  
            modifier = Modifier.fillMaxWidth()  
        )  
        Spacer(modifier = Modifier.height(16.dp))  
        TextField(  
            value = note.value.content,  
            onValueChange = { note.value = note.value.copy(content = it) },  
            label = { Text("Content") },  
            modifier = Modifier.fillMaxWidth().height(200.dp)  
        )  
        Spacer(modifier = Modifier.height(16.dp))  
        Button(  
            onClick = {  
                if (noteId == null) {  
                    viewModel.insert(note.value)  
                } else {  
                    viewModel.update(note.value.copy(id = noteId))  
                }  
                navController.popBackStack()  
            },  
            modifier = Modifier.fillMaxWidth()  
        ) {  
            Text(if (noteId == null) "Create Note" else "Update Note")  
        }  
    }}

7. 导航

更新导航以支持笔记列表和编辑界面之间的切换。

MainActivity.kt

package com.nemo.notes.ui  
  
import android.os.Bundle  
import androidx.activity.ComponentActivity  
import androidx.activity.compose.setContent  
import androidx.compose.foundation.layout.fillMaxSize  
import androidx.compose.material3.MaterialTheme  
import androidx.compose.material3.Surface  
import androidx.compose.ui.Modifier  
import androidx.hilt.navigation.compose.hiltViewModel  
import androidx.navigation.compose.NavHost  
import androidx.navigation.compose.composable  
import androidx.navigation.compose.rememberNavController  
import com.nemo.notes.ui.theme.NotesAppTheme  
import com.nemo.notes.viewmodel.NoteViewModel  
import dagger.hilt.android.AndroidEntryPoint  
  
@AndroidEntryPoint  
class MainActivity : ComponentActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContent {  
            NotesAppTheme {  
                Surface(  
                    modifier = Modifier.fillMaxSize(),  
                    color = MaterialTheme.colorScheme.background  
                ) {  
                    val navController = rememberNavController()  
                    val viewModel: NoteViewModel = hiltViewModel()  
  
                    NavHost(navController = navController, startDestination = "noteList") {  
                        composable("noteList") {  
                            NoteListScreen(navController, viewModel)  
                        }  
                        composable("noteEdit/{noteId}") { backStackEntry ->  
                            val noteId = backStackEntry.arguments?.getString("noteId")?.toLongOrNull()  
                            NoteEditScreen(navController, viewModel, noteId)  
                        }  
                    }                
                }            
            }        
        }    
    }  
}


8. 运行项目

  1. 确保 Android 项目配置正确。
  2. 运行项目并测试笔记的创建和编辑功能。

Note2.png

Note.png

项目代码参考地址:github.com/wxxzy/Notes…

通过以上步骤,您已经成功实现了笔记的创建和编辑功能。接下来,您可以继续实现搜索、标签管 理、云同步等功能。如果有任何问题或需要进一步的帮助,请随时告诉我!