1. MVVM Pattern 이란?
(1) 예시1
MVVM 패턴은 복잡한 앱을 만들기 위해 고안된 방법으로 여러가지 데이터에 대한 대응은 View와 ViewModel은 그대로 있되 Model만 여러가지를 만들어 대응한다. 즉 뷰모델은 그대로 있으며 Model(데이터 형식)만 변경한다.
- Model 모델 : 데이터 형식을 지정해주는 공간
- View 뷰 : 유저의 Action을 받아서 처리하는 곳으로 초기 데이터를 뷰모델에 전달해준다.
- ViewModel 뷰모델 : 데이터를 저장하는 공간으로 엑티비티가 종료되기 전까지 유지한다.
(2) 예시2
- 사용자 Action이 View를 통해 들어온다.
- View는 Action 에 맞는 data를 ViewModel에 요청한다.
- ViewModel은 Model에 데이터를 요청 하고 observable field로 매핑하여 외부로 노출한다.
- View는 ViewModel을 구독해서 자신을 변경한다.
MVC와 차이점은 Activity를 View로서 사용할 수 있고 ViewModel이 Controller와 같은 역할을 한다는것이다. 그리고 MVVM의 ViewMoedel의 핵심 키워드는 옵저버이다. 옵저버가 뷰모델에서 데이터변경을 감지한뒤 엑티비티로 가져와 View를 업데이트 할 수 있도록 도와준다. 즉 엑티비티 -> 뷰모델의 옵저버가 데이터 변경 감지 -> 뷰변경
2. CODE
(1) Model
데이터 형식을 지정하는 공간으로 용도에 따라 분류하여 지정한다.
// User 모델
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
// UserList 모델
public class UserList {
private List<User> userList;
public UserList(List<User> userList) {
this.userList = userList;
}
public List<User> getUserList() {
return userList;
}
}
(2) ViewModel
데이터를 저장하는 공간으로 기본적으로 엑티비티가 종료되기 전, Fragment가 분리되기 전까지 데이터를 유지한다.
public class UserListViewModel extends ViewModel {
private MutableLiveData<List<User>> userList;
public UserListViewModel() {
userList = new MutableLiveData<>();
}
public LiveData<List<User>> getUserList() {
return userList;
}
public void setUserList(List<User> list) {
userList.setValue(list);
}
}
(3) View와 연결된 MainActivity
데이터 초기값 저장, 데이터 변경 감지, 유저의 액션을 받는 공간이다.
public class MainActivity extends AppCompatActivity {
private UserListViewModel userListViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView userListTextView = findViewById(R.id.userListTextView);
// 뷰모델 초기화
userListViewModel = new ViewModelProvider(this).get(UserListViewModel.class);
// 뷰모델에서 데이터 변경 감지
userListViewModel.getUserList().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(List<User> newUserList) {
// 사용자 목록을 텍스트뷰에 표시
StringBuilder userListText = new StringBuilder();
for (User user : newUserList) {
userListText.append(user.getName()).append(", ").append(user.getAge()).append(" years\n");
}
userListTextView.setText(userListText.toString());
}
});
// 사용자 목록 설정 (예: 어딘가에서 데이터를 받아온다고 가정)
List<User> sampleUserList = createSampleUserList();
userListViewModel.setUserList(sampleUserList);
}
private List<User> createSampleUserList() {
// 예시로 사용할 사용자 목록 생성
return List.of(
new User("John Doe", 25),
new User("Jane Smith", 30),
new User("Bob Johnson", 22)
);
}
}
3. CODE 2
또다른 예시 코드를 살펴보자
(1) Model
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
(2) ViewModel
import androidx.lifecycle.ViewModel;
import androidx.databinding.ObservableField;
public class MainViewModel extends ViewModel {
public final ObservableField<String> userName = new ObservableField<>();
public void setUser(User user) {
userName.set(user.getName());
}
}
(3) View
뷰에서 DataBinding으로 ViewModel에 직접적으로 데이터를 전달한다.
<!-- activity_main.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.viewmodeldemo.MainViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.userName}"
android:textSize="18sp"
android:padding="16dp"
android:id="@+id/textView" />
</LinearLayout>
</layout>
(4) Activity
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import com.example.viewmodeldemo.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private MainViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 데이터 바인딩 초기화
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
// ViewModel 초기화
viewModel = new ViewModelProvider(this).get(MainViewModel.class);
// 데이터 바인딩과 ViewModel 연결
binding.setViewModel(viewModel);
binding.setLifecycleOwner(this);
// 모델 업데이트
User user = new User("John Doe");
viewModel.setUser(user);
}
}
Reference
'CS > Basic' 카테고리의 다른 글
[CS Basic] HashMap (0) | 2024.01.04 |
---|---|
[CS Basic] MVC Pattern (1) | 2023.12.21 |
[CS Basic] Static 변수와 Static 메서드 (0) | 2023.10.26 |
[CS Basic] Multi Process와 Multi Thread, Thread Safe, Context Switching (0) | 2023.10.26 |
[CS Basic] Thread와 Process 그리고 Stack, Queue, List (0) | 2023.10.26 |