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();
}
}