编辑框架类实现Android以实现向后兼容性

编辑框架类实现Android以实现向后兼容性,android,performance,android-fragments,reflection,android-viewpager,Android,Performance,Android Fragments,Reflection,Android Viewpager,我试图在旧的Android 2.2应用程序中使用ViewPager.PageTransformer接口。我的目标API是8级。但是有一个已知的签入ViewPager compat库类 if (Build.VERSION.SDK_INT >= 11) { final boolean hasTransformer = transformer != null; final boolean needsPopulate = hasTransformer != (mPa

我试图在旧的Android 2.2应用程序中使用ViewPager.PageTransformer接口。我的目标API是8级。但是有一个已知的签入ViewPager compat库类

if (Build.VERSION.SDK_INT >= 11) {
        final boolean hasTransformer = transformer != null;
        final boolean needsPopulate = hasTransformer != (mPageTransformer ....
    }
因此,由于这个检查,PageTransformer在旧的机器人中不起作用,即使有伟大的NineodelDroids库。 我知道有一些解决方案可用,其中之一是更改ViewPager类的默认实现。此外,github上还提供了没有此检查的dafault compat库的fork。 当然,我可以使用这个库,也可以自己修改它,然后使用我的自定义ViewPager类。 但在这种情况下,出现了很多问题。 最重要的是,您不能将此自定义类与其他库(例如ViewPageIndicator)一起使用,因为它们是为默认的ViewPager类创建的。 首先,我想实现什么

我的想法是为我的目的创建一些库和自定义视图,这个自定义视图将包括页面指示器、视图寻呼机和一些其他视图

因此,库的用户不必直接使用ViewPager,它将只使用库中的自定义视图和其他一些类

我有不同的想法如何才能解决这个问题

只需创建自定义ViewPager,使用自定义实现编辑依赖于ViewPager的其他库中的类,即可更改类成员的类型。所以,只需对用户隐藏所有这些肮脏的东西,并允许他使用自定义视图的方法

使用反射。起初,我认为这是一个坏主意,因为它相当昂贵,我也这么认为,但比我在官方Android开发博客上找到的文章要贵。下面是如何使用反射来向后兼容的示例。如果在这种情况下使用反射,我可以简单地重写方法,而不是不调用super,更改部分,但它看起来非常沉重和丑陋。但是我们有一个很大的优势,我们可以在任何需要默认ViewPager的地方使用这个自定义类

也许还有另一个解决这个问题的好方法

但我真正关心的是性能,因为这段代码应该在旧设备上运行,它应该尽可能轻量级

在这种情况下,请建议最好的方法,只需使用默认实现实现库,并对用户隐藏它,或者使用反射并保存与其他类的兼容性

我将感谢任何帮助和建议。
Thx.

首先,我尝试更改ViewPager的默认实现,并在库中使用它。我只是删除了API检查,并开始编写库的其他部分。 很快我就解决了第一个问题,而不是另一个问题。所以我的代码出现了一些奇怪的东西。 在使用自定义ViewPager类的情况下,兼容性将完全中断。 我必须将所有需要的库放在我的项目中,使其与使用默认ViewPager的其他库伪兼容。仅用于更改这些类中的参数和字段

总而言之,我回到了沉思中。这看起来很难看,并假装是一个糟糕的做法,但在这种情况下,我找不到更好的解决方案,如果有,请给出一个例子。 我已经做了一些基准测试,并测量了使用反射和默认方法调用方法所需的时间。 结果是

默认方法第一次的延迟为0,即使是纳秒。但比它最大需要30517纳秒

反射看起来很重。调用此方法需要10000000到50000000纳秒。但更进一步,它会将来自不同服务的错误打印到调试日志中。 下面是此类消息的示例

05-09 22:39:50.995 169-187/?电子/活动管理器﹕ 安纳 com.google.android.gms 原因:执行服务com.google.android.gms/.ice.service.IndexWorkerService 负荷:3.06/3.08/3.0 从5830毫秒到0毫秒前的CPU使用率: 4.1%169/系统\服务器:3%用户+1%内核/故障:158次 0.3%123/adbd:0%用户+0.3%内核/故障:15次 0.3%2137/lib.performancecheck:0.3%用户+0%内核/错误:28次 0%245/tiwlan_wq:0%用户+0%内核 总计6%:3.7%的用户+2.2%的内核 从513ms到1124ms之后的CPU使用率

这种情况并非每次都会发生,但大多数情况下是在应用程序首次启动时发生的,所以使用反射调用方法需要很多时间

@Override
    public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
     Log.d("VIEWPAGER","Inside overridden method Reflection");
        if (Build.VERSION.SDK_INT >= 11) {
            super.setPageTransformer(reverseDrawingOrder, transformer);
        }
        else {
            final boolean hasTransformer = transformer != null;
            Class<?> clazz =this.getClass();
            while(clazz!=null && !clazz.getSimpleName().equals("ViewPager")) {
                clazz = clazz.getSuperclass();
            }
            Log.d("VIEWPAGER", clazz.getSimpleName());
            try {
                Field pageTransformerField = clazz.getDeclaredField("mPageTransformer");
                pageTransformerField.setAccessible(true);
                PageTransformer pageTransformer = (PageTransformer) pageTransformerField.get(this);
                final boolean needsPopulate = hasTransformer != (pageTransformer != null);
                pageTransformerField.set(this, transformer);
                Method drawingOrderMethod = clazz.getDeclaredMethod("setChildrenDrawingOrderEnabledCompat",boolean.class);
                drawingOrderMethod.setAccessible(true);
                drawingOrderMethod.invoke(this,hasTransformer);
                Field drawingOrderField = clazz.getDeclaredField("mDrawingOrder");
                drawingOrderField.setAccessible(true);

                if (hasTransformer) {
                    drawingOrderField.set(this, reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD);
                } else {
                    drawingOrderField.set(this, DRAW_ORDER_DEFAULT);
                }
                if (needsPopulate) {
                    Method populateMethod = clazz.getDeclaredMethod("populate");
                    populateMethod.setAccessible(true);
                    populateMethod.invoke(this);
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

    }
也许这是一个可以接受的解决方案,因为这个方法不会被频繁调用,也许在活动开始时只调用一次,或者根本不调用

我担心这条消息,当然有任何真正的ANR,因为它不应该响应更长的时间。这个信息是否会在将来引起问题,我真的应该在这种情况下消除反思吗?也许有其他方法可以解决这个问题

下面是使用反射的setPageTransformer方法的代码

@Override
    public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
     Log.d("VIEWPAGER","Inside overridden method Reflection");
        if (Build.VERSION.SDK_INT >= 11) {
            super.setPageTransformer(reverseDrawingOrder, transformer);
        }
        else {
            final boolean hasTransformer = transformer != null;
            Class<?> clazz =this.getClass();
            while(clazz!=null && !clazz.getSimpleName().equals("ViewPager")) {
                clazz = clazz.getSuperclass();
            }
            Log.d("VIEWPAGER", clazz.getSimpleName());
            try {
                Field pageTransformerField = clazz.getDeclaredField("mPageTransformer");
                pageTransformerField.setAccessible(true);
                PageTransformer pageTransformer = (PageTransformer) pageTransformerField.get(this);
                final boolean needsPopulate = hasTransformer != (pageTransformer != null);
                pageTransformerField.set(this, transformer);
                Method drawingOrderMethod = clazz.getDeclaredMethod("setChildrenDrawingOrderEnabledCompat",boolean.class);
                drawingOrderMethod.setAccessible(true);
                drawingOrderMethod.invoke(this,hasTransformer);
                Field drawingOrderField = clazz.getDeclaredField("mDrawingOrder");
                drawingOrderField.setAccessible(true);

                if (hasTransformer) {
                    drawingOrderField.set(this, reverseDrawingOrder ? DRAW_ORDER_REVERSE : DRAW_ORDER_FORWARD);
                } else {
                    drawingOrderField.set(this, DRAW_ORDER_DEFAULT);
                }
                if (needsPopulate) {
                    Method populateMethod = clazz.getDeclaredMethod("populate");
                    populateMethod.setAccessible(true);
                    populateMethod.invoke(this);
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

    }