Android 初始化滚动条未定义? 背景

Android 初始化滚动条未定义? 背景,android,android-5.0-lollipop,Android,Android 5.0 Lollipop,我使用它作为它的一个类(从ViewGroup扩展而来),在“PLA_AbsListView.java”中,在CTOR内部,有以下几行: final TypedArray a = context.obtainStyledAttributes(R.styleable.View); initializeScrollbars(a); a.recycle(); 最近,我更新了Android的SDK和ADT,以支持新的Android版本(棒棒糖-API21) 问题 自从我更新了所有

我使用它作为它的一个类(从ViewGroup扩展而来),在“PLA_AbsListView.java”中,在CTOR内部,有以下几行:

    final TypedArray a = context.obtainStyledAttributes(R.styleable.View);
    initializeScrollbars(a);
    a.recycle();
最近,我更新了Android的SDK和ADT,以支持新的Android版本(棒棒糖-API21)

问题 自从我更新了所有内容后,我一直遇到以下错误:

类型PLA_AbsListView的方法initializeScrollbars(TypedArray)未定义

我试过的 我尝试将API设置为低于21,但没有帮助

我还试图找出这个函数的声明位置。它应该是“View.java”中的一个受保护函数,但由于某些原因,我无法在中看到它

问题 怎么可能呢

我怎样才能修好它

有可能是文档中的错误吗


以前,当从android-21的
View.java
中瞄准Kitkat…

时,它起到了作用

/**
 * ...
 *
 * @removed
 */
protected void initializeScrollbars(TypedArray a) {
    // It's not safe to use this method from apps. The parameter 'a' must have been obtained
    // using the View filter array which is not available to the SDK. As such, internal
    // framework usage now uses initializeScrollbarsInternal and we grab a default
    // TypedArray with the right filter instead here.
    TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);

    initializeScrollbarsInternal(arr);

    // We ignored the method parameter. Recycle the one we actually did use.
    arr.recycle();
}

/**
 * ...
 *
 * @hide
 */
protected void initializeScrollbarsInternal(TypedArray a) {
您看不到它,因为该方法是用
@removed
注释的
initializeScrollbarsInternal()
也不能使用,因为它是用
@hide
注释的。
从评论来看,使用这种方法不安全,你应该明确地向lib的作者报告。

正如@biegleux在他的回答中提到的,
initializeScrollbars()
现在在API 21源代码中被注释为
@removed
。以下是API 21中的方法源:

protected void initializeScrollbars(TypedArray a) {
    // It's not safe to use this method from apps. The parameter 'a' must have been obtained 
    // using the View filter array which is not available to the SDK. As such, internal 
    // framework usage now uses initializeScrollbarsInternal and we grab a default 
    // TypedArray with the right filter instead here. 
    TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);

    initializeScrollbarsInternal(arr);

    // We ignored the method parameter. Recycle the one we actually did use. 
    arr.recycle();
}
根据方法中的注释,API 21之前的问题似乎是传入
TypedArray
不安全,但现在它不再使用传入的
TypedArray
。因此,似乎应该使用
@Deprecated
而不是
@removed
对该方法进行注释,并且应该有一个新版本的该方法,当我们需要从以编程方式创建的自定义视图中初始化滚动条时,不需要调用任何参数

在解决此问题之前,有两种方法可以解决此问题:

1) 使用
android:scrollbars
属性集从xml扩展自定义视图。这是最安全的方法,应该适用于所有过去和将来的平台版本。例如:

创建xml布局文件(
my\u custom\u view.xml
):

2) 使用反射在自定义视图的构造函数中调用
initializeScrollbars()
。如果方法
initializeScrollbars()
实际被删除或重命名,则在将来的API版本中,此操作可能会失败。例如:

在自定义视图中(例如,
MyCustomView.java
):


+1.我将sdk改回API 19进行检查,并在那里定义。它已被删除,没有解释。奇怪。@rockgecko所以也许我应该报告这件事?@rockgecko好的,我已经在这里报告过了:这样的东西怎么能被移除?如果删除该调用,它在以前的版本中如何工作?你会因为它而对以前的版本使用反射吗?如果调用同一API不是一件安全的事情,那么库的早期版本如何能够在同一API上工作?如果它不安全,为什么不删除里面的代码呢?我只是不明白…问题是lib在获取保存属性值的
TypedArray
时使用
R.styleable.View
。相反,它应该使用
com.android.internal.R.styleable.View
,但它是内部的,不能从SDK访问。我能猜到的问题是什么,可能是它导致了一些泄漏或不正确的样式。我建议您从库中删除
initializeScrollbars()
,并通过定义
R.styleable.View\u scrollbars
attr将其放在
View
类中,该属性不是内部的。查看
View.java的源代码,我已经删除了它,但我希望它不会在旧版本和新版本的Android上造成任何问题。你是说它已经通过CTOR初始化了?如果是这样的话,以前版本的Android也是这样吗?我想知道为什么会添加它……不,它不是通过ctor初始化的,但是如果您能够使用另外两个ctor中的一个,那么如果您将
滚动条设置为
垂直
,它应该可以。或者您可以检查它是否可以帮助您,它直接继承自
AbsListView
,而不创建自己的实现。
<com.example.MyCustomView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="horizontal|vertical"/>
MyCustomView view = (MyCustomView) LayoutInflater.from(context).inflate(R.layout.my_custom_view, container, false);
public MyCustomView(Context context) {
    super(context);

    // Need to manually call initializedScrollbars() if instantiating view programmatically
    final TypedArray a = context.getTheme().obtainStyledAttributes(new int[0]);
    try {
        // initializeScrollbars(TypedArray)
        Method initializeScrollbars = android.view.View.class.getDeclaredMethod("initializeScrollbars", TypedArray.class);
        initializeScrollbars.invoke(this, a);
    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
        e.printStackTrace();
    }
    a.recycle();
}