読者です 読者をやめる 読者になる 読者になる

眠いしお腹すいたし(´・ω・`)

C#関連を主に書きます。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

WeakなReactivePropertyを作ってみた

C# ReactiveExtentions ReactiveProperty Xamarin.Forms

本題

ReactivePropertyを使う際にViewModelでModel層からToReactivePropertyなどを使う場合にモデル層にSubjectすることで強参照な結びつきが生まれてViewModelがいつまでも破棄されなくなってリークしてしまいます。

その解決アプローチとしてWeakReferenceを利用できないか考えてみました。

今回のリポジトリです

github.com

WeakReactiveProperty

とりあえずWeakなReactivePropertyを作成。

まずはWeakSubscriber。

gist.github.com

要するにWeakに購読します、みたいな感じです。

これを利用してWeakReactivePropertyを作成。

WeakReactivePropertyExtentions/WeakReactiveProperty.cs at master · yuka1984/WeakReactivePropertyExtentions · GitHub

基本的に素のReactivePropertyのObservableにSubScribeしている部分をWeakSubscribeに置き換える感じです。

詳細までは確認してません。

確認

まずは効果を検証するためにみんな大好きコンソールアプリでチェック

WeakReactivePropertyExtentions/Program.cs at master · yuka1984/WeakReactivePropertyExtentions · GitHub

結論としてはWeakReactivePropertyをViewModel側で使うとダメな感じ。

まだVMインスタンスが参照されているのにGC.Collect()で回収されてしまって動かなくなってしまいます。

良いパターンとしてはModel(コードで言うとWeakServiceクラス)のパターン。

モデル層でWeakReactivePropertyを使うとうまくいっています。

これならうまくいきそうなので実際にXamarin.Formsで検証してみました。

こんな感じのVMを作ります。

gist.github.com

App.csはこんな感じ。

gist.github.com

NavagationPageに沢山スタックさせてからバックボタンで最初のページまで戻ってカウントアップボタンを押します。

Weakでない普通のサービスクラスを使用するとデバッグウィンドウに作ったページ分のデバッグ出力が出てしまいます。

f:id:tamafuyou:20170315095634p:plain

所謂リークしている状態。

次にServiceをWeakServiceに書き換えて同じ動作を行います。

f:id:tamafuyou:20170315095900p:plain

いい感じに見える(; ・`д・´)

ただNavigationスタック上にはPageは一つしかないはずなのにデバッグメッセージは2行必ずでてきちゃう。

おそらくどこかでXFが参照を持っていると思われるのだけれども深追いはしないです。

最後に

一応こんな感じでWeakReferenceを使用したReactivePropertyでModel層を作る事でリークを解決できるかもしれないです。

ReactivePropertyの有識者の方、Xamarin.Formsチョットデキル以上な方で、この記事を読んでくれた人がいましたら

問題点とかおかしい点とか指摘してもらえると助かります。

よろしくお願いします。

ではでは(‘ω’)ノ