Android Architecture Components ViewModel을 간단하게 초기화 하려면?

Android Architecture Components ViewModel을 간단하게 초기화 하려면?



개인 광고 영역

Google I/O 2017에서 첫 선을 보였었다. 2018년 Google I/O에서 Jetpack 소개하였고, Android AAC(Android Architecture Components)를 포함하였다.

Jetpack에는 안드로이드 개발에 도움을 줄 수 있는 라이브러리 대부분을 추가하였는데 Architecture에는 Data Binding/Lifecycle/LiveData/Navigation/Paging/Room/ViewModel/WorkManager 제공하고 있다.

이중 AAC ViewModel 초기화하는 방법과 내부 코드를 살펴보고, 필자가 사용하려고 배포한 LifecycleExtensions을 소개한다.

Android AAC ViewModel을 간단하게 Inject 하기 위해서 개발 배포하는 라이브러리는 Github - LifecycleExtensions에서 확인 가능하다.


AAC ViewModel의 역할은?

Android AAC에서 제공하는 ViewModel은 일반적인 ViewModel 과는 다르게, Android에서 편하게 사용할 수 있도록 만든 ViewModel이다.

이러한 AAC ViewModel은 Android 개발에 특화되어있으며, 명칭상 ViewModel 일 뿐 실제 ViewModel 과는 내부 동작 방법이 다르다. 이러한 부분을 ViewModel과 AAC ViewModel을 비교해본다.

ViewModel

일반적으로 ViewModel을 설명할 때는 MSDN에서 설명하는 ViewModel을 이야기합니다.

  • View와 ViewModel 간의 관계를 단절시키기 위함
    • MVP를 활용하는 경우 View와 Presenter는 1:1의 관계를 가지며, 결합도가 높다.
      • Presenter에서 View를 알고, 이를 갱신하도록 유도한다.
      • View는 Presenter로부터 View 갱신을 유도 받고, 이를 갱신한다.
        • 이러한 이유로 View와 Presenter 간의 결합도가 높으며 의존관계를 깨기 어렵다.
    • MVVM은 MVP의 View와 Presenter의 높은 결합도를 줄이며, ViewModel에서 View를 알지 못하도록 설계한다.
      • ViewModel에서 View를 갱신할 때는 Observable 형태로 알리거나, DataBinding을 활용해서 알려야 한다.
        • DataBinding과 Observable(RxJava, Listener 등)을 통해 View의 갱신을 할 수 있도록 한다.
        • 결국 ViewModel의 데이터가 수정되었더라도, View는 수정할게 없도록 설계할 수 있다.
  • 결국 View와 ViewModel은 서로 의존하지 않는 형태로 구성해야 한다.
    • DI(Dependency Injection)을 이용해 의존성을 낮출 수 있다.
  • ViewModel은 용도에 따라서 최대한 구분하며, 공통 코드를 줄이는 방향으로 설계해야 한다.
    • 한 개의 View에서는 N 개의 ViewModel을 가질 수 있으며, 반대로 한 개의 ViewModel은 N 개의 View에서 사용될 수 있다.
  • Application 등 Android Lifecycle과 무관하게 동작해야 한다.

Android Jetpack의 AAC는 사실 ViewModel을 만들기 위한 도구들이 포함되어있는데, DataBinding이 이에 해당하며 Dagger2를 활용하여 좀 더 ViewModel 답도록 만들어줄 수 있다.

다만 AAC에 포함하고 있는 ViewModel은 오늘의 글을 통해 일반적인 ViewModel 과는 다름을 확인하고, Android용의 ViewModel로 활용할 수 있으면 좋을 것 같다.

그리고 ViewModel은 코드의 분리를 잘하면 할수록 복잡도가 낮아질 수 있으며, Test의 간소화도 함께 이루어질 수 있다.

AAC ViewModel

AAC ViewModel Document 소개에 잘 나와있는데 아래와 같다.

Android AAC ViewModel은 화면 회전시 데이터를 유지할 수 있는 구조로 디자인하였으며, Android Lifecycle의 onDestroy() 코드가 동작한다.

