Giới Thiệu Về Mô Hình MVVM Trong Phát Triển Ứng Dụng Android
Trong phát triển ứng dụng Android, mô hình MVVM (Model-View-ViewModel) là một trong những kiến trúc phổ biến giúp tách biệt rõ ràng giữa giao diện người dùng và logic xử lý dữ liệu. Dưới đây là phân tích chi tiết về từng thành phần trong mô hình MVVM:
Các Thành Phần Chính
Model
Model là nơi lưu trữ và quản lý dữ liệu của ứng dụng. Nó có thể lấy dữ liệu từ nhiều nguồn khác nhau nhưng không thực hiện bất kỳ giao tiếp trực tiếp nào với View.
View
View đại diện cho giao diện người dùng của ứng dụng. Đây là nơi hiển thị dữ liệu nhưng không chứa logic xử lý. View quan sát ViewModel để cập nhật thông tin khi cần thiết.
ViewModel
ViewModel giữ vai trò trung gian, quản lý dữ liệu và tương tác giữa Model và View. Nó cho phép View quan sát các thay đổi trong dữ liệu mà không cần quan tâm đến nơi dữ liệu được tạo ra.
Sự Khác Biệt Giữa MVVM Và MVP
Mô hình MVP (Model-Presenter-View) cũng giống như MVVM ở điểm tổ chức mã nguồn, nhưng có một số điểm khác biệt quan trọng. Trong khi Presenter trong MVP giữ tham chiếu đến View, ViewModel trong MVVM không giữ tham chiếu đó. Điều này giúp ViewModel độc lập hơn và giảm thiểu nguy cơ rò rỉ bộ nhớ.
Cài Đặt MVVM Trong Một Dự Án Android
Dưới đây là hướng dẫn từng bước để cài đặt MVVM trong ứng dụng Android:
Thêm Thư Viện Cần Thiết
Đầu tiên, thêm các thư viện dưới đây vào build.gradle
của dự án:
gradle
implementation 'com.amitshekhar.android:rx2-android-networking:1.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.2.18'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
Định Nghĩa Model
Tạo một lớp dữ liệu cho user như sau:
kotlin
import com.google.gson.annotations.SerializedName
data class User(
@SerializedName("id") val id: Int = 0,
@SerializedName("name") val name: String = "",
@SerializedName("email") val email: String = "",
@SerializedName("avatar") val avatar: String = ""
)
Tạo ViewModel
kotlin
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.demomvvm.data.model.User
import com.example.demomvvm.data.repository.MainRepository
import com.mindorks.framework.mvvm.utils.Resource
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
class MainViewModel(private val mainRepository: MainRepository) : ViewModel() {
private val users = MutableLiveData<Resource<List<User>>>()
private val compositeDisposable = CompositeDisposable()
init {
fetchUsers()
}
private fun fetchUsers() {
users.postValue(Resource.loading(null))
compositeDisposable.add(
mainRepository.getUsers()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ userList ->
users.postValue(Resource.success(userList))
}, { throwable ->
users.postValue(Resource.error("Something Went Wrong", null))
})
)
}
override fun onCleared() {
super.onCleared()
compositeDisposable.dispose()
}
fun getUsers(): LiveData<Resource<List<User>>> {
return users
}
}
Tạo View (Activity)
kotlin
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.demomvvm.R
import com.example.demomvvm.data.api.ApiHelper
import com.example.demomvvm.data.api.ApiServiceImpl
import com.example.demomvvm.data.model.User
import com.example.demomvvm.base.ViewModelFactory
import com.example.demomvvm.adapter.MainAdapter
import com.example.demomvvm.viewmodel.MainViewModel
import com.mindorks.framework.mvvm.utils.Status
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private lateinit var mainViewModel: MainViewModel
private lateinit var adapter: MainAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupUI()
setupViewModel()
setupObserver()
}
private fun setupUI() {
recyclerView.layoutManager = LinearLayoutManager(this)
adapter = MainAdapter(arrayListOf())
recyclerView.addItemDecoration(
DividerItemDecoration(
recyclerView.context,
(recyclerView.layoutManager as LinearLayoutManager).orientation
)
)
recyclerView.adapter = adapter
}
private fun setupObserver() {
mainViewModel.getUsers().observe(this, Observer {
when (it.status) {
Status.SUCCESS -> {
progressBar.visibility = View.GONE
it.data?.let { users -> renderList(users) }
recyclerView.visibility = View.VISIBLE
}
Status.LOADING -> {
progressBar.visibility = View.VISIBLE
recyclerView.visibility = View.GONE
}
Status.ERROR -> {
progressBar.visibility = View.GONE
Toast.makeText(this, it.message, Toast.LENGTH_LONG).show()
}
}
})
}
private fun renderList(users: List<User>) {
adapter.addData(users)
adapter.notifyDataSetChanged()
}
private fun setupViewModel() {
mainViewModel = ViewModelProviders.of(
this,
ViewModelFactory(ApiHelper(ApiServiceImpl()))
).get(MainViewModel::class.java)
}
}
XML Layout
Cuối cùng, đừng quên thêm quyền truy cập Internet vào file AndroidManifest.xml
:
xml
<uses-permission android:name="android.permission.INTERNET"/>
Kết Luận
Như vậy, bài viết đã cung cấp cái nhìn tổng quan về mô hình MVVM và cách triển khai nó trong ứng dụng Android. Trong các bài tiếp theo, chúng tôi sẽ hướng dẫn các bạn xây dựng ứng dụng xem thời tiết với coroutines và flow, điều này sẽ mang lại nhiều kiến thức bổ ích trong lập trình đa luồng trên Android. Hãy theo dõi nhé!
Tham Khảo
JournalDev - Hướng Dẫn MVVM trên Android
GitHub Code Demo
source: viblo