kotlin으로 안드로이드 Room, LiveData를 viewmodel에서 구현하기

Kyung yup Lee·2020년 12월 21일
1

안드로이드

목록 보기
7/8

뷰모델에 대한 설명부터 정리해야 될 것 같다.

뷰모델은 기본적으로 UI를 관리하는 부분에서 데이터를 다루는 것을 막고 이 둘을 분리시키기 위해 고안되었다.

안드로이드를 처음 입문했던 사람이라면 activity 클래스 onCreate 메소드 안에 모든 코드를 다 때려박고 실행시킨 경험이 있을 것이다.

activity는 생명주기가 있다. 특히 앱 같은 경우 다양한 요인(팝업, 다른 앱의 요청, 가로 변경 등등등) 에 의해 앱이 밑으로 내려가거나 백그라운드로 옮겨지게 된다.

이럴 때마다 activity 는 onPause, onStop 메소드가 실행되면서 생명주기가 변경된다.

그렇게 되면 다시 앱을 onResume() 했을 때 onCreate에 들어있던 데이터들이 다 날라가버리게 된다.

물론 데이터가 단순한 경우에는 onSaveInstanceState() 메소드를 사용해 자동으로 bundle에서 데이터를 복원해준다.

하지만 데이터가 커지고 복잡해지면 이 방법을 사용할 수가 없다. 때문에 UI 컨트롤러와 데이터 관리 부분을 분리해야 할 필요성이 생긴 것이다.

추가적으로 객체지향적으로도 단일책임원칙을 따르지 않게 되기 때문에 클래스는 하나의 역할만 하는 것이 설계적으로도 바르다고 생각한다.

해당 코드는 '20.12.21.에 작성되어 안드로이드 developer에 게시된 현재의 최신 코드를 따랐고 시간이 지나서 deprecated 될 수 있습니다.

mainActivity 코드이다.
뷰모델을 호출하는 것 외엔 특별한 점이 없다. 안드로이드 developer을 참고하면 된다.

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val textView : TextView = findViewById(R.id.result_text)
        val button : Button = findViewById(R.id.button)
        val editText : EditText = findViewById(R.id.todo_edit)
	// 뷰 바인딩을 사용해도 됨
    
        val mainViewModel : MainViewModel by viewModels()
	// 뷰모델 호출
        mainViewModel.getAll().observe(this, Observer {users->
            textView.text = users.toString()
        } )
	// 뷰모델에서 데이터를 받아오고 해당 데이터를 observe 해서 변경이 생기면 update
        button.setOnClickListener{
            mainViewModel.insert(User(editText.text.toString()))
            // 입력한 값을 뷰모델로 넘겨서 저장
        }
    }    

메인 뷰모델 클래스

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

    private val db = Room.databaseBuilder(application,AppDatabase::class.java, "todo").allowMainThreadQueries().build()

    fun getAll(): LiveData<List<User>> {
        return db.userDAO().getAll()
    }

    fun insert(user: User) {
        db.userDAO().insertAll(user)
    }

}

반드시 AndroidViewModel(application)을 상속받아야 한다.

android developer의 예시에는 ViewModel 을 상속하는 부분만 나와있어서 헤맸다.

viewModel 클래스는 본인이 호출된 activity의 context를 받아 사용하게 된다.

하지만 Room 모듈과 LiveData는 앱 전체에서 사용하기 때문에 application context를 받아 사용해야 한다.

이를 위해서는 AndroidViewModel 을 상속받아야 하고 application을 생성자로 초기화 해주어야 한다.

그리고 현재 내가 만들고있는 뷰 모델에서도 그대로 초기화해주어서 db를 생성하는 context로 넘겨주어야 한다.

AppDatabase.class

@Database(entities = arrayOf(User::class), version = 1)
abstract class AppDatabase : RoomDatabase(){

    abstract fun userDAO() : UserDAO
}

User.class

@Entity
data class User(

    @ColumnInfo(name = "first_name")
    val firstName: String?

    ) {
    @PrimaryKey(autoGenerate = true)
    var userId: Int = 0
}

UserDAO.interface

@Dao
interface UserDAO {
    @Query("SELECT * FROM user")
    fun getAll(): LiveData<List<User>>

    @Insert
    fun insertAll (vararg users: User)

    @Delete
    fun delete(user: User)
}

그 외에는 안드로이드 개발자 문서에 뷰모델을 적용시키지 않은 예시와 크게 다르지 않다.

profile
성장하는 개발자

0개의 댓글