컨텐츠 중심의 모바일 서비스 응용프로그램을 개발하기 위해 MVVM(Model-View-ViewModel) 패턴과 Rx(Reactive Extensions)를 활용해 설계한 Reactive MVVM 아키텍쳐를 설명합니다. 조금 더 자세한 설명은 블로그 포스트를 참고하세요. https://justhackem.wordpress.com/2015/03/19/rmvvm-architecture/
3. MVVM(Model-View-ViewModel)
• In 2005, John Gossman(Microsoft)
• Separation of Presentation and Presentation Logic
• Two-way Binding
• Properties and Commands
• Testability
• WPF, Silverlight, Xamarin Forms, AngularJS, EmberJS, KnockoutJS, RoboBinding
• Introduction to Model/View/ViewModel pattern for building WPF apps
• WPF Apps With The Model-View-ViewModel Design Pattern
7. Showcase …
Showcase 15
no envy
Showcase …
…
… …
Showcase 15
no envy
Profile
Showcase 15
no envy
Showcase …
…
New Feed Explore Notifications
단일 컨텐트에 대한 다중 뷰
35. 모델
public abstract class Model<TModel, TId>
where TModel : Model<TModel, TId>
where TId : IEquatable<TId>
{
private readonly TId _id;
public TId Id { get { return _id; } }
protected Model(TId id)
{
_id = id;
}
}
36. 모델
public sealed class ShowcaseModel : Model<ShowcaseModel, long>
{
private readonly bool _isEnvied;
private readonly int _envyCount;
public ShowcaseModel(long id, bool isEnvied, int envyCount) : base(id)
{
_isEnvied = isEnvied;
_envyCount = envyCount;
}
public bool IsEnvied { get { return _isEnvied; } }
public int EnvyCount { get { return _envyCount; } }
}
37. 스트림 저장소
public static class StreamStore<TModel, TId>
where TModel : Model<TModel, TId>
where TId: IEquatable<TId>
{
public static IObservable<TModel> GetStream(TId id);
public static void Push(TModel model);
}
38. 모델-뷰모델
public abstract class ModelViewModel<TModel, TId> : ViewModel
{
private TModel _model = null;
public TModel Model
{
get { return _model;}
set { SetProperty(ref _model, value); }
}
protected virtual void OnNext(TModel next)
{
Model = next;
}
}
45. 중복된 비동기 데이터 조회
• 불필요한 무효화(invalidation)
• 시작과 종료 순서의 불일치
46.
47. Switch()
“Transforms an observable
sequence of observable sequences
into an observable sequence
producing values only from the
most recent observable sequence.”
- from MSDN
50. Task to Observable
public abstract class ModelViewModel<TModel, TId> : ViewModel
{
protected void Push(Task<TModel> next)
{
Push(next.ToObservable());
}
protected void Push(Func<Task<TModel>> next)
{
Push(next.Invoke().ToObservable());
}
}
51. Model to Observable
public abstract class ModelViewModel<TModel, TId> : ViewModel
{
protected void Push(TModel next)
{
Push(Task.FromResult(next).ToObservable());
}
}
57. 병합 연산
public static class ModelExtensions
{
public static UserModel Coalesce(this UserModel user, UserModel other)
{
if (user == null) throw new ArgumentNullException("user");
if (other == null) return user;
if (other.Id != user.Id) throw new ArgumentException();
if (user.Equals(other)) return user;
return new UserModel(user.Id,
user.UserName,
user.ProfilePhotoUri,
user.FolloweeCount ?? other.FolloweeCount,
user.FollowerCount ?? other.FollowerCount);
}
}
58. 병합 연산
public class UserViewModel : ModelViewModel<UserModel, string>
{
protected override void OnNext(UserModel next)
{
var current = Model;
base.OnNext(next.Coalesce(current));
}
}