Learning to use Java’s reflection mechanism can help you in the real world.
What is reflection
Reflection refers to the support program in the running state, can obtain the internal information of the class, wrapped methods, variables and other information, and can change the method or its internal variables at run time.
In simple terms, if I want to dynamically change the value of a class in a system source code, such as the mFirst variable of Recyclerview, I can use reflection to get that value and change it.
The main classes for Java reflection are as follows:
The name of the class | use |
---|---|
Class Class | The compiled Class object |
Constructor class | Class constructor |
The Field class | Class member variables |
Method | A method member of the class |
Annotaion | Class notes |
In the above classes, such as the Field class, there are two reuse formats:
- GetField: Obtains a common object
- GetDeclaredField: obtains all objects, including private methods
Also used for other classes. Methods with Declared modifiers can be used to reflect private methods, while methods without Declared modifiers can only be used to reflect public methods.
Second, the instance
Next, let’s test a simple example and talk about some of the methods that Android often uses. The following is a simple class that requires changing the value dynamically. Start by writing a simple Bean:
public class PersonBean {
private int age;
public PersonBean(int age) {
this.age = age;
}
public PersonBean() {
}
public int getAge() {
return age;
}
public void setAge(int age) { this.age = age; }}Copy the code
So how do you get it?
As we know, the Class Class is the entry point to the program at runtime. Once we get an instance of the Class, we can manipulate it.
2.1. Common methods of Class
Here are some common ones.
methods | application |
---|---|
forName() | Returns the object of the class based on the class name |
newInstance() | Gets an instance of the class |
getSuperClass() | Gets the name of the parent class that the class inherits |
. | . |
2.2. Constructor method
NewInstance () above is a no-argument constructor, but what if the constructor has arguments? Can be aClass of Constructor getDeclaredConstructor (Class)… .newInstance(Object..) . For example, a value for the PersonBean argument above:
Class<? > aClass = Class.forName("com.zhengsr.androiddemo.bean.PersonBean");
Object instance = aClass.getDeclaredConstructor(int.class).newInstance(23);
Copy the code
Because the PersonBean is already known, use class.forname. You can also use new PersonBean(23).
Method and Field class methods
Now that I’ve got the PersonBean instance, how do I get the age variable while getting the getAge() method?
Field
methods | use |
---|---|
getField(String name) | Gets a public property object |
getFields() | Get all public property objects |
getDeclaredField(String name) | Get a property object |
getDeclaredFields() | Get all property objects |
get(Object obj) | The value of that variable |
set(Object obj, Object value) | Set the value through set |
Here, our code can be changed to:
try { Class<? > aClass = Class.forName("com.zhengsr.androiddemo.bean.PersonBean");
Object instance = aClass.getDeclaredConstructor(int.class).newInstance(23);
Field field = aClass.getDeclaredField("age");
field.setAccessible(true); Int age = (int) field. Get (instance); / / bysetSetting the d (TAG,ZSR gets the private variable age:+age);
field.set(instance,25);
int age2 = (int) field.get(instance);
Log.d(TAG, ZSR gets the changed private variable age:+age2);
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "zsr error: "+e.getMessage());
}
Copy the code
Method
methods | use |
---|---|
getMethod(String name, Class… <? > parameterTypes) | Gets a public method of that class |
getMethods() | Gets all public methods of the class |
getDeclaredMethod(String name, Class… <? > parameterTypes) | Gets a method of that class |
getDeclaredMethods() | Get all methods of the class |
nvoke(Object obj, Object… args) | Executes the target method of the object |
Here, setAge and getAge are both public methods, so you can get them using getMethod. So the code looks like this:
try { Class<? > aClass = Class.forName("com.zhengsr.androiddemo.bean.PersonBean");
Object instance = aClass.getDeclaredConstructor(int.class).newInstance(23);
Method setAge = aClass.getMethod("setAge", int.class);
setAge.setAccessible(true);
setAge.invoke(instance,30);
Method getAge = aClass.getMethod("getAge");
getAge.setAccessible(true);
int age = (int) getAge.invoke(instance);
Log.d(TAG, "ZSR gets changed value:"+age);
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "zsr error: "+e.getMessage());
}
Copy the code
So we’re done with some of the basic applications of reflection.
Android combat
With reflection in mind, some Android problems can be fixed on their own.
3.1 Modifying the Zoom Value
If you’ve ever done a ScaleGestureDetector, you know, on a larger screen, when you zoom out, when you zoom out to a certain scale, you can’t zoom any more because
mMinSpan = res.getDimensionPixelSize(com.android.internal.R.dimen.config_minScalingSpan);
Copy the code
This limits the size, and it’s a private value, which can be easily modified if we use reflection.
/ / set the mMinTry {Field Field = mScaleGesture.getClass().getDeclaredField()"mMinSpan");
field.setAccessible(true);
field.set(mScaleGesture,1);
} catch (Exception e) {
e.printStackTrace();
}
Copy the code
3.2 The combination of Banner and Recyclerview does not roll
Those of you who have wrapped the Banner should know that when you use ViewPager to make the Banner, and Recyclerview, when Recyclerview goes up, the next time it comes back, the Banner will jump directly to the next page, instead of scrolling. The reason for this is mFirstLayout, because Recyclerview will cause ViewPager to call onAttachedToWindow(), so mFirstLayout will be set to True again, So there’s the problem of not just skipping to the next page.
Change the value of mFirstLayout.
private boolean firstLayout = true;
@Override
protected void onAttachedToWindow() { super.onAttachedToWindow(); // Solve the problem that recyclerView does not work because of recyclerViewif(getAdapter() ! = null) { try { Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout");
mFirstLayout.setAccessible(true);
mFirstLayout.set(this, firstLayout);
setCurrentItem(getCurrentItem()); } catch (Exception e) { e.printStackTrace(); }}}Copy the code
If you have system privileges, but need to call some hidden API methods. Reflection can also be used at this point.
3.3 screenshot
Screenshots are common in system applications, but their classes are hidden and methods are public static methods:
public static Bitmap screenshot(int widht, int height){ Bitmap bitmap = null; try { Class<? > sClass = Class.forName("android.view.SurfaceControl");
Method method = sClass.getMethod("screenshot",int.class,int.class);
method.setAccessible(true);
bitmap = (Bitmap) method.invoke(sClass,widht,height);
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "zsr --> screenshot: "+e.toString());
}
return bitmap;
}
Copy the code
3.4 Deleting a Task
Use ActivityManager’s remvoeTask method (@hide) when you need to delete background tasks as a system manager or other admin app.
/** * Delete the task list * @param taskId * @return
* @throws SecurityException
*/
public static boolean removeTask(Context context,int taskId) throws SecurityException {
try {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
Method method = activityManager.getClass().getDeclaredMethod("removeTask",int.class);
method.setAccessible(true);
boolean invoke = (boolean) method.invoke(activityManager, taskId);
return invoke;
} catch (Exception e) {
return false; }}Copy the code
Finally, after learning the basics of posterior reflexes, you will no longer be confused.
Reference: Java Advanced features – Reflection