Android 編程時我們少不了使用FindIdByView函數,在Xamarin Android開發時也需要如此。這個工作很無聊且煩人。在常規Android開發中,人們已經發明瞭一些方法免除這項工作,例如Android數據綁定,還有butterknife,都可以解決這個問題。關於它們我不去細說了。 ...
Android 編程時我們少不了使用FindIdByView函數,在Xamarin Android開發時也需要如此。這個工作很無聊且煩人。在常規Android開發中,人們已經發明瞭一些方法免除這項工作,例如Android數據綁定,還有butterknife,都可以解決這個問題。關於它們我不去細說了。但是這兩個方案在Xamarin Android開發里還無法使用。本文介紹一個函數,就可以把程式員從這項工作中解脫出來,原文請參見http://redth.codes/auto-wire-up-views-xamarin-activity/。
下麵直接上代碼吧。
這段是一個Activity.
1 using Android.App; 2 using Android.Widget; 3 using Android.OS; 4 5 namespace AndApp2 6 { 7 [Activity(Label = "AndApp2", MainLauncher = true, Icon = "@drawable/icon")] 8 public class MainActivity : Activity 9 { 10 int count = 1; 11 Button myButton; 12 TextView txtName; 13 14 protected override void OnCreate(Bundle bundle) 15 { 16 base.OnCreate(bundle); 17 this.BindView(Resource.Layout.Main); 18 19 myButton.Click += (s,e)=> { 20 myButton.Text = string.Format("{0} clicks!", count++); 21 txtName.Text = "Bruce"; 22 }; 23 } 24 } 25 }
其中BindView是一個擴展方法,包括SetContent和將View綁定到本Activity的變數上。
Layout中有一個Button myButton和一個TextView txtName.
下麵是BindView擴展方法:
1 public static class ActivityExtensions 2 { 3 public static void BindView(this Activity activity, int layoutResId) 4 { 5 activity.SetContentView(layoutResId); 6 //Get all the View fields from the activity 7 var members = from m in activity.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance) 8 where m.FieldType.IsSubclassOf(typeof(View)) 9 select m; 10 11 if (!members.Any()) 12 return; 13 14 members.ToList().ForEach(m => 15 { 16 try 17 { 18 //Find the android identifier with the same name 19 var id = activity.Resources.GetIdentifier(m.Name, "id", activity.PackageName); 20 //Set the activity field's value to the view with that identifier 21 m.SetValue(activity, activity.FindViewById(id)); 22 } 23 catch (Exception ex) 24 { 25 throw new MissingFieldException("Failed to wire up the field " 26 + m.Name + " to a View in your layout with a corresponding identifier", ex); 27 } 28 }); 29 } 30 }
該方法使用了反射,會有人擔憂其性能。但是對於一個Activity中具有不多的View來說可以忽略不計。
當然,也不是一點問題都沒有。原文已經指出了,如果想使用一個在layout中沒有對應的View時會拋出異常。這個問題其實很好解決。例如,修改一下BindView函數,讓我們約定凡是自動綁定的view變數都以m開頭,其他的變數不以m開頭就好了。當讓我們也可以採取在變數上加註解的方案,這樣也能解決問題,至於具體怎麼弄,就不在這裡說了,到此為止,我覺得現在已經足夠好了。