在編寫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 }
下載