Java笔记:[反射篇] 利用反射,获取类中的私有内部类对象,并调用该对象的方法

来源:互联网 发布:知金教育好吗 编辑:程序博客网 时间:2024/05/16 07:19

有时候,你会想使用Android自带的某个控件,但发现某些参数需要重新设置,但是并没有暴露出来修改的入口。

这时反射就可以帮上你的忙了~


我们以RecyclerView为例,看看反射的使用方法。

在RecyclerView.java中有这样一个方法smoothScrollBy(int dx,int dy)源码如下:


/** * Animate a scroll by the given amount of pixels along either axis. * * @param dx Pixels to scroll horizontally * @param dy Pixels to scroll vertically */public void smoothScrollBy(int dx, int dy) {    if (mLayout == null) {        Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " +                "Call setLayoutManager with a non-null argument.");        return;    }    if (mLayoutFrozen) {        return;    }    if (!mLayout.canScrollHorizontally()) {        dx = 0;    }    if (!mLayout.canScrollVertically()) {        dy = 0;    }    if (dx != 0 || dy != 0) {        mViewFlinger.smoothScrollBy(dx, dy);    }}

这里有一个私有的mViewFlinger成员对象,该对象是RecyclerView类中的一个私有内部类ViewFlinger的一个实例。

private class ViewFlinger implements Runnable

ViewFlinger有一个方法smoothScrollBy(int dx, int dy, int duration)

public void smoothScrollBy(int dx, int dy, int duration) {    smoothScrollBy(dx, dy, duration, sQuinticInterpolator);}

在RecyclerView的smoothScrollBy(int dx,intdy)中,令mViewFlinger调用自己的smoothScrollBy(int dx, int dy, int duration)方法,duration的值自己设置。目的是可以通过控制duration的值,来控制滚动时间。


下面就是继承RecyclerView重新定义一个方法smoothScrollBy(int dx,int dy, int duration)方法,在方法中利用反射获得RecyclerView的私有属性,并调用属性对象mViewFlinger方法smoothScrollBy(int dx, int dy, int duration)

请注意代码中的注释,跟关键哦~

    public void smoothScrollBy(int dx, int dy, int duration) {        try {            Class<?> c = null;            try {                c = Class.forName("android.support.v7.widget.RecyclerView");//获得Class对象            } catch (ClassNotFoundException e) {                e.printStackTrace();                return;            }            /**             * 对应代码             * if (mLayout == null) {             *      Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " +             *          "Call setLayoutManager with a non-null argument.");             *      return;             * }             */            Field mLayoutField = c.getDeclaredField("mLayout");//根据属性名称,获得类的属性成员Field            mLayoutField.setAccessible(true);//设置为可访问状态            LayoutManager mLayout = null;            try {                mLayout = (LayoutManager) mLayoutField.get(this);//获得该属性对应的对象                if(mLayout == null){                    return;                }            } catch (IllegalAccessException e) {                e.printStackTrace();                return;            }            /**             * 对应代码             * if (mLayoutFrozen) {             *      return;             * }             */            Field mLayoutFrozen = c.getDeclaredField("mLayoutFrozen");            mLayoutFrozen.setAccessible(true);            try {                if((Boolean)mLayoutFrozen.get(this)){                    return;                }            } catch (IllegalAccessException e) {                e.printStackTrace();                return;            }            /**             * 对应代码             * if (!mLayout.canScrollHorizontally()) {             *      dx = 0;             * }             */            if (!mLayout.canScrollHorizontally()) {                dx = 0;            }            /**             * 对应代码             * if (!mLayout.canScrollVertically()) {             *      dy = 0;             * }             */            if (!mLayout.canScrollVertically()) {                dy = 0;            }            /**             * 对应代码             * if (dx != 0 || dy != 0) {             *      mViewFlinger.smoothScrollBy(dx, dy);             * }             * 此处调用mViewFlinger.smoothScrollBy(dx, dy, duration);这是我们的目的。             */            Field mViewFlingerField = c.getDeclaredField("mViewFlinger");            mViewFlingerField.setAccessible(true);            try {                Class<?> ViewFlingerClass = null;                try {                    //由于内部类是私有的,所以不能直接得到内部类名,                    //通过mViewFlingerField.getType().getName()                    //可以得到私有内部类的完整类名                    ViewFlingerClass = Class.forName(mViewFlingerField.getType().getName());                } catch (ClassNotFoundException e) {                    e.printStackTrace();                    return;                }                //根据方法名,获得我们的目标方法对象。第一个参数是方法名,后面的是该方法的入参类型。                // 注意Integer.class与int.class的不同。                Method smoothScrollBy = ViewFlingerClass.getDeclaredMethod("smoothScrollBy",                        int.class, int.class, int.class);                smoothScrollBy.setAccessible(true);//设置为可操作状态                if (dx != 0 || dy != 0) {                    Log.d("MySmoothScrollBy", "dx="+dx + " dy="+dy);                    try {                        //唤醒(调用)方法,                        // mViewFlingerField.get(this)指明是哪个对象调用smoothScrollBy。                        // dx, dy, duration 是smoothScrollBy所需参数                        smoothScrollBy.invoke(mViewFlingerField.get(this), dx, dy, duration);                    } catch (IllegalAccessException e) {                        e.printStackTrace();                    } catch (InvocationTargetException e) {                        e.printStackTrace();                    }                }            } catch (NoSuchMethodException e) {                e.printStackTrace();                return;            }        }catch (NoSuchFieldException e){;            return;        }    }

大功告成,睡觉!





1 0
原创粉丝点击