Android开发笔记:利用反射获取View

时间:2021-7-9 作者:qvyue

实例一

反射 + 多态: 生成容器实例化并装好 view 子类

简单实现步骤:

两个方法, 一个提供完整包名. 类以及资源所在引用 (android 的话就是 xml 的 id);

另外一个方法就是用反射加上多态实现的装载;

    private List getViewList(List list){
        if(list == null)
            list = new ArrayList();
        String vName[] = {"com.sansui.Memo.MemoView",
                    "com.sansui.Calendar.CalendarView","com.sansui.ClassRoom.ClassRoom"};
        int vNo[] = {R.layout.memoview, R.layout.calendarview , R.layout.classroomview};
        for(int i = 0 ; i 

这里要解释下: 装载在 vNames 的三个类是自定义控件的类, 其最上层父类是 View(类似于 j2se 的 object 吧);

    private View getInstanceView(String className,int resouces){
        XmlPullParser parser = this.getResources().getXml(resouces);
        AttributeSet attributes = Xml.asAttributeSet(parser);
        Object view = null;
        try {
            Class clazz = Class.forName(className);
            Constructor con = clazz.getDeclaredConstructor(Context.class,AttributeSet.class);
            view = con.newInstance(MainView.this,attributes);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }       
        return (View)view;
    }   

再用一个简单的反射装载好了类 (也就是具体类和 xml 的匹配以及实例化),然后再装入 list 容器中

作用就是对于 viewpager 的设置吧, 当时写这个就是这样打算的; 是不是觉得很方便呢? 要是有多个 view 的话就很简单灵活的可以装载了, 而且此类方法复用性相当高;

实例二

通过反射获取控件对象

    @ViewInject(R.id.pull_to_refresh_listview)
    private PullToRefreshListView pullToRefreshListView;
不再使用一下代码初始化

pullToRefreshListView = (PullToRefreshListView) findViewById(R.id.pullToRefreshListView);

实现方式(网上有很多代码):一个 interface 和一个 class

interface

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();
}

class

import android.app.Activity;
import java.lang.reflect.Field;

@SuppressWarnings("unused")
public class ViewInjectClass {
    public static void autoInjectAllField(Activity activity) {
        //得到Activity对应的Class
        Class clazz = activity.getClass();
        //得到该Activity的所有字段
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                //判断字段是否标注InjectView
                if (field.isAnnotationPresent(ViewInject.class)) {
                    //如果标注了,就获得它的id
                    ViewInject inject = field.getAnnotation(ViewInject.class);
                    int id = inject.value();
                    if (id > 0) {
                        //反射访问私有成员,必须加上这句
                        field.setAccessible(true);
                        try {
                            //然后对这个属性复制
                            field.set(activity, activity.findViewById(id));
                        } catch (Exception ex) {
                        }
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
使用方式及建议:
统一写一个BaseActivity
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.anykaalibrary.ViewInjectClass;

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        ViewInjectClass.autoInjectAllField(this);
    }
}

public class MainActivity extends BaseActivity {

    @ViewInject(R.id.pull_to_refresh_listview)
    private PullToRefreshListView pullToRefreshListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }
}

其实我并不建议这样使用,我倒是希望开发工具能够根据类似这种代码,在编译前自动将代码改成
pullToRefreshListView = (PullToRefreshListView) findViewById(R.id.pullToRefreshListView);
这种形式。

Android高级开发系统进阶笔记、最新面试复习笔记PDF,我的GitHub

好了,今天的文章就到这里,感谢阅读,喜欢的话不要忘了三连。大家的支持和认可,是我分享的最大动力。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。