Tizen .Net Xamarin.Forms - Navigation 타이젠 Tizen 2020. 7. 22. 22:48

MVVM 패턴이 적용된 Tizen Xamarin.Forms Application을 만들 때 고민되는 Navigation에 대해서 정리해 본다.

Navigation이 고민되는 이유는 View의 전환인데, View Model에서 처리하는 경우 View Model이 View에 의존성을 갖게되는 부분이 MVVM의 철학과 배치되기 때문이다. 그외에도 파라미터를 제대로 넘겨주는 것과 navigation 중에 적용되어야 할 규칙을 확인하는 등의 문제가 있는데, Navigation Service 클래스를 만들어서 이런 부분을 해소하려 한다.

핵심 내용은 지난 번에 소개한 그 책에서 소개된 내용이다. Enterprise Application Patterns - Navigation 핵심 컨셉은 비슷하지만 구현 내용은 좀 다르다.

https://docs.microsoft.com/ko-kr/xamarin/xamarin-forms/app-fundamentals/navigation/hierarchical

NavigationService

NavigationService 라는 클래스를 만들었다. Singleton 이어도 좋지만 Singleton으로 만들면 테스트하기 힘드니까. 그냥 내가 쓸때 싱글톤으로 사용한다. App 생성될 때 만들어서 global context에 붙여놓고 쓰기도 하고, 가능하면 생성자 Dependency Injection을 사용한다. 간단하게 구성하기에는 이걸로도 충분하다. 나중에 DI에 대해서는 좀 더 깊게 이야기를 풀어놔봐야겠다.

Shared project에서는 아래와 같이 인터페이스를 추가해서 사용하고, 실제 구현체는 .Tizen프로젝트에서 구현했다. 플랫폼 의존성이 있는 것과 없는 것을 구분해두면 느슨한 커플링 상태를 유지할 수 있다.

namespace xamarinExample.Services
{
    public interface INavigationService
    {
        void Initialize();

        Task NavigateToMainListPageAsync();

        Task NavigateToBunchPageAsync(Bunch bunch);
    }
}

실제 구현체는 아래와 같다.

namespace xamarinExample.Tizen.Services
{
    public class NavigationService : INavigationService
    {
        public void Initialize()
        {
            App.Current.MainPage = new NavigationPage(new MainPage(this));
        }

        public Task NavigateToMainListPageAsync()
        {
            var navigationPage = App.Current.MainPage as NavigationPage;
            if (navigationPage != null)
            {
                return navigationPage.PushAsync(new MainListPage(this));
            }
            else
            {
                Application.Current.MainPage = new NavigationPage(new MainListPage(this));
            }
            return Task.FromResult(true);
        }

        public Task NavigateToBunchPageAsync(Bunch bunch)
        {
            var navigationPage = App.Current.MainPage as NavigationPage;
            if (navigationPage != null)
            {
                return navigationPage.PushAsync(new BunchPage(this, bunch));
            }
            else
            {
                Application.Current.MainPage = new NavigationPage(new BunchPage(this, bunch));
            }
            return Task.FromResult(true);
        }

    }
}

사용은 App 생성 될 때 아래와 같이 생성해서 사용하였다.

public App()
{
    InitializeComponent();
    _navigationService = new NavigationService();
    _navigationService.Initialize();
}

마치며

View Model이 View를 모르게 하고 싶어서 결국 인터페이스를 추가하여 참조하고, 실제 구현체에서 View를 참고하고 있는 식이다. 느슨한 결합을 유지하기 위해 사용되는 아주 일반적인 방식이다. 코드도 조금 더 많아지고, 조금 더 귀찮아지긴 했지만 그래도 이렇게하는것이 마음이 편하다. Navigation 관련 로직도 한곳에 모아서 정리할 수도 있다.

참조

댓글