위 내용으로 알 수 있지만 앞서 본 ViewModel의 디자인 패턴과는 다름이 명확하다. AAC ViewModel은 화면 회전시 데이터 유지를 위함과 동시에 내부적인 구조에 따라 Lifecycle도 자동으로 동작하는데 onDestroy()가 이에 해당한다.

이런데 왜 이름을 ViewModel이라고 지어야 했는지는 의문이다.

그래도 최근 AAC 샘플인 Github - Google Android Architecture Components 샘플들을 보면 Android만의 ViewModel 활용을 하도록 샘플 코드 가이드를 하고 있음을 알 수 있다.

AAC ViewModel을 정리하면

  • 목적 : 화면 회전시 데이터 유지를 위한 구조로 ViewModel을 디자인하였다.
  • Activity/Fragment에 따라서 ViewModel 유지를 하고 있다.
  • 내부에서 Lifecycle을 사용할 수 있도록 초기화하고 있으며, onDestroy() 동작 시 ViewModel 내부의 onCleared() 호출을 통해 Release를 유도한다.

결국 AAC ViewModel은 일반적인 ViewModel에서 하지 않는 데이터 유지의 형태와 Android Lifecycle을 내부에서 동작하도록 하고 있음을 알고, AAC ViewModel을 활용하면 좋을것같다.

필자의 경우 모든 부분에서 AAC ViewModel을 활용하고 있지는 않다. Release가 필요치 않으며, 데이터 유지가 필요치 않은 경우에는 일반적인 ViewModel로 설계하여 사용하고 있다.

ViewModel의 초기화와 AAC-ViewModel 초기화 방법

ViewModel은 일반적인 객체 생성 방식을 사용한다. lifecycle이 필요한 경우 viewModel.something()을 부르는 방법으로 접근한다.

val viewModel = ViewModel()
viewModel.something()

하지만 AAC의 ViewModel은 ViewModelProviders을 이용한 초기화를 해야 하는데 아래와 같다.

val viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
viewModel.something()

ViewModel의 활용

Android 개발함에 있어 AAC ViewModel을 사용하는 것은 분명한 장점은 있다. Lifecycle을 내부적으로 알아서 호출해주고 있으며, Application의 활용을 할 수도 있다.

그렇다고 일반적인 ViewModel을 이해하지 못하면 AAC-ViewModel을 활용하는 것은 큰 장점은 없다고 생각한다. ViewModel을 먼저 이해하고, AAC-ViewModel을 활용할 수 있는 방향을 검토하는 게 좋다.

  • AAC ViewModel과 일반적인 ViewModel은 설계한 디자인 패턴부터가 다르다.
  • ViewModel 설명시 AAC-ViewModel 언급은 ViewModel을 설명하는 것이 아니다.

ViewModel 자체는 이미 어려운 구조이다. 더 많은 고민과 코드 분리의 필요성도 함께 이해해야 한다.

필자의 경우 코드 분리를 즐기고 있다 보니 이러한 부분이 어렵지 않았다. 다만 ViewModel을 접근하는 방법에는 아래와 같은 2가지 도구를 함께 사용해야 한다.

위의 2가지를 활용하는 경우에는 좀 더 ViewModel 다워지는 것인데, 필자의 경우 RxJava를 활용하여 ViewModel을 활용하고 있다.

추가로 Kotlin을 사용하는 경우 koin을 통해 DI를 활용할 수 있다. Koin은 Kotlin의 DSL(Domain Specific Language)을 활용하고 있다.

결론은 Android니깐 Context 또는 Application을 활용하지 않는 방법은 없으며, Lifecycle을 활용해야 좀 더 유용하게 사용할 수 있다.

이러한 부분을 편하게 쓰려면 결국 AAC의 ViewModel을 활용함이 좋다.


AAC ViewModel 적용하기

Android AAC ViewModel을 적용하기 위해서 Adding components 문서를 참고해서 아래와 같이 추가할 수 있다.

Android Lifecycle

Google I/O 2018에서는 AndroidX 패키지를 소개하였다. 하지만 아직 28.x까지는 기존 패키지를 사용할 수 있다.

dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
}

AndroidX packages

앞으로 Android의 Support library와 Architecture 등 모든 라이브러리는 androidx.*으로 시작하는 패키지 명을 활용한다.

