This is the 26th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

preface

In the previous article, we made a preliminary use of Room in Jetpack, but each time we manipulated the data, we needed an additional query. In this article, there will be an integration of Room and what we learned earlier.

No more words, just get started!

1, Room + ViewModel + LiveData

As is shown in

This is the official recommended architecture that we use,

  • ViewModel and Repository interact
  • Repository interacts with the corresponding database and network requests

On the basis of the previous article, the corresponding Room database related for the time being.

Since databases are associated with Repository, and Repository is associated with ViewModel, what does Repository look like?

1.1 StudentRepository

class StudentRepository {

    var studentDao: StudentDao? = null

    constructor(context: Context) {
        valdatabase = MyDatabase.getInstance(context) studentDao = database!! .getStudentDao() }fun insertStudent(vararg student: Student?).{ studentDao!! .insertStudent(*student) }fun deleteStudent(vararg student: Student){ studentDao!! .deleteStudent(*student) }fun updateStudent(vararg student: Student){ studentDao!! .updateStudent(*student) }fun deleteAllStudents(a){ studentDao!! .deleteAllStudents() }fun getAllStudentsLive(a): LiveData<List<Student>> {
        returnstudentDao!! .getAllStudentsLive() }fun queryAll(a): List<Student>? {
        returnstudentDao!! .queryAll() } }Copy the code

As you can see, all previous operations on the Dao are moved to Repository, which is also simpler.

But here’s the thing:getAllStudentsLive()The method returnsLiveData<List<Student>>, LiveData collection!

Now what about the ViewModel?

1.2 StudentViewModel

class StudentViewModel(application: Application) : AndroidViewModel(application) {

	// Initialize the corresponding Repository object
    private val repository by lazy { StudentRepository(application) }
       
	// Define the corresponding set of LiveData
    private var liveDataStudent: LiveData<List<Student>>? = null
	
    init {
        liveDataStudent = repository.getAllStudentsLive()
        Log.d("StudentViewModel"."init liveDataStudent ${liveDataStudent? .value? .size}")}private fun insertStudent(vararg student: Student) {
        viewModelScope.launch(Dispatchers.Default) {
            repository.insertStudent(*student)
        }
    }

    private fun deleteStudent(vararg student: Student) {
        viewModelScope.launch(Dispatchers.Default) {
            repository.deleteStudent(*student)
        }
    }

    private fun updateStudent(vararg student: Student) {
        viewModelScope.launch(Dispatchers.Default) {
            repository.updateStudent(*student)
        }
    }

    private fun deleteAllStudents(a) {
        viewModelScope.launch(Dispatchers.Default) {
            repository.deleteAllStudents()
        }
    }

    fun getAllStudentsLive(a): LiveData<List<Student>>? {
        viewModelScope.launch(Dispatchers.Default) {
            liveDataStudent = repository.getAllStudentsLive()
        }
        return liveDataStudent
    }
    
    // Here are the methods called by the DataBinding layout -------------------
    fun mInsert(a) {
        val s1 = Student("hqk".26)
        val s2 = Student("Rose".18)
        insertStudent(s1, s2)
    }
    fun mClear(a) {
        deleteAllStudents()
    }
    fun mDelete(a) {
        var s1 = Student(3)
        deleteStudent(s1)
    }
    fun mUpdate(a) {
        val s1 = Student(2."Jason".21)
        updateStudent(s1)
    }
}
Copy the code

We can also see that the ViewModel is associated with the Repository and the corresponding layout is bound to the ViewModel via DataBinding!

Note that the viewModelScope is used inside the ViewModel, so you need to add the following dependencies

    implementation "Androidx. Activity: activity - KTX: 1.2.0"
    implementation "Androidx. Fragments: fragments - KTX: 1.3.0"
Copy the code

Here’s how to use it:

1.3 mainActivity

class MainActivity : AppCompatActivity() {

    private var adapter: StudentRecyclerViewAdapter? = null
    private var listStudent: ArrayList<Student> = ArrayList()
    
    private var viewModel: StudentViewModel? = null

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_main)
        val binding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)


        viewModel = ViewModelProvider(this)[StudentViewModel::class.java]

        binding.studentViewModel = viewModel
        binding.lifecycleOwner = this

// val recycleView = findViewById
      
       (R.id.recycleView)
      
        binding.recycleView.layoutManager = LinearLayoutManager(this)
        adapter = StudentRecyclerViewAdapter(listStudent)
        binding.recycleView.adapter = adapter

	// Listen on the corresponding LiveData, when the database data changes, will be active callback notification!viewModel!! .getAllStudentsLive()!! .observe(this, androidx.lifecycle.Observer {
            Log.d("StudentViewModel"."main  it ${it.size}") adapter!! .students = it adapter!! .notifyDataSetChanged() }) } }Copy the code

Get the LiveData via ActivityMainBinding and add the logic. Use getAllStudentsLive to get the LiveData and listen on the LiveData set via Observe.

The DataBinding for Item is an ItemBinding. The DataBinding for Item is an ItemBinding.

Finally, let’s see how it works

Here we see that the data is automatically loaded with each operation, without manual query!

conclusion

Well, that’s the end of this optimization! In the next installment, we’ll cover Room upgrades and pre-fills!