问题
Background
I'm using this library which for one of its classes (that extends from ViewGroup), in "PLA_AbsListView.java", inside the CTOR, there are those lines:
final TypedArray a = context.obtainStyledAttributes(R.styleable.View);
initializeScrollbars(a);
a.recycle();
Recently, I've updated the SDK & ADT of Android to support the new Android version (Lollipop - API21) .
The problem
Ever since I've updated everything, I keep getting this error:
The method initializeScrollbars(TypedArray) is undefined for the type PLA_AbsListView
What I've tried
I've tried to set the API to be used as lower than 21, but it didn't help.
I've also tried to find out where this function is declared. It's supposed to be a protected function within "View.java", but for some reason, I can't see it in the documentations
The question
How could it be?
How can I fix it?
Is it possible it's a bug in the documentation?
It worked before, when targeting Kitkat...
回答1:
from View.java
of android-21
sources:
/**
* ...
*
* @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) {
You don't see it because the method is annotated with @removed
. initializeScrollbarsInternal()
also cannot be used as it is annotated with @hide
.
As from the comment it's not safe to use this method, you should definitely report it to the author of the lib.
回答2:
As @biegleux mentioned in his answer, initializeScrollbars()
is now annotated with @removed
in the API 21 source code. Here is the method source from 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();
}
Based on the comment in the method, it sounds like the issue before API 21 was that it was not safe to pass in a TypedArray
, but now it no longer uses the passed in TypedArray
. So it seems like this should be annotated with @Deprecated
instead of @removed
and there should be a new version of this method that takes no parameter that can be called when we need to initialize the scrollbars from a custom view that's created programmatically.
Until this gets fixed, there's two ways you can work around the issue:
1) Inflate your custom view from xml with the android:scrollbars
attribute set. This is the safest method and should work with all past and future platform versions. For example:
Create an xml layout file (my_custom_view.xml
):
<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"/>
Inflate your custom view:
MyCustomView view = (MyCustomView) LayoutInflater.from(context).inflate(R.layout.my_custom_view, container, false);
2) Use reflection to invoke initializeScrollbars()
in your custom view's constructor. This could fail in future API versions if the method initializeScrollbars()
is actually removed or renamed. For example:
In your custom view (e.g. MyCustomView.java
):
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();
}
来源:https://stackoverflow.com/questions/26448771/initializescrollbars-is-undefined