在編寫Android應用的時候經常需要做的事情就是對View的資料進行設定,在Android下設定控制元件相對.net來說是件麻煩的事情,首先根據ID從view把控制元件找出來然後才能設定相應屬性值;如果資料成員多那這些工作的是繁鎖的事情。下面通過java提供的reflect的功能實現資料自動繫結功能。
在實現之前先描述一下實現的功能效果。
傳統方式:
1 EditText editor = (EditText)v.findViewById(R.id.orders_orderid); 2 editor.setText(item.getOrderID()); 3 editor =(EditText)v.findViewById(R.id.orders_employee); 4 editor.setText(item.getEmployee()); 5 editor=(EditText)v.findViewById(R.id.orders_customer); 6 editor.setText(item.getCustomer()); 7 editor =(EditText)v.findViewById(R.id.orders_orderdate); 8 editor.setText(item.getOrderDate()); 9 editor =(EditText)v.findViewById(R.id.orders_requireddate); 10 editor.setText(item.getRequiredDate()); 11 editor=(EditText)v.findViewById(R.id.orders_shipaddress); 12 editor.setText(item.getShipAddress()); 13 editor =(EditText)v.findViewById(R.id.orders_shipcity); 14 editor.setText(item.getShipCity()); 15 editor=(EditText)v.findViewById(R.id.orders_shipname); 16 editor.setText(item.getShipName()); 17 editor =(EditText)v.findViewById(R.id.orders_shippedDate); 18 editor.setText(item.getShippedDate()); 19 editor =(EditText)v.findViewById(R.id.orders_shipregion); 20 editor.setText(item.getShipRegion());
資料繫結方式:
1 orderproto.Order item = mOrders.get(position); 2 Binding binder = BindingFactory.GetBindig("order_list_view", v); 3 binder.Execute(v, item);
資料繫結描述
下面詳細講解實現方式,為了達到資料繫結功能首先要有一個資訊描述;由於接觸android不久所以暫不清楚如何給控制元件新增一些自定義的XML描述,所以直接採用了ContentDescription這個屬性來完成繫結描述的工作。約定繫結表示式為"bind:member".
當有了繫結描述資訊後要做的事情就是找出容器中有那些控制元件存在繫結描述和對應的繫結的屬性。
1 private void findChild(View view) { 2 ViewGroup bg = null; 3 View nextChild = null; 4 if (view instanceof ViewGroup) 5 bg = (ViewGroup) view; 6 if (bg != null) { 7 for (int i = 0; i < bg.getChildCount(); ++i) { 8 nextChild = bg.getChildAt(i); 9 if (nextChild instanceof ViewGroup) { 10 findChild(nextChild); 11 } else { 12 13 CharSequence cs = nextChild.getContentDescription(); 14 String bindinfo = null; 15 if (cs != null) 16 bindinfo = nextChild.getContentDescription().toString(); 17 if (bindinfo != null && bindinfo.indexOf("bind:") == 0) { 18 String member = bindinfo.split(":")[1]; 19 mControls 20 .add(new Control(nextChild.getId(), 21 new ControlHandler( 22 nextChild.getClass(), member))); 23 24 } 25 } 26 27 } 28 } 29 }
實現程式碼並不複雜,遞迴的方式尋找控制元件如果存在繫結資訊的情況下新增了繫結列表中。
資料繫結介面
由於資料輸出控制元件是不固定的,因此需要制定一個繫結介面;具體控制元件繫結就通過實現該介面來處理具體的工作。
1 public interface IControlDataBinder { 2 void SetValue(View e,Object value,String format); 3 Object GetValue(View e); 4 }
TextView的實現
1 public class TextViewDataBinder implements IControlDataBinder { 2 3 @Override 4 public void SetValue(View e, Object value, String format) { 5 // TODO Auto-generated method stub 6 TextView control=(TextView)e; 7 if(format==null || format.equals("")) 8 { 9 control.setText(value.toString()); 10 } 11 else 12 { 13 control.setText(String.format(format, value)); 14 } 15 } 16 17 @Override 18 public Object GetValue(View e) { 19 // TODO Auto-generated method stub 20 TextView control=(TextView)e; 21 return control.getText().toString(); 22 } 23 24 }
EditText的實現
1 public class EditTextDataBinder implements IControlDataBinder { 2 3 @Override 4 public void SetValue(View e, Object value, String format) { 5 // TODO Auto-generated method stub 6 EditText control=(EditText)e; 7 if(format==null || format.equals("")) 8 { 9 control.setText(value.toString()); 10 } 11 else 12 { 13 control.setText(String.format(format, value)); 14 } 15 } 16 17 @Override 18 public Object GetValue(View e) { 19 // TODO Auto-generated method stub 20 EditText control=(EditText)e; 21 return control.getText().toString(); 22 } 23 24 }
對於其它控制元件則根據自己需要來實現。
物件資料獲取
在java似乎不存在象c#那樣的屬性,要麼是Field或方法。所以通過名稱來得到繫結資訊就要做一些簡單的處理,如果Field不儲存則要檢索一下對應的get方法。
1 public MemberInvoke(Class<?> type,String name) 2 { 3 try 4 { 5 mField = type.getField(name); 6 mIsMethod= false; 7 mInvalid = false; 8 } 9 catch(Exception e) 10 { 11 12 } 13 if(mInvalid) 14 { 15 try 16 { 17 mGetMethod = type.getMethod("get"+name); 18 mIsMethod= true; 19 mInvalid = false; 20 } 21 catch(Exception e) 22 { 23 24 } 25 } 26 }
資料繫結的具體工作
通過名稱找到對應的Binding物件,所以名稱和View在使用的時候必須保持一致。
1 private static HashMap<String, Binding> mBindingTbl = new HashMap<String, Binding>(); 2 public static Binding GetBindig(String name,View view) 3 { 4 Binding result = null; 5 result = mBindingTbl.get(name); 6 if(result ==null) 7 { 8 result = new Binding(view); 9 mBindingTbl.put(name, result); 10 } 11 return result; 12 }
找到相應Binding物件後直接處理所有需要繫結的控制元件即可。
1 public void Execute(View view, Object source) { 2 try { 3 for (Control item : mControls) { 4 item.Handler.ToControl(view.findViewById(item.ID), source); 5 } 6 } catch (Exception e) { 7 8 } 9 }
下載