dependencies {
    def lifecycle_version = "2.0.0-beta01"

    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
}


ViewModel 상속 클래스 생성하기

Android AAC ViewModel은 2개의 ViewModel을 상속을 제공한다.

기본 ViewModel의 내부에는 onCleared() 메소드가 포함되어있으며, Lifecycle 중 onDestroy()에서 onCleared가 호출된다.

public abstract class ViewModel {
	/**
	 * This method will be called when this
	 * ViewModel is no longer used and will be destroyed.
	 * <p>
	 * It is useful when ViewModel observes some data
	 * and you need to clear this subscription to
	 * prevent a leak of this ViewModel.
	 */
	 @SuppressWarnings("WeakerAccess")
	 protected void onCleared() {
	 }
}

AndroidViewModel은 ViewModel을 상속받고있으며, Application을 함께 초기화한다.

public class AndroidViewModel extends ViewModel {
    @SuppressLint("StaticFieldLeak")
    private Application mApplication;

    public AndroidViewModel(@NonNull Application application) {
        mApplication = application;
    }

    /**
     * Return the application.
     */
    @SuppressWarnings("TypeParameterUnusedInFormals")
    @NonNull
    public <T extends Application> T getApplication() {
        //noinspection unchecked
        return (T) mApplication;
    }
}

ViewModel과 AndroidViewModel을 상속받는 구현체는 Application 필요 여부에 따라서 개발자가 사용할 수 있다.

ViewModel 상속 구현

import androidx.lifecycle.ViewModel

class MainViewModel : ViewModel() {
	// ViewModel init

	override fun onCleared() {
		super.onCleared()
	}
}

AndroidViewModel 상속 구현

import android.app.Application
import androidx.lifecycle.AndroidViewModel

class MainViewModel(application: Application) : AndroidViewModel(application) {
	// ViewModel init

	override fun onCleared() {
		super.onCleared()
	}
}


AAC ViewModel 초기화

AAC ViewModel은 단순 객체 초기화가 아닌 AAC ViewModelProviders.of()로 시작하는 초기화를 진행해야 하는데 아래와 같다.

class MainActivity : AppCompatActivity() {

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

		val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
	}
}


ViewModelProviders.of() 내부를 조금 살펴보자

ViewModelProviders의 내부 코드를 살펴보면 FragmentActivity를 통한 초기화하는 함수와 Fragment를 이용한 함수 초기화하는 방법을 제공하고 있다.

이 안에서도 ViewModelFactory를 함께 넘겨서 초기화하는 경우와 @Nullable인 경우 초기화하는 코드가 함께 포함되어있다.

// Activity에서 초기화
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
		return of(activity, null);
}

// Activity에서 초기화
public static ViewModelProvider of(@NonNull FragmentActivity activity,
				@Nullable Factory factory) {
		Application application = checkApplication(activity);
		if (factory == null) {
				factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
		}
		return new ViewModelProvider(activity.getViewModelStore(), factory);
}

factory가 없을 경우 내부의 ViewModelProvider.AndroidViewModelFactory.getInstance()를 호출하는 코드가 포함되어있는데, 아래의 AndroidViewModelFactory 코드를 확인할 수 있다.

ViewModelProvider.NewInstanceFactory 상속을 통해 아래와 같이 구현되어있는 코드에서 중요한 부분은 create 부분이다.

public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {

	private static AndroidViewModelFactory sInstance;

	@NonNull
	public static AndroidViewModelFactory getInstance(
			@NonNull Application application) {
		if (sInstance == null) {
			sInstance = new AndroidViewModelFactory(application);
		}
		return sInstance;
	}

	private Application mApplication;

	/**
	 * Creates a {@code AndroidViewModelFactory}
	 *
	 * @param application an application to pass in {@link AndroidViewModel}
	 */
	public AndroidViewModelFactory(@NonNull Application application) {
		mApplication = application;
	}

	@NonNull
	@Override
	public <T extends ViewModel> T create(
			@NonNull Class<T> modelClass) {
		if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
			//noinspection TryWithIdenticalCatches
			try {
				return modelClass.getConstructor(Application.class).newInstance(mApplication);
			} catch (NoSuchMethodException e) {
				throw new RuntimeException("Cannot create an instance of " + modelClass, e);
			} catch (IllegalAccessException e) {
				throw new RuntimeException("Cannot create an instance of " + modelClass, e);
			} catch (InstantiationException e) {
				throw new RuntimeException("Cannot create an instance of " + modelClass, e);
			} catch (InvocationTargetException e) {
				throw new RuntimeException("Cannot create an instance of " + modelClass, e);
			}
		}
		return super.create(modelClass);
	}
}

