最近 ChatGPT 很紅,我剛剛請它寫給我一個使用 ViewModel, Room 的 jetpack compose 小範例,它實在是太強了。以下筆記一下它寫的內容。
Todo App with Jetpack.
以下是一個使用 ViewModel、Room 和 Jetpack Compose 構建簡單 Todo App 的範例:
//build.gradle(Module:app)
plugins {
//...
id 'kotlin-kapt'
}
dependencies {
//...
//room
implementation "androidx.room:room-runtime:2.5.0"
implementation "androidx.room:room-ktx:2.5.0"
annotationProcessor "androidx.room:room-compiler:2.5.0"
kapt "androidx.room:room-compiler:2.5.0"
//livedata
implementation "androidx.compose.runtime:runtime-livedata:1.3.3"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1"
}
首先,定義一個數據模型:
@Entity(tableName = "todos")
data class Todo(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
// 或是把上兩行改成如下
// @PrimaryKey
// val id: String = UUID.randomUUID().toString(),
val title: String,
val description: String
)
為了操作 Todo 對象,我們需要創建一個 Dao:
@Dao
interface TodoDao {
@Query("SELECT * FROM todos")
fun getTodos(): Flow<List<Todo>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addOrUpdate(todo: Todo)
@Delete
suspend fun delete(todo: Todo)
}
接下來,我們創建一個 Room 數據庫:
@Database(entities = [Todo::class], version = 1)
abstract class TodoDatabase : RoomDatabase() {
abstract fun todoDao(): TodoDao
companion object {
@Volatile
private var INSTANCE: TodoDatabase? = null
fun getDatabase(context: Context): TodoDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
TodoDatabase::class.java,
"todo_database"
).build()
INSTANCE = instance
instance
}
}
}
}
現在,我們創建一個 ViewModel 來管理數據庫操作:
class TodoViewModel(application: Application) : AndroidViewModel(application) {
private val todoDao = TodoDatabase.getDatabase(application).todoDao()
val todos: LiveData<List<Todo>> = todoDao.getTodos().asLiveData()
fun addOrUpdate(todo: Todo) {
viewModelScope.launch {
todoDao.addOrUpdate(todo)
}
}
fun delete(todo: Todo) {
viewModelScope.launch {
todoDao.delete(todo)
}
}
}
最後,我們使用 Jetpack Compose 創建 UI:
@Composable
fun TodoListScreen(todoViewModel: TodoViewModel) {
val todos by todoViewModel.todos.observeAsState(emptyList())
Column {
TodoList(todos = todos)
TodoInput(onAddTodo = { title, description ->
todoViewModel.addOrUpdate(Todo(title = title, description = description))
})
}
}
@Composable
fun TodoList(todos: List<Todo>) {
LazyColumn {
items(todos) { todo ->
TodoItem(todo)
}
}
}
@Composable
fun TodoItem(todo: Todo) {
Card(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(text = todo.title, style = MaterialTheme.typography.h6)
Text(text = todo.description, style = MaterialTheme.typography.body1)
}
}
}
@Composable
fun TodoInput(onAddTodo: (title: String, description: String) -> Unit) {
var title by rememberSaveable { mutableStateOf("") }
var description by rememberSaveable { mutableStateOf("") }
Column {
OutlinedTextField(
value = title,
onValueChange = { title = it },
label = { Text(text = "Title") },
modifier = Modifier
.padding(16)
.fillMaxWidth()
)
OutlinedTextField(
value = description,
onValueChange = { description = it },
label = { Text(text = "Description") },
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
)
Button(
onClick = { onAddTodo.invoke(title, description) },
modifier = Modifier
.padding(16.dp)
.align(Alignment.End)
) {
Text(text = "Add")
}
}
最後,將 TodoListScreen 加入到 MainActivity:
class MainActivity : ComponentActivity() {
private val todoViewModel: TodoViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TodoListScreen(todoViewModel)
}
}
}
這樣就完成了一個使用 ViewModel、Room 和 Jetpack Compose 構建的簡單 Todo App,當用戶添加或刪除代辦事項時,它將自動更新。
發佈留言