UWP(Universal Windows Platform)

-       Lifecycle

n  Not running, running, suspended

u  몇 개의 앱을 삭제해야 하는 경우(Suspended state App이 너무 많은 리소스를 잡아 먹는 경우), 앱을 삭제 할 텐데, 이럴 때 사용자가 시스템이 종료시킨 앱에 돌아오려고 한다면?? 데이터를 잃을 것이다. 이러한 해프닝을 막기 위해선 아래의 두 Method 에서 useful data를 저장해주어야 한다.. The coding pattern for managing potential app terminations only requires you to save off any useful data from the current user session. Then, if the app gets terminated, you restore this data with custom code once the app is relaunched by the user.
(Read more at
https://blogs.windows.com/buildingapps/2016/04/28/the-lifecycle-of-a-uwp-app/#sL5cBJVCbLvUHK7p.99)

n  Application.Suspending : 일반적으로 앱이 terminated 수도 있다고 가정하고, 이를 대비하기 위해 하는 작업을 다루는 .

n  Application.Resuming : 보통은 아무것도 필요 없는 . 하지만??

u  좋은 UWP개발자라면? Suspending에서 큰 리소스를 deallocated 해줘야 할 것.

u  위에 처럼 Suspending 에서 리소스를 deallocated 했다면, Resuming 에서는 해제했던 리소스들을 reinitialize 해줘야 할 것이다.

n  Await 키워드 : await AppInitialization.DoInitializations();

u  Await이 붙으면 그 뒤에는 task가 위치한다. 만약 위의 코드 한줄이
private async Task<AppShell> Initialize()
안에 있다면, DoInitializations()가 실행이 되어 리턴될때까지(Task가 수행될 때 까지) Initialize() 메소드가 기다려 준다. .(http://nsinc.tistory.com/109)

n  GetDeferral()

u  var deferral = e.SuspendingOperation.GetDeferral();

//Async 작업.

deferral.Complete();

 

Deferral을 사용하면, 최대 5초까지 사용자가 필요로 하는 시간을 보장해준다.Deferral을 사용하는 목적은 결국 백그라운드 작업이 일찍 중지되지 않도록(최대5) 보장해주기 위해 사용.

백그라운드 작업에서 비동기 코드를 실행할 경우 백그라운드 작업은 deferral 사용해야 합니다. deferral 사용하지 않을 경우 비동기 메서드 호출이 완료되기 전에 Run 메서드가 완료되면 백그라운드 작업 프로세스가 예기치 않게 종료될 있습니다.

비동기 메서드를 호출하기 전에 Run 메서드에서 deferral 요청합니다. 비동기 메서드에서 액세스할 있도록 deferral 전역 변수에 저장합니다. 비동기 코드가 완료된 후에 deferral 완료를 선언합니다.

https://msdn.microsoft.com/ko-kr/windows/uwp/launch-resume/create-and-register-a-background-task

 

 

n  MVVM

u  View – ViewModel –Model

l  View : Page 객체이다.

n  View.cs : code-behind 코드 내에서, onNavigatedTo 내에서. 즉 이 page로 넘어올 때, ServiceLocator 에서 viewModel을 로드해온다. 그리고 set 해준다.

l  ViewModel : 상수, 커맨드, Property 들을 정의.

n  특징은 viewModel 생성자들은 자기의 view가 화면에 보여지게 하기 위해 파사드(façade) 가 필요하므로, 생성자에서 첫번째 인자로 façade를 전달받아, 해당 façade를 통해 화면전환을 진행 한다.

 

 

 

 

Unity: The Unity Container (Unity) is a lightweight, extensible dependency injection container with optional support for instance and type interception.

(https://msdn.microsoft.com/en-us/library/ff647202.aspx)

 ServiceLocator, UnityContainer, BootStrapper 등등 라이브러리 제공.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

메모장에 주절주절 한 것.

1. App.xaml.cs

 - OnActivated, OnLaunched -> Initialize -> Bootstrapper의 초기화

 

2. Bootstrapper.cs (The bootstrapper is responsible for the initialization of an application built using the Composite Application Library)

ServiceLocator, Registries, Container 생성 및 셋팅

 ViewRegistry Configure() 에서 NavigationFacade 에 각 Page ViewModel Facade에 등록.

 

 

*************************************************************

 

 

[ServiceLocator]

(http://www.c-sharpcorner.com/UploadFile/dacca2/service-locator-design-pattern/)

 

Generic type을 지원. 여러 타입의 Serivce <Service Type, Service object> 형식으로

Dictionary를 내부적으로 가지고 있고, 해당 Dictionary를 활용하여 GetService method를 지원 한다.

Dictionary Service Container 라 부른다.

 

 

[Bootstrapper]

Container Registries를 가지고 있고 App ServiceLocator 를 셋팅 해준다.

Container는 내부적으로 위에서 설명한 Dictionary를 가지고 있으며,

ServiceLocator를 생성할 때, Container를 만들어서 전달인자로 전달해준다.

 

그러면 ServiceLocator Conatiner는 우리가 원하는 Container로 설정이 되며,

그 다음 Registries을 생성 및 초기화 할 때, Locator가 들고있는 Conatiner를 전달해주어,

Registires 에서도 해당 Container <type, object> 형태로 저장을 한다.

 

결론: ServiceLocator가 들고있는 Container bootstrapper 가 들고있는 Container 이며,

해당 Container는 하나만 존재한다. 그리고 모든 Service(Facade 포함) 를 들고 있다.

 

[Container]

Bootstrapper에서 들고있고, Service를 관리.(type, object) dictionary.

 

[Registry] : 필요한 위치에 service, view , viewModel 등을 등록한다.

대표적으로 viewRegistry, viewModelRegistry, ServiceRegistry 가 있다.

 

- ServiceRegstry 에서는 App에 필요한 각종 Service Container에 등록하는 일을 한다.

IDialogService, NavigationFacade 등의 각 서비스를 Container에 등록하는 일을 한다.

 

*************************************************************

 

[AppShell]

현재까지 파악한 건, 가장 RootPage. 우리가 만드는 page 이다. App.xaml.cs 내에 있는 OnActivated, onLaunched

메소드 내에서, Window.Current.Content = new AppShell() 형태로 설정해줌으로써, 처음 화면이 시작된다.

AppShell 내에는 Frame이 있어서, 이 해당 Frame에다가 NavigationFacade가 화면을 설정해주면,

해당 Root 윈도우의 Frame에 원하는 View가 설정된다.

 

, AppShell은 하나의 Page이며, Root(main) page라 할 수있다.

그리고 root page에서 화면이 전환되길 원하는 영역을 AppShell.xaml에서 Frame 영역으로 정의해 둔다.

 

 

해결 된 질문 사항---------------------------------------------------------------------------------

 

Q) Frame Facade에 의해 제어 된 후,  AppShell(MainWindow)에 어떻게 화면이 뜨는지?

 

1. 우선 App.xaml.cs 에서 Window.current.Content = shell 이런 작업을 해준다.

content에 넣는 타입은 UIElement타입이고, 해당 코드를 통해 실제 현재 App Window의 화면이

결정된다.

2. Widnow.current.content = frame. 이런식. (new example을 만들면...)

3. PhotoSharing 프로젝트 내에, AppShell.xaml에는 <Frame x:name=frame /> 이 있어서 xaml내에 위치하고 있으며,

코드 비하인드내에 AppFrame 프로퍼티는 read-only이며, 해당 위 xaml에 있는 frame 객체를 return 한다.

즉 해당 App에서는 Facade AppShell.xaml Frame 객체를 가지고, navigate 한다.

 

핵심 : Tool에서 하나의 Frame을 사용하여 화면 제어. (지금까지 이해한 바로는...)

-> 테스트 결과 Page 클래스에 Frame객체를 들고있지만, Read only이고, AppXaml.cs에 있는

RootFrame에서 frame.Navigate(typeof(page1)) 을하면, page1.frame rootFrame frame으로 되는 듯.

 

App에서는 하나의 frame이 존재 -> Hashcode값이 모두 동일함을 확인.

 

Q) Facade Pattern ??

https://ko.wikipedia.org/wiki/%ED%8D%BC%EC%82%AC%EB%93%9C_%ED%8C%A8%ED%84%B4#C.23

 

 

(adapter pattern) : https://ko.wikipedia.org/wiki/%EC%96%B4%EB%8C%91%ED%84%B0_%ED%8C%A8%ED%84%B4

 

비슷하지만,

adapter pattern은 사용자가 기대하는 다른 인터페이스로 변환하는 패턴.

Facade pattern은 커다란 부분의 코드 부분을 간략화된 인터페이스로 사용자에게 제공하는 패턴.

 

 

 

Q) View ViewModel들이 어떻게 Datacontext로 셋이 되는가.. 기존 wpf에서처럼 viewmodel을 우리가 원할 때,

넣는 방법은?

 

1. SettingPage를 예로 들면 코드비하인드에서 ViewModel ServiceLocator.Current.GetInstance<SettingViewModel>(); 을 해서

얻는다.(이때 GetInstance는 확장메서드)

  type을 전달하면 ServiceLocator가 객체를 생성해서 리턴한다.

2. 일반적으로 page Code-behind내에있는 navigatedTo() 메소드 안에서, DataContext ServiceLocator GetInstance 확장메서드를 활용해서

ViewModel을 얻어와서 설정한다.

3. ViewModel을 만드는 다른 유형은 CropPage() 참고.

 

 - CropPage()의 생성자에서 우선 여러 paramter를 전달하여 viewModel을 만들어 놓는다.

NavigatedTo() 내에서는 전달받은 NavigationEventArgs 객체를 통해 이전 상태를 Load 할 수 있다. (viewModelBase 내에있는 ViewModel.LoadState() 사용)

(NavigatedTo() NavigationFacade에 구현된 NavigateToCropView() 내에서, Navigate 할 때,

ViewModel에 필요한 Args 를 같이 전달 해준다...)

 

 

Q) Facade를 이용하면, ViewModel도 싱글톤인가.?? GetInstance로 얻어오는데, 싱글톤인가..???