AndroidViewModelFactory의 create에서는 넘어온 Class<T>의 객체가 AndroidViewModel인지 체크한 다음 Application.class가 생성자에 포함되어있는 객체를 생성하고, 그렇지 않으면 아래의 기본 NewInstanceFactory의 create()를 호출하여 생성자에 아무것도 없는 객체를 생성하게 된다.

public static class NewInstanceFactory implements Factory {

	@SuppressWarnings("ClassNewInstance")
	@NonNull
	@Override
	public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
		//noinspection TryWithIdenticalCatches
		try {
			return modelClass.newInstance();
		} catch (InstantiationException e) {
			throw new RuntimeException("Cannot create an instance of " + modelClass, e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException("Cannot create an instance of " + modelClass, e);
		}
	}
}

결국 Class<T> 형태를 만들어서 좀 더 편하게 ViewModel을 만들 수 있도록 Default.Factory를 불러와서 사용하도록 해두었다.

하지만 모든 ViewModel에 객체가 없는 경우는 보통 없을 것 같다. 데이터를 사용해야 하므로 Repository를 함께 초기화해야 하는 건 일반적이다.


ViewModelFactory을 구현해서 초기화하는 방법은?

생성자에 초기화 값을 넘겨야 하는 게 일반적이다. 이 경우에는 앞서본 Default.Factory를 이용해서는 객체를 생성할 수 없으니 Factory를 상속받아 구현해주어야 한다.

class GithubSearchViewModel(
	private val adapterViewModel: UserAdapterViewModel,
	private val githubSearchRepository: GithubSearchRepository) : ViewModel() {
		// ...
}

ViewModelFactory를 이용하여 초기화해야 ViewModel에서 Activity/Fragment의 lifecycle을 사용할 수 있으니, 그에 맞게 ViewModelProvider.Factory를 상속받아 아래와 같이 초기화하는 코드가 필요하다.

class MainActivity : AppCompatActivity() {

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

		val viewModel = ViewModelProviders.of(this,
				object : ViewModelProvider.Factory {

			override fun <T : ViewModel?> create(modelClass: Class<T>): T {
				return GithubSearchViewModel(
						userRecyclerAdapter.viewModel,
						githubSearchRepository) as T
			}
		}).get(GithubSearchViewModel::class.java)
	}
}


AAC ViewModel에서는 ViewModelProviders.of() 메소드가 중요하다.

AAC ViewModel에서 가장 중요한 부분으로 ViewModelProviders.of()of()이다. of() 메소드 호출시에 넘겨주는 FragmentActivity/Fragment를 이용하여 내부에서 ViewModelStore를 어떤 걸 사용할지 결정하게 된다.

코드를 좀 더 따라가보도록 하자. ViewModelProvider를 생성할 때 ViewModelStores을 함께 초기화하는데 아래와 같은 코드를 확인할 수 있다.

public static ViewModelStore of(@NonNull FragmentActivity activity) {
	if (activity instanceof ViewModelStoreOwner) {
		return ((ViewModelStoreOwner) activity).getViewModelStore();
	}
	return holderFragmentFor(activity).getViewModelStore();
}

최초에는 holderFragmentFor를 통해 ViewModelStore을 리턴하는 코드를 확인할 수 있다. 결국 holderFragmentFor에 따라가면 ViewModelStoreOwner을 상속받고 있는 HolderFragment를 확인할 수 있다. 그리고 그 안에는 FragmentActivity 용 ViewModelStore와 Fragment 용 ViewModelStore을 각각 따로 초기화하고 있음을 확인할 수 있다.

