gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 14:09:42 25 4
gpt4 key购买 nike

我正在尝试在旧的 Android 2.2 应用程序中使用 ViewPager.PageTransformer 界面。我的目标 API 是 8 级。但是在 ViewPager compat library class

中有已知的检查
if (Build.VERSION.SDK_INT >= 11) {
final boolean hasTransformer = transformer != null;
final boolean needsPopulate = hasTransformer != (mPageTransformer ....
}

因为这个检查 PageTransformer 在旧的 Android 中不起作用,即使有很棒的 NineOldAndroids 库也是如此。
我知道有一些可用的解决方案,其中之一是更改 ViewPager 类的默认实现。此外,github 上提供了不带此检查的 dafault compat 库的分支。
当然,我可以使用这个库,或者自己更改它并使用我自定义的 ViewPager 类。
但是在这种情况下出现了很多问题。
最重要的是,您不能将此自定义类与其他库一起使用,例如 ViewPageIndicator,因为它们是为默认的 ViewPager 类创建的。
首先,我想实现什么?

我的想法是为我的目的创建一些库和自定义 View ,这个自定义 View 将包括页面指示器、 View 分页器和一些其他 View 。

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

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

  1. 只需创建自定义 ViewPager ,使用我的自定义实现从依赖于 ViewPager 的其他库编辑类,只是为了更改类成员的类型。因此,只需向用户隐藏所有这些肮脏的东西,并允许他使用自定义 View 的方法。

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

也许还有另一种好方法可以解决这个问题。

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

请建议在这种情况下遵循的最佳方法,只需使用默认实现实现我想做的任何事情的库,并使其对用户隐藏或使用反射并保存与其他类的兼容性。

如果有任何帮助和建议,我将不胜感激。谢谢。

最佳答案

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

总而言之,我回到了反射(reflection)。它看起来非常丑陋并且假装是一种不好的做法,但在这种情况下我找不到更好的解决方案(如果有请举个例子)。
我已经完成了一些基准测试,并测量了使用反射和默认方法调用方法所需的时间。
结果是。

  1. 默认方法第一次的延迟为 0(甚至以纳秒为单位)。但它最多花费 30517ns

  2. 反射看起来很重。调用此方法需要 10000000 到 50000000 ns。但此外,它将来自某些(不同)服务的 ANR 错误打印到调试日志中。这是此类消息的示例。

05-09 22:39:50.995 169-187/? E/ActivityManager﹕ ANR in com.google.android.gms Reason: Executing service com.google.android.gms/.icing.service.IndexWorkerService Load: 3.06 / 3.08 / 3.0 CPU usage from 5830ms to 0ms ago: 4.1% 169/system_server: 3% user + 1% kernel / faults: 158 minor 0.3% 123/adbd: 0% user + 0.3% kernel / faults: 15 minor 0.3% 2137/lib.performancecheck: 0.3% user + 0% kernel / faults: 28 minor 0% 245/tiwlan_wq: 0% user + 0% kernel 6% TOTAL: 3.7% user + 2.2% kernel CPU usage from 513ms to 1124ms later.......

这种情况不是每次都会发生,但主要是在应用程序首次启动时发生,因此使用反射调用方法需要花费很多时间。

就此方法不会被频繁调用而言,也许这是可以接受的解决方案,可能只在 Activity 开始时调用一次,或者根本不调用?

我担心这条消息,有任何真正的 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();
}
}

}

关于android - 编辑框架类实现 Android 以实现向后兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30019326/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com