일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- springboot
- viewmodel
- Button
- cocoapod
- backgroundTint
- podinit
- PostgreSQL
- prolificinteractive/material-calendarview
- calendar
- editText
- Dialog
- addTextChangedListner
- RestAPI
- livedata
- DialogFragment
- 리눅스
- android
- Today
- Total
코코딩딩
[안드로이드] ViewModel , LiveData 본문
ViewModel은 화면회전과 같은 동작을 할 때 수명주기에 의해 activity가 처음부터 다시 시작해도 데이터를 유지할 수 있게 해준다. 그리고 UI와 비즈니스로직을 분리해 코드를 작성 할 수 있어 프로그램을 유지보수 하는데도 도움을 준다.
이는 MVVM 패턴과 연관이 있는데 깊게 알고 싶긴 하지만 당장 동작하는 코드를 보면서 안드로이드에 대한 기본 이해를 높이고자 코드 중심으로 살펴보려고 한다.
https://www.youtube.com/watch?v=Y-uPcwBEEV4 영상을 참고해서 예제를 제작하였다.
1. gradle dependencies 추가
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
android 개발자 문서에 있는 implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1'와 같은 것들도 있지만 참고한 코드가 위의 종속성을 사용하고 있어 일단 이것을 쓸 것이다.
2. ViewModel.class 만들기
public class MainActivityViewModel extends ViewModel {
public MutableLiveData<Integer> counter = new MutableLiveData<>();
public MainActivityViewModel(){
counter.setValue(0);
}
public void increase(){
counter.setValue(counter.getValue() + 1);
}
public void decrease(){
counter.setValue(counter.getValue() - 1);
}
}
ViewModel을 만드는 방법은 간단하다. 어떤 클래스의 ViewModel인지 구분할 수 있게 이름을 정해주고 ViewModel을 상속하면 된다. 위의 코드는 Livedata인 counter를 선언해주고 counter 값을 1씩 증감 시키는 메서드를 만들어주었다.
.setValue를 이용해 livedata의 값을 초기화 해 준다.
3. MainActivity
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private MainActivityViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.setLifecycleOwner(this);
binding.setViewModel(viewModel);
// 이 아래는 한 프로젝트에 여러개를 추가하기 위해 넣은 것으로 예제와 상관없다.
binding.btnMove.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(),VmShareActivity.class);
startActivity(intent);
}
});
}
}
이전에 했던 databinding이 적용되어 있는 상태이고 MainActivityViewModel viewModel 을 선언해주고
viewModel을 new로 생성해준다. 영상에서는 viewModelProviders 를 사용하는데 이는 deprecated 되었기 때문에
위에적힌 방법을 사용해준다.
// 이런 코드는 ViewModel과 databinding을 이용해 생략할 수 있다.
binding.btnPlus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
viewModel.increase();
}
});
나머지 코드들을 보면 위와 같은 click 이벤트에 대한 내용이 없는 것을 알 수 있는데 지금부터 databinding을 이용해
viewmodel을 조금 더 깔끔하게 사용하는 방법을 사용하려고 한다.
3. viewmodel + databinding ( MainActivity.xml )
<?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.counterre.MainActivityViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="@{Integer.toString(viewModel.counter)}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btn_plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{()-> viewModel.increase()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/plus" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btn_minus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{()-> viewModel.decrease()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/minus" />
<Button
android:id="@+id/btn_move"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="이동"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
위의 코드 처럼 <data>를 추가해 주면 xml에서 ViewModel 에 있는 코드들을 사용할 수 있다.
textView에 있는 값은 android:text="@{Integer.toString(viewModel.counter)}"에 의해 ViewModel에 있는 counter의 값이 변할 때 마다 세팅된다. Integer.toString을 해준 이유는 textView이기 때문이다.
button에 클릭 이벤트를 세팅하기 위해서는 android:onClick="@{()-> viewModel.increase()}" 이와같은 코드를 추가해준다.
4. 동작화면
동작 순서를 나열해 보자면 ViewModel에 있는 livedata인 counter를 textview에 세팅해주고 버튼을 누르면 increase 메서드가 실행되고 counter의 값이 변경되면 mainactivity에 있는 binding.setLifecycleOwner(this); 에 의해서 실시간으로 값이 변경된 것을 확인해준다.
'코딩 > Android' 카테고리의 다른 글
[안드로이드] DataBinding (0) | 2022.03.31 |
---|---|
[안드로이드]Dialog 만들기 (DialogFragment, Custom Dialog) (0) | 2022.03.30 |