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