昨天介绍了一下在activity中初始化控件用注解的方式实现。其实注解就是利用的java反射机制在编译好的class文件字节码通过放射获取到的。但是这只是activity中,在android 任何一个类中需要绑定view需要初始化控件怎么办呢。所以这时候就需要动动脑筋了。想想就把activity 换成Object不就行了吗?废话少说,代码敲起来。
package com.jxust.eddie.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
int value();
int parentId() default 0;
}
跟上篇文章一样。定义了一个注解类。
package com.jxust.eddie.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value();
}
今儿又稍稍加了另外一个注解,需要注意的是@Target元注解的类型是ElmentType.TYPE。表明本人定义的是一个类注解,比如struts2中的@controller。
下面写了一个辅助类ViewFinder。
package com.jxust.eddie.annotation;
import android.app.Activity;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.view.View;
/**
* Author: Eddie
*/
public class ViewFinder {
private View view;
private Activity activity;
public ViewFinder(View view) {
this.view = view;
}
public ViewFinder(Activity activity) {
this.activity = activity;
}
public View findViewById(int id) {
return activity == null ? view.findViewById(id) : activity.findViewById(id);
}
public View findViewById(int id, int pid) {
View pView = null;
if (pid > 0) {
pView = this.findViewById(pid);
}
View view = null;
if (pView != null) {
view = pView.findViewById(id);
} else {
view = this.findViewById(id);
}
return view;
}
}
下面最重要的环节就要出现了,那就是注解解析了。
package com.jxust.eddie.annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.app.Activity;
import android.view.View;
/**
*
* @author Eddie
*
*/
public class ViewUtils {
public static void inject(Object handler,View view) {
injectObject(handler, new ViewFinder(view));
}
public static void inject(Activity activity) {
injectObject(activity, new ViewFinder(activity));
}
/**
* 我的理解是java反射机制中获取类handlerType中的方法
* @author Eddie
* @param String name 这个是方法名
* @param Class<?> parameterType 这个是方法对应的参数类型
* @description
*/
public static void injectObject(Object handler, ViewFinder finder) {
Class<?> handlerType = handler.getClass();
//实现类注解 绑定view
ContentView contentView = handlerType.getAnnotation(ContentView.class);
if (contentView != null) {
try {
Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);
setContentViewMethod.invoke(handler, contentView.value());
} catch (Throwable e) {
}
}
Field[] fields = handlerType.getDeclaredFields();
if (fields != null && fields.length > 0) {
for (Field field : fields) {
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if (viewInject != null) {
try {
View view = finder.findViewById(viewInject.value(),
viewInject.parentId());
if (view != null) {
field.setAccessible(true);
field.set(handler, view);
}
} catch (Throwable e) {
}
}
}
}
}
}
好了,注解介绍完了。开用。
import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import com.jxust.eddie.adapter.MainFragmentAdapter;
import com.jxust.eddie.annotation.ContentView;
import com.jxust.eddie.annotation.ViewInject;
import com.jxust.eddie.annotation.ViewUtils;
import com.jxust.eddie.redtourism.fragment.FindFragment;
import com.jxust.eddie.redtourism.fragment.HomeFragment;
import com.jxust.eddie.redtourism.fragment.MeFragment;
import com.jxust.eddie.redtourism.fragment.TripFragment;
@ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity implements OnClickListener{
private static final String TAG = "MainActivity";
private static final int FOOT_HOME = 0;
private static final int FOOT_TRIP = 1;
private static final int FOOT_FIND = 2;
private static final int FOOT_ME = 3;
@ViewInject(R.id.id_viewpager)
private ViewPager mViewPager;
@Override
public void initView() {
ViewUtils.inject(this);