FragmentActivity/Fragment의 ViewModelStore에는 HashMap<String, ViewModel>에서 별도의 key를 이용해 기존에 있던 객체를 다시 가져오도록 구성되어있는데 이러한 역할은 ViewModelProviders 초기화시에 사용한 마지막 메소드인 get()에서 하고 있다.

key를 별도로 지정하지 않은 경우에는 아래와 같은 코드에서 확인할 수 있지만 내부의 DEFAULT_KEY에 받아온 modelClass의 이름을 조합하여 키를 만들고 있다.

// key 지정하지 않을 경우 내부에서 DEFAULT_KEY:canonicalName을 합쳐서 사용한다
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
	String canonicalName = modelClass.getCanonicalName();
	if (canonicalName == null) {
		throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
	}
	return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}

key를 만들고 난 다음 ViewModelFactory의 create() 메서드를 호출하여 ViewModel을 생성하고, 이미 있는 경우 HashMap의 결과를 return 하는 코드를 아래와 같이 확인할 수 있다.

// key를 지정할 경우에는 아래와 같다.
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {

	ViewModel viewModel = mViewModelStore.get(key);

	if (modelClass.isInstance(viewModel)) {
		//noinspection unchecked
		return (T) viewModel;
	} else {
		//noinspection StatementWithEmptyBody
		if (viewModel != null) {
			// TODO: log a warning.
		}
	}

	viewModel = mFactory.create(modelClass);
	mViewModelStore.put(key, viewModel);
	//noinspection unchecked
	return (T) viewModel;
}

결국 FragmentActivity/Fragment 용의 별도의 ViewModel들을 관리하고 있으며, 그에 따라서 생명 주기도 동작하게 한다.

이 코드는 HolderFragment에서 확인할 수 있는데 아래와 같다.

public class HolderFragment extends Fragment implements ViewModelStoreOwner {
	// ...
	@Override
	public void onDestroy() {
		super.onDestroy();
		mViewModelStore.clear();
	}
	// ...
}

// ViewModelStore 내부는 아래와 같다.
public class ViewModelStore {
	/**
	 *  Clears internal storage and notifies ViewModels that they are no longer used.
	 */
	public final void clear() {
		for (ViewModel vm : mMap.values()) {
			vm.onCleared();
		}
		mMap.clear();
	}
}


ViewModel과 AAC ViewModel 도식화

ViewModel과 AAC ViewModel의 초기화 및 사용 방법을 도식화한 이미지이다.

ViewModel

ViewModel은 일반적인 객체 생성하는 방법을 활용하여 생성하며, ViewModel과 View/ViewModel과 Model의 사이는 Observable 통지를 통해 UI 갱신을 한다.

ViewModel

AAC-ViewModel

AAC ViewModel도 크게 다르지 않지만 ViewModelProvider를 활용해 초기화를 한다. 그리고 ViewModel과 View/ViewModel과 Model의 사이는 Observable 통지를 통해 UI 갱신을 한다.

AAC-ViewModel


Introduction LifecycleExtensions

LifecycleExtensions은 1년 전에 배포했었다. 다만 라이브러리 업데이트와 초기화 코드의 문제를 확인하여 전체 수정을 하였다.

이번 버전에서는 크게 2 종류로 분리하여 배포하였는데 AndroidX 패키지와 Legacy 패키지를 분리하여 배포하였다.

모두 jcenter()를 통해 배포하고 있으며, 아래와 같은 dependencies 추가가 필요하다.

AndroidX - New package

AndroidX 패키지를 활용하는 경우 implementation “tech.thdev.lifecycle:lifecycle-extensions:$latestVersion”를 추가하여 사용할 수 있다.

Download

implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.60'
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0-beta01'

implementation "tech.thdev.lifecycle:lifecycle-extensions:$latestVersion"

Legacy package

기존 com.android.support 라이브러리를 활용하는 경우 implementation ‘tech.thdev.lifecycle:lifecycle-extensions-legacy:1.3.0’를 추가하여 사용할 수 있다.

Download

implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.60'
implementation 'com.android.support:appcompat-v7:27.1.1'

implementation 'android.arch.lifecycle:extensions:1.1.1'

implementation 'tech.thdev.lifecycle:lifecycle-extensions-legacy:1.3.0'