Facade에서 ViewModel을 생성하는것은 아니고, Facade에서는 약속된 Interface를 통해

클라이언트가 원하는 View navigate만 시켜준다. ViewModel View의 코드비하인드 내에서 알아서 만들어서쓰는데,

이때 Facade에서는 ViewModel에 필요한 args가 있다면, Navigate() parameter로 전달해줘서

code-behind에서 알아서 args를 참고해서 viewModel을 생성 혹은 갱신할 수 있도록 해준다.

 

 

위 질문에 대한 대답은 Facade view navigate만 해주며, viewModel에 필요한 args가 있다면,

Navigate()할 때, 같이 전달한다.

 

 

Q) Bootstrapper -> ServiceRegistry -> Container Facade RegisterType으로 추가하는데,

실제 NavigationFacade 객체를 생성하는곳은 어디인가..

 

일단 PhotoSharing 프로젝트에서는 마.소의 UnityServiceLocator를 쓰고, UnitiContainer를 쓴다.

UnityServiceLocator.Current.GetInstance()를 하면,

내부적으론 UnityContainer.Resolve() -> DoBuildUp() -> 내부에서 Type을 가지고 instance화 해서

Return 해준다.

 

Q) Design-time ViewModel ViewModel의 차이.

Design-time ViewModel : https://catelproject.atlassian.net/wiki/display/CTL/Design-time+view+models

