做android有时候很痛苦的是一件还没技术含量的活但又必须不得不干,比如:
setContentView(R.layout.activity_main);
btn_select_all = (Button) findViewById(R.id.btn_select_all);
像这种findViewById每个activity必写,而又对技术提高没任何好处,于是后来进化了一点,变成了这样:
private T $(int viewId) {
return (T) findViewById(viewId);
}
这一般放在BaseActivity上,但是这样也挺麻烦的,就像科技的发展是让人越来越省事,越来越方面,框架的出现也是让你开发更加专注你的业务,IOC概念:
让调用类对某一接口实现类的依赖关系由第三方(容器类和协作类)注入
不管是setContentView()和findViewById()都是Activity中的方法,如果我写一个工具类把这个Activity传递进去,这些findViewById()方法放在这个工具类上,这样Activity中就不用findViewById()了,但是xml中的id怎么办呢?所以这个就行不通啊,既然这样的话,能不能通过反射这个Activity然后获取所有的变量,那么这个id怎么传递进去呢?突然想到了,用注解啊,我们只要把这个id写在View上面的注解上不就ok么?所以IOC框架用到的主要技术就是反射和注解.其实很简单,可能听到框架二个词,让你懵逼,没那必要.
今天就讲下setContentView()和findViewById()方法怎么通过IOC框架实现:
ContentViewJect.java(注解)
package com.ioc.annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ContentViewJect {
int value();
}
ViewJect.java(View的注解)
package com.ioc.annotion;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ViewInject {
int value();
}
InjectUtils.java
package com.ioc;
import android.content.Context;
import android.view.View;
import com.ioc.annotion.ContentViewJect;
import com.ioc.annotion.ViewInject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* ioc容器框架
*/
public class InjectUtils {
public static final String TAG = "InjectUtils";
public static void inject(Context context)
{
injectLayout(context);
injectView(context);
}
/**
* Activity中的findViewById()方法
* @param context
*/
public static void injectView(Context context)
{
if(context!=null){
Class> clazz=context.getClass();
Field[] fields=clazz.getDeclaredFields();
for (Field field:fields)
{
ViewInject viewInject=field.getAnnotation(ViewInject.class);
if(viewInject!=null)
{
int valueId=viewInject.value();//获取view的id
try {
Method method=clazz.getMethod("findViewById",int.class);
View view= (View) method.invoke(context,valueId);
field.setAccessible(true);
field.set(context,view);//field 表示tv
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
/**
* Activity中的setContentView()方法
* @param context
*/
public static void injectLayout(Context context)
{
if(context!=null){
int layoutId=0;
Class> clazz=context.getClass();
ContentViewJect contentView=clazz.getAnnotation(ContentViewJect.class);
if (contentView != null ) {
layoutId=contentView.value();
try {
Method method=clazz.getMethod("setContentView",int.class);
method.invoke(context,layoutId);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
这个一般都是写在一个BaseActivity的onCreate()方法中把ioc初始哈
BaseActivity.java
package com.ioc;
import android.app.Activity;
import android.os.Bundle;
public class BaseActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InjectUtils.inject(this);
}
}
MainActivity.java
package com.ioc;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.ioc.annotion.ContentViewJect;
import com.ioc.annotion.ViewInject;
@ContentViewJect(R.layout.activity_main)
public class MainActivity extends BaseActivity{
public static final String TAG="dongnao";
@ViewInject(R.id.text)
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv.setText("zhouguizhi_ioc");
}
}
如图所示:
IOC缺点的话,用到反射会影响点性能!