I my case: I want to override a hide method in TextView
by extends TextView
, and make call to its super method.
public class MyTextView extends TextView {
protected void makeNewLayout(int wantWidth, int hintWidth,
BoringLayout.Metrics boring,
BoringLayout.Metrics hintBoring,
int ellipsisWidth, boolean bringIntoView) {
// omit try catch for simple
Method method = Class.forName("android.widget.TextView").getDeclaredMethod("makeNewLayout", int.class, int.class, BoringLayout.Metrics.class, BoringLayout.Metrics.class, int.class, boolean.class);
method.setAccessible(true);
method.invoke(this, wantWidth, hintWidth, boring, hintBoring, ellipsisWidth, bringIntoView);
}
}
The problem is my self define makeNewLayout
is called and the method.invoke is executed, but the method invoke is MyTextView::makeNewLayout
not TextView::makeNewLayout
, it a dead recursive call.
How can I acheive it?
PS: makeNewLayout is a hide function, so I cannot call it directly by super.makeNewLayout(...)
Looks like it's not possible for java/android to do this kind of work easily. java is too safe to hack around.
There's a solution below android 8.0 if you can accept packaging some *.so library. There's a family of calling non-virtual methods in JNI interface ( https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#CallNonvirtual_type_Method_routines ) Using it like this:
Declaring in java:
public native void callNonvirtualVoidMethodHelper(Object obj, String classNameOfMethod, String methodName, String methodSignature);
Implementation in cpp:
extern "C"
JNIEXPORT
void JNICALL
Java_yourpackage_yourclass_callNonvirtualVoidMethodHelper(
JNIEnv *env,
jobject /* this */,
jobject obj,
jstring classNameOfMethod,
jstring methodName,
jstring methodSignature) {
const char *classNameStr = env->GetStringUTFChars(classNameOfMethod, JNI_FALSE);
const char *methodNameStr = env->GetStringUTFChars(methodName, JNI_FALSE);
const char *methodSignatureStr = env->GetStringUTFChars(methodSignature, JNI_FALSE);
jclass classOfMethod = env->FindClass(classNameStr);
jmethodID method = env->GetMethodID(classOfMethod, methodNameStr, methodSignatureStr);
env->CallNonvirtualVoidMethod(obj, classOfMethod, method);
}
Using it in java:
callNonvirtualVoidMethodHelper(new SubClass(),
"some/package/SuperClass", // specify the class of non-virtual method
"foo",
"()V"); // method signature
Or using MethodHandle when running above android 8.0 (Reference: https://stackoverflow.com/a/15674467/2300252 ).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.