( you can preview the UserControl or DataWindow implementations using example data.)

요지 : Design time  viewModel은 즉 테스용으로, 디자이너가 xaml을 직접 or blend 따위를 이용하여

작성한 후에, 실행한 화면을 보고싶을 때 사용될 viewModel. 또는 처음 실행했을 때,

값이 셋팅된 모습의 뷰를 보여주고자 할 때 사용한다.

 

IsDesignTimeCreatable flag 이용해서, 데모데이터를 보여주도록 설정 가능.

 

처음에 원하는 샘플용 데이터로 보여주고, 실제 유저가 사용할 때 Datacontext를 일반적인 VieModel

바꿔치기하면, 원래대로 사용.

 

미확인 질문 사항-------------------------------------------------------------------------------------------

 

 

Q)

ServiceLocator.Current.GetInstance<SettingsViewModel>() ;

 

이렇게하면 viewModel이 나오는데, 이땐 싱글톤은 아닐듯? 그때그때 type보고 새 객체를 생성해주지않을까..

근데 전달인자가 필요할땐 어떻게 GetInstance로 만들지??

 

전달인자가 있을때는, 글쎄...........

 

Q) GridView, FlipView (WelcomePage)

   HubSection (LeaderboardsPage)

   VisualState

 

  각각 Layout 공부하기.

 

 

 

블로그 이미지

kuku_dass

,