Xamarin でネイティブオブジェクトを使う際に最近気をつけていること
Xamarin でネイティブクラス(UIViewやActivity)のオブジェクトを使った際、気をつけて使わないとクラッシュの元になったりします。
今回は最近はまって気をつけていることをご紹介します。
ネイティブオブジェクトから継承したら Dispose を書く
ネイティブオブジェクトを継承した場合、Dispose で参照を外しましょう。また、コードから new で作ったインスタンスは Dispose しましょう。
このとき、disposing の値を見て、この値が true でないときは処理をしないようにする必要があります。そうしないとUIスレッド外でこれが呼ばれたときにUIオブジェクトを触ってしまいクラッシュ、ということになります。
UIButton appendButton; public override void ViewDidLoad () { base.ViewDidLoad (); appendButton = new UIButton(new CGRect(10,10, 200, 48)); View.AddSubview(appendButton); } protected override void Dispose(bool disposing) { if (disposing) { if (appendButton != null) { appendButton.Dispose(); appendButton = null; } } base.Dispose(disposing); }
イベントハンドラのメモリリークに注意
イベントハンドラにを使う場合、イベントハンドラの方向や内容によってはメモリリークしてしまいます。 内容とか方向とか考えるの面倒なので、僕は全部ラムダには書かず、全部メソッドにしています。
※ WeakEvent を使うところまではまだたどり着けておらず…あと MVVM フレームワークにお任せできるときはしてしまったほうがいいですね。
// こうせず protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); takeButton.Click += (sender, e) => Debug.WriteLine("Hello"); }
// こうする protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); takeButton.Click += HandleTakeButton; } void HandleTakeButton (object sender, EventArgs e) { Debug.WriteLine("Hello") } protected override void OnDestroy () { base.OnDestroy (); if (_takeBtn != null) { _takeBtn.Click += _takeBtn_Click; _takeBtn.Dispose(); } }