iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 30
0
自我挑戰組

Android App 初學者從零開始用Kotlin寫APP系列 第 30

<Day30>動手做 Demo App(下)

  • 分享至 

  • xImage
  •  

使用 room 來建立Database

abstract class AppDatabase: RoomDatabase() {
    companion object {
        private const val DATABASE_NAME = "_db"

        // For Singleton instantiation
        @Volatile private var instance: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }

        private fun buildDatabase(context: Context): AppDatabase {
            return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME).build()
        }
    }

      abstract fun peopleDao(): PeopleDao
}

//建立table 所需要的欄位

@Entity(
    tableName = Person.TABLE_NAME
)
data class Person (
    @ColumnInfo(name = COLUMN_Name) var title: String,
    @ColumnInfo(name = COLUMN_CREATED_DATE) var createdDate: Date
) {
    companion object {
        const val TABLE_NAME = "person"
        const val COLUMN_ID = "id"
        const val COLUMN_NAME = "name"
        const val COLUMN_CREATED_DATE = "created_date"
    }
    
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = COLUMN_ID) var id: Int = 0
}

// 實作 新增與查詢

class PersonRepository(
    private val database: AppDatabase
) {
    suspend fun insertPerson(person: Person) {
        database.peopleDao().insert(person)
    }

    suspend fun updatePerson(person: Person) {
        database.peopleDao().update(person)
    }

    fun getAll(): LiveData<List<Person>> {
        return database.peopleDao().findAll()
    }
}

ViewModel conncet repository Data


class PeopleViewModel(private val repository: PersonRepository) : ViewModel() {

    private val title = Person.Title("聯絡人清單")

    val todoLiveData: LiveData<List<Todo>> = MediatorLiveData<List<Todo>>().apply {
        val source = repository.getAll().map {
            it.map { person ->
                Person.Item(
                    person.id,
                    person.name,
                    person.done,
                    person.createdDate
                )
            }
        }
        addSource(source) {
            this.value = mutableListOf(title) + it
        }
        value = mutableListOf(title)
    }

    fun createNewTodo(name: String) {
        val person = Person(
            name = name,
            createdDate = Date()
        )
        viewModelScope.launch {
            repository.insertPerson(person)
        }
    }

    fun updateTodo(person: Person.Item) {
        val person = Person(
            name = person.name,
            createdDate = person.createdDate
        ).apply { id = person.id }

        viewModelScope.launch {
            repository.updatePerson(person)
        }
    }
}

從DB讀取資料,顯示清單頁 data放入recyclerView

class ListFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        ...........
        val peopleDb = AppDatabase.getInstance(requireActivity().applicationContext)
        val peopleRepo = PersonRepository(peopleDb)
        val viewModelFactory = AnyViewModelFactory {
            peopleViewModel(peopleRepo)
        }
        
        //  recyclerView  ListAdapter  Listener  data change
         val adapter = PersonAdapter().apply {
            onTodoChangeListener = object : OnTodoChangeListener {
                override fun onChange(person: Person.Item) {
                    peopleViewModel.updateTodo(person)
                }
            }
        }
        
        recyclerView.adapter = adapter
        recyclerView.layoutManager =
            LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
        recyclerView.addItemDecoration(
            DividerItemDecoration(
                requireContext(),
                LinearLayoutManager.VERTICAL
            )
        )
        
       val peopleViewModel = ViewModelProvider(requireActivity(), viewModelFactory).get(PeopleViewModel::class.java)
       
         peopleViewModel.personLiveData.observe(viewLifecycleOwner, Observer { todos: List<Todo> ->
            adapter.submitList(todos)
        })

}
}

新增頁面,點選新增按鈕


 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        .....
        val peopleDb = AppDatabase.getInstance(requireActivity().applicationContext)
        val peopleRepo = PersonRepository(peopleDb)
        val viewModelFactory = AnyViewModelFactory {
            peopleViewModel(peopleRepo)
        }
        
          val peopleViewModel = ViewModelProvider(requireActivity(), viewModelFactory).get(PeopleViewModel::class.java)
       
         ........
        buttonAdd.setOnClickListener {
            if (name.text.isNullOrEmpty()) {
                name.error = "尚未填寫新增聯絡人"
            } else {
                name.error = null
                val name = name.text.toString()
                peopleViewModel.createNewPerson(name)
                findNavController().popBackStack()
            }
        }
    }

資料存在app db 裡, app 關掉再打開後資料仍存在,完成簡單新增聯絡人

https://ithelp.ithome.com.tw/upload/images/20201013/20130598Jk3dTuZUXC.png

reference:https://www.notion.so/Navigation-component-9-9-Andy-a1245a1b31c5453fbf1b28f887ec0d73
reference:https://enginebai.com/2019/04/03/android-database-room/
reference:https://givemepass.blogspot.com/2015/12/recyclerview.html
reference:https://medium.com/evan-android-note/android-fragment-%E5%85%B1%E7%94%A8-viewmodel-19a6d9161421


上一篇
<Day29>動手做 Demo App(上)
系列文
Android App 初學者從零開始用Kotlin寫APP30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言