여러 화면이 있더라도 비슷한 데이터를 가지고 있는 애라면 같은 ViewModel을 공유할 수 있다.
(MVP 처럼 1:1이 아니기 때문)
ViewModel이 직접적으로 요소를 그리라고 View에게 요청하지 않기 때문.
간단한 프로젝트에 사용하기에는 과하다.
비교적 구현 구조가 복잡하고 설계가 수비지 않다.
이번 예제의 프로젝트 구조입니다.
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.drawerlayout:drawerlayout:1.1.1'
implementation 'com.orhanobut:logger:2.2.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.example.project1.viewmodel.ViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="오늘의 간식 당번"
android:textSize="40sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.25" />
<TextView
android:id="@+id/user_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.winner}"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.4" />
<Button
android:id="@+id/ok_btnview"
android:layout_width="114dp"
android:layout_height="68dp"
android:text="돌리기"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
package com.example.project1.view;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import android.view.View;
import com.example.project1.R;
import com.example.project1.databinding.ActivityMainBinding;
import com.example.project1.model.Database;
import com.example.project1.viewmodel.ViewModel;
import com.orhanobut.logger.Logger;
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding; //상속 ViewDataBinding
ViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
Logger.d("Main_onCreate() 실행");
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewModel = new ViewModel(Database.getInstance());
binding.setViewModel(viewModel);
binding.okBtnview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Logger.d("버튼 클릭");
viewModel.getUser();
}
});
}
}
package com.example.project1.viewmodel;
import androidx.databinding.BaseObservable;
import com.example.project1.model.Database;
import com.example.project1.model.Person;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
import java.util.List;
public class ViewModel extends BaseObservable {
private Database database;
private List<Person> items = new ArrayList<>();
private String winner;
public ViewModel(Database database){
Logger.d("ViewModel 생성자 실행 | DB(Model) 참조");
this.database = database;
this.database.setOnDatabaseListener(new Database.DatabaseListener() {
@Override
public void onChanged() {
Logger.d("리스너 실행");
winner = null;
winner = database.getWinner();
notifyChange();
}
});
}
public void getUser() {
Logger.d("db에게 user(winner)를 달라고 요청");
database.getUser();
}
public String getWinner() {
Logger.d("Winner 변환 (%s)", winner);
return winner;
}
}
package com.example.project1.model;
import com.orhanobut.logger.Logger;
import java.util.ArrayList;
public class Database {
private static Database instance;
private ArrayList<Person> personList = new ArrayList<>();
private String winner;
private DatabaseListener databaseListener;
private Database(){
Logger.d("Model인 Database 생성");
personList.add(new Person(0, "최00"));
personList.add(new Person(1, "김00"));
personList.add(new Person(2, "고00"));
personList.add(new Person(3, "문00"));
personList.add(new Person(4, "윤00"));
}
public static Database getInstance() {
Logger.d("Model에 접근 할 수 있도록 DB 인스턴스 값 요청");
if(instance == null) {
instance = new Database();
}
return instance;
}
public void getUser() {
Logger.d("당첨자 획득");
winner = personList.get((int)(Math.random()*5)).getName();
notifyChange();
}
private void notifyChange() {
if(databaseListener != null) {
Logger.d("Model | Data 변경 되어 notify 하라고 알림");
databaseListener.onChanged();
}
}
public void setOnDatabaseListener(DatabaseListener databaseListener) {
Logger.d("DatabaseListener 구현 객체 참조 변수 세팅 (arg1 : %s)", databaseListener.getClass().getSimpleName());
this.databaseListener = databaseListener;
}
public String getWinner() {
return winner;
}
public interface DatabaseListener {
void onChanged();
}
}
package com.example.project1.model;
public class Person {
private long id;
private String name;
public Person(long id, String name) {
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}