• android使用篇(四) 注解依赖注入IOC实现绑定控件


    android使用篇(三) MVC模式中提到一个问题:

    1) 视图层(View):一般採用XML文件进行界面的描写叙述,使用的时候能够很方便的引入,可是用xml编写了,又须要在Acitvity声明而且实例化,有点麻烦,考虑是否能做一个类似注解实现匹配,或者写一个类获取xml的各个节点然后自己主动进行封装,当然,这仅仅是个想法,以后再实现。

    今天最终把这个想法实现了,使用依赖注入IOC注解实现对activity中控件的实例化。

    先普及一下java的反射机制和注解机制的知识:

    下面引用大神的两篇文章:

    JAVA反射机制  


    java 注解 

    完毕后仅仅须要: @ViewInject(id=R.id.btn1,click="btnClick") TextView btn1;  就可以完毕实例化,并加入�点击事件

    基本思路: 

    一,public abstract class D3Activity extends Activity    写一个类继承Activity。

    二,重写  setContentView   在此方法实现注解。

    三,Field[] fields = activity.getClass().getDeclaredFields();    获取activity中的字段属性

    四, field.getAnnotation(ViewInject.class);         获取字段的注解属性

    五, field.set(activity,sourceView.findViewById(viewId));       实例化控件

    大功告成,到此已实现了注解实现对android中activity和xml文件的实例化问题。

    另外也能够实现注解对控件的事件加入�,具体


    分三个类实现:

    实现注解类:

    注解类可注入 id---相应xml的id,各种点击事件,可自定义

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME) 
    public @interface D3View {
     public int id() default 0;
     public String click() default "";
     public String longClick() default "";
     public String itemClick() default "";
     public String itemLongClick() default "";
    }


    重写activity类,使用反射和注解实现实例化并添�事件:

    public abstract class D3Activity extends Activity {

     public void setContentView(int layoutResID) {   super.setContentView(layoutResID);   initInjectedView(this);  }

     public void setContentView(View view, LayoutParams params) {   super.setContentView(view, params);   initInjectedView(this);  }

     public void setContentView(View view) {   super.setContentView(view);   initInjectedView(this);  }  

     private void initInjectedView(Activity activity){   initInjectedView(activity, activity.getWindow().getDecorView());  }      private void initInjectedView(Object activity,View sourceView){   Field[] fields = activity.getClass().getDeclaredFields();   //获取字段   if(fields!=null && fields.length>0){    for(Field field : fields){     try {      field.setAccessible(true);   //设为可訪问            if(field.get(activity)!= null )       continue;           D3View d3View = field.getAnnotation(D3View.class);      if(d3View!=null){              int viewId = d3View.id();       if(viewId == 0)        viewId = getResources().getIdentifier(field.getName(), "id",getPackageName());       if(viewId == 0)        Log.e("D3Activity", "field "+ field.getName() + "not found");              //关键,注解初始化,相当于 backBtn = (TextView) findViewById(R.id.back_btn);          field.set(activity,sourceView.findViewById(viewId));           //事件          setListener(activity,field,d3View.click(),Method.Click);       setListener(activity,field,d3View.longClick(),Method.LongClick);       setListener(activity,field,d3View.itemClick(),Method.ItemClick);       setListener(activity,field,d3View.itemLongClick(),Method.itemLongClick);      }     } catch (Exception e) {      e.printStackTrace();     }    }   }  }    private void setListener(Object activity,Field field,String methodName,Method method)throws Exception{   if(methodName == null || methodName.trim().length() == 0)    return;      Object obj = field.get(activity);      switch (method) {    case Click:     if(obj instanceof View){      ((View)obj).setOnClickListener(new EventListener(activity).click(methodName));     }     break;    case ItemClick:     if(obj instanceof AbsListView){      ((AbsListView)obj).setOnItemClickListener(new EventListener(activity).itemClick(methodName));     }     break;    case LongClick:     if(obj instanceof View){      ((View)obj).setOnLongClickListener(new EventListener(activity).longClick(methodName));     }     break;    case itemLongClick:     if(obj instanceof AbsListView){      ((AbsListView)obj).setOnItemLongClickListener(new EventListener(activity).itemLongClick(methodName));     }     break;    default:     break;   }  }    public enum Method{   Click,LongClick,ItemClick,itemLongClick  }   }


    事件类: 实现了 OnClickListener, OnLongClickListener, OnItemClickListener,OnItemLongClickListener ,能够自己扩展

    public class EventListener implements OnClickListener, OnLongClickListener, OnItemClickListener,OnItemLongClickListener {
    
    	private Object handler;
    	
    	private String clickMethod;
    	private String longClickMethod;
    	private String itemClickMethod;
    	private String itemLongClickMehtod;
    	
    	public EventListener(Object handler) {
    		this.handler = handler;
    	}
    	
    	public EventListener click(String method){
    		this.clickMethod = method;
    		return this;
    	}
    	
    	public EventListener longClick(String method){
    		this.longClickMethod = method;
    		return this;
    	}
    	
    	public EventListener itemLongClick(String method){
    		this.itemLongClickMehtod = method;
    		return this;
    	}
    	
    	public EventListener itemClick(String method){
    		this.itemClickMethod = method;
    		return this;
    	}
    	
    	public boolean onLongClick(View v) {
    		return invokeLongClickMethod(handler,longClickMethod,v);
    	}
    	
    	public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
    		return invokeItemLongClickMethod(handler,itemLongClickMehtod,arg0,arg1,arg2,arg3);
    	}
    	
    	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
    		
    		invokeItemClickMethod(handler,itemClickMethod,arg0,arg1,arg2,arg3);
    	}
    	
    	public void onClick(View v) {
    		
    		invokeClickMethod(handler, clickMethod, v);
    	}
    	
    	
    	private static Object invokeClickMethod(Object handler, String methodName,  Object... params){
    		if(handler == null) return null;
    		Method method = null;
    		try{   
    			method = handler.getClass().getDeclaredMethod(methodName,View.class);
    			if(method!=null)
    				return method.invoke(handler, params);	
    			else
    				throw new RuntimeException("no such method:"+methodName);
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		
    		return null;
    		
    	}
    	
    	
    	private static boolean invokeLongClickMethod(Object handler, String methodName,  Object... params){
    		if(handler == null) return false;
    		Method method = null;
    		try{   
    			//public boolean onLongClick(View v)
    			method = handler.getClass().getDeclaredMethod(methodName,View.class);
    			if(method!=null){
    				Object obj = method.invoke(handler, params);
    				return obj==null?false:Boolean.valueOf(obj.toString());	
    			}
    			else
    				throw new RuntimeException("no such method:"+methodName);
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		
    		return false;
    		
    	}
    	
    	
    	
    	private static Object invokeItemClickMethod(Object handler, String methodName,  Object... params){
    		if(handler == null) return null;
    		Method method = null;
    		try{   
    			///onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
    			method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);
    			if(method!=null)
    				return method.invoke(handler, params);	
    			else
    				throw new RuntimeException("no such method:"+methodName);
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		
    		return null;
    	}
    	
    	
    	private static boolean invokeItemLongClickMethod(Object handler, String methodName,  Object... params){
    		if(handler == null) throw new RuntimeException("invokeItemLongClickMethod: handler is null :");
    		Method method = null;
    		try{   
    			///onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,long arg3)
    			method = handler.getClass().getDeclaredMethod(methodName,AdapterView.class,View.class,int.class,long.class);
    			if(method!=null){
    				Object obj = method.invoke(handler, params);
    				return Boolean.valueOf(obj==null?false:Boolean.valueOf(obj.toString()));	
    			}
    			else
    				throw new RuntimeException("no such method:"+methodName);
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    		
    		return false;
    	}
    }


    到此已经完毕了,仅仅须要这样就可以实例化:

    public class MainActivity extends D3Activity {
        
    	//@ViewInject EditText input;   //id和属性名同样,自己主动匹配
    	@ViewInject(id = R.id.input) EditText editText;     
    	@ViewInject(click="btnClick") TextView btn1,btn2,btn3;
    	
        public void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
        }  
    
    	public void btnClick(View v){
        	
        	switch (v.getId()) {
    		case R.id.btn1:
    			btn1.setText(editText.getText().toString());
    			Toast.makeText(getApplicationContext(), "111", Toast.LENGTH_SHORT).show();
    			break;
    		
    		case R.id.btn2:
    			Toast.makeText(getApplicationContext(), "222", Toast.LENGTH_SHORT).show();
    
    			break;
    			
    		case R.id.btn3:
    			Toast.makeText(getApplicationContext(), "333", Toast.LENGTH_SHORT).show();
    			break;
    
    		default:
    			break;
    		}
        	
        }
        
    }

    相应xml布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        
        <EditText 
            android:id="@+id/input"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            
            />
        <TextView
            android:id="@+id/btn1"
            android:layout_marginTop="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="设置自己"
             />
    	<TextView 
            android:id="@+id/btn2"
            android:layout_marginTop="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="btn2"
    	    />
    	
    	
    	<TextView 
            android:id="@+id/btn3"
            android:layout_marginTop="10dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="btn3"
    	    />
    </LinearLayout>
    


    源代码已经放在了github,有兴趣的能够去看看 :https://github.com/mozhenhau/injectAndroid.git


  • 相关阅读:
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Visual Studio断点调试, 无法监视变量, 提示无法计算表达式
    ASP.NET MVC中MaxLength特性设置无效
    项目从.NET 4.5迁移到.NET 4.0遇到的问题
    发布网站时应该把debug设置false
    什么时候用var关键字
    扩展方法略好于帮助方法
    在基类构造器中调用虚方法需谨慎
    ASP.NET MVC中商品模块小样
    ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/3952135.html
Copyright © 2020-2023  润新知