Library 사용 방법

자세한 Library 사용 방법은 thdev - LifecycleExtensions 문서를 통해 확인 가능하고, 이 글에서는 Kotlin lazy pattern을 활용한 lazyInject 하는 방법을 소개한다.

두 라이브러리는 ViewModelProvider.Factory을 만들지 않고, 내부에서 처리할 수 있도록 구성하여, 사용할 때는 간단하게 inject만으로 할 수 있도록 구현하였다.

Activity에서 초기화

Activity에서 사용할 lazyInject에는 option으로 customKey를 구성할 수 있도록 추가하였다. 기본은 내부의 customKey를 활용하고 있어 커스텀 키가 필요한 경우 초기화가 가능하다.

@param customKey : Option value. Default empty.

아래와 같이 lazyInject를 초기화할 수 있으며, customKey를 함께 초기화할 수 있다.

class MainActivity : AppCompatActivity() {

    private val viewModel: MyViewModel
            by lazyInject(/* @Option customKey = "custom key" */) {
        // create Your ViewModel
        MyViewModel(..., ..., ...)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        // Maybe init view model
        viewModel ...
    }
}

Fragment에서 초기화

Fragment에서는 2 가지 방법으로 초기화해야 하는데, FragmentActivity와 Fragment를 활용한 초기화를 할 수 있도록 API를 만들었다.

@param isActivity : Option value. Default false.
@param customKey : Option value. Default empty.

위의 2 가지 옵션을 활용하여 아래와 같이 Activity 초기화와 Fragment 초기화를 구분할 수 있다.

isActivity는 초기화하지 않으면 기본 Fragment를 활용하여 초기화한다.

class MainFragment : Fragment() {

    private val viewModel: MyViewModel
            by lazyInject(
                    isActivity = true
                    /* @Option , customKey = "custom key" */) {
        // create Your ViewModel
        MyViewModel(..., ..., ...)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        // Maybe init view model
        viewModel ...
    }
}


마무리

Android AAC ViewModel은 안드로이드에서 사용하는 데 있어 좋은 패턴임은 명확하다. 하지만 ViewModel이라고 칭하기에는 View의 디펜던시를 너무 강하게 가지고 있다.

문서에도 나와있지만 AAC ViewModel은 ViewModel의 조건과는 다르다. 데이터를 유지하기 위한 FragmentActivity/Fragment를 통한 초기화 코드와 lifecycle을 편하게 해주기 위해서 onDestroy() 호출 시 onCleared() 호출을 하기 위한 HolderFragment… 너무 많은 부분의 개입이 일어나고 있다.

ViewModel은 어떤 View에서 쓰이는지 알 필요가 없고, 다양한 View에서 사용될 수 있어야 한다. 결국 View 어디서든 초기화가 가능해야 하는데 그에 비해 디펜던시가 강하다. 어떻게 보면 ViewModel 일 수도 있지만, ViewModel로 칭하기에는 힘들 수 있다.

아무래도 Android이기 때문에 전제를 깔고 가면 좀 쉽게 사용할 순 있다.

필자는 AAC ViewModel을 활용하고 있다. 모든 부분에서 AAC ViewModel을 활용하지는 않으며, Activity/Fragment에서 Lifecycle의 onDestroy()가 필요한 경우에 이를 활용하고 있다. 그 외에는 ViewModel을 만들어서 사용하고 있다.

여하튼 애매하게 ViewModel이라는 이름으로 만들어서 MSDN의 ViewModel을 이해하고 있는 사람들은 AAC ViewModel은 ViewModel이 아니라고 명확하게 이야기한다. 위와 같은 이유들이 있기 때문에 ViewModel 설명시에는 잘못된 결과를 가져올 수 있다. 결국 사용하고 있는 필자도 Android니깐 ViewModel은 이렇게 할 수 있다 정도이다.

쓰면 편해서 더 편하게 사용하도록 LifecycleExtensions Library를 활용할 수 있다.

좀 더 이해를 하고 쓰는 게 좋아서 Android AAC ViewModel을 정리해보았다.



About Taehwan

My name is Taehwan Kwon. I have developed Android for 6 years and blog has been active for eight years.

Comments