-
[Android] MVVM 패턴 적용 - ACC 예제Android 2022. 10. 11. 23:01
- DAO ? DB의 data에 접근하기 위한 객체
< viewmodel 적용 이전>
Todo.class (Room)
: id, title이 정의된 데이터
package org.techtown.myapplication; import androidx.room.Entity; import androidx.room.PrimaryKey; @Entity //룸에서 사용할수 있는 entity public class Todo { @PrimaryKey(autoGenerate = true) private int id; private String title; public Todo(String title) { this.title = title; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @Override public String toString() { return "Todo{" + "id=" + id + ", title='" + title + '\'' + '}'; } }
TodoDao.interface
: Todo에 접근하기 위한 데이터 접근 객체
: 조회, 삽입 , 삭제등의 메서드를 정의함 getAll() -> Todo의 모든 값 조회
: LiveData로 지정함
package org.techtown.myapplication; import androidx.lifecycle.LiveData; import androidx.room.Dao; import androidx.room.Delete; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Update; import java.util.List; //Todo에 접근하기 위한 Data access object @Dao public interface TodoDao { //Todo에 어떤 동작 제공할지 정의 @Query("SELECT * FROM Todo") LiveData<List<Todo>> getAll(); @Insert void insert(Todo todo); @Update void update(Todo todo); @Delete void delete(Todo todo); }
AppDatabase.class
: RoomDB 상속후 tododao 구체화
package org.techtown.myapplication; import androidx.room.Database; import androidx.room.RoomDatabase; @Database(entities = {Todo.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract TodoDao todoDao(); // todo조작 }
MainActivity.class
: observe를 통해 값이 바뀌면 갱신함
package org.techtown.myapplication; import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.room.Room; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.TextView; import java.util.List; public class MainActivity extends AppCompatActivity { private EditText mTodoEditText; private TextView mResultTextview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTodoEditText = findViewById(R.id.todoEdit); mResultTextview = findViewById(R.id.result_text); final AppDatabase db = Room.databaseBuilder(this,AppDatabase.class,"todo-db") .build(); //UI 갱신 db.todoDao().getAll().observe(this,todos -> { mResultTextview.setText(todos.toString()); }); // 버튼 클릭시 db에 insert findViewById(R.id.addBtn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { new InsertAsyncTask(db.todoDao()) .execute(new Todo(mTodoEditText.getText().toString())); } }); } private static class InsertAsyncTask extends AsyncTask<Todo, Void, Void> { private TodoDao mTodoDao; public InsertAsyncTask(TodoDao todoDao){ this.mTodoDao = todoDao; } //Room을 비동기로 사용 @Override protected Void doInBackground(Todo... todos) { mTodoDao.insert(todos[0]); return null; } } }
< ViewModel 적용 후 >
MainActivity.class
: 원래는 db 선언, 버튼 클릭시 insert가 MainActivity에 선언되어 있었지만,
UI와 기능을 분리하기 위해
MainActivity에서 viewprovider를 선언하고 따로 선언된 MainViewModel의 메서드를 불러옴
observe()로 변하는 ui를 관찰함
package org.techtown.myapplication; import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.room.Room; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.TextView; import java.util.List; public class MainActivity extends AppCompatActivity { private EditText mTodoEditText; private TextView mResultTextview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTodoEditText = findViewById(R.id.todoEdit); mResultTextview = findViewById(R.id.result_text); //ViewModelPrivider로 ViewModel 사용 가능 MainViewModel viewModel = new ViewModelProvider(this) .get(MainViewModel.class); // getall시 결과가 변경될때마다 todo로 들어옴 // 관찰하다가 ui 갱신 viewModel.getAll().observe(this, new Observer<List<Todo>>() { @Override public void onChanged(List<Todo> todos) { mResultTextview.setText(todos.toString()); } }); // 버튼 클릭시 db에 insert // 값이 안 바뀔수도 있는 경우엔 ui갱신을 하지 않아도 됨 findViewById(R.id.addBtn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { viewModel.insert(new Todo(mTodoEditText.getText().toString())); } }); } // 원래 아래 코드를 onClick()에 썼다면 aac패턴에서는 onChanged안에 넣기 // mResultTextview.setText(db.todoDao().getAll().toString()); }
MainViewModel.class
: 여기서 db선언, LiveData 선언, insert() 메서드 선언을 따로 해줌
getAll() 을 호출하면 tododao의 getall을 호출해줌
package org.techtown.myapplication; import android.app.Application; import android.os.AsyncTask; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModel; import androidx.room.Room; import java.util.List; public class MainViewModel extends AndroidViewModel { private AppDatabase db; public MainViewModel(@NonNull Application application) { super(application); db = Room.databaseBuilder(application, AppDatabase.class,"todo-db") .build(); } public LiveData<List<Todo>> getAll() { return db.todoDao().getAll(); } public void insert(Todo todo) { new InsertAsyncTask(db.todoDao()) .execute(todo); } private static class InsertAsyncTask extends AsyncTask<Todo, Void, Void> { private TodoDao mTodoDao; public InsertAsyncTask(TodoDao todoDao){ this.mTodoDao = todoDao; } @Override protected Void doInBackground(Todo... todos) { mTodoDao.insert(todos[0]); return null; } } // // private AppDatabase db; // // public MainViewModel(@NonNull Application application) { // super(application); // // db 객체 생성 // db = Room.databaseBuilder(application, AppDatabase.class,"todo-db") // .build(); // // //.allowMainThreadQueries() //백그라운드 말고 메인 스레드에서 db사용 // // public LiveData<List<Todo>> getAll() { // return db.todoDao().getAll(); // } // public void insert(Todo todo) { // // } // } }
-> MainActivity에는 ui관련 코드만 남게 됨
<DataBinding 적용후>
'Android' 카테고리의 다른 글
[Android] DataBinding (3) 2022.10.15 [Android] MVVM 패턴 적용 - ACC (0) 2022.10.10