昨天介绍了一下在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);