Xpage series | after this upgrade, it is finally fully automated registration!

Time:2021-10-27

Xpage series | after this upgrade, it is finally fully automated registration!

preface

As the soul of the x-library series framework, xpage has been committed to reducing the difficulty of using fragments since it was opened to the public for two years, and strive to realize an android development mode with multiple activities and fragments.

Not long ago, I sorted out the use of xpage open source in recent years, wrote a guide to the use of xpage, the most convenient Android page framework in history, and recorded several videos to explain the use of xpage separately, so that more and more people can see the convenience of xpage.

But just a few days ago, someone in the exchange group suddenly asked me the following questions:

  • 1. What should I do if I want to use xpage in multiple modules?
  • 2. Why can’t I find it after I use xpageAppPageConfigThis class?

The above questions made me suddenly realize that not everyone knows about apt technology.

It seems that I used to refer toARouterThe automatic registration function may not be perfect. No wonderARouterI’ll write one laterarouter-registerPlug in to realize the function of automatic registration.

Therefore, in order to make the automatic registration function of xpage more perfect, I worked overtime to develop, so I had version 3.1.1 of xpage – complete automatic registration.

What has changed since the upgrade

Before feeling the convenience of fully automated page registration, let’s first feel the use of the previous version.

Before 3.1.1

Before version 3.1.1, when using the automatic registration function, it still needs to be implementedPageConfigurationInterface and call the getpages() method of the page configuration class “modulename” + pageconfig automatically generated during compilation to return the registered page.

PageConfig.getInstance()
        . setpageconfiguration (New pageconfiguration() {// page registration
            @Override
            public List<PageInfo> registerPages(Context context) {
                //The automatic registration page is automatically generated during compilation. Build will come out at once. If you haven't used @ page, it won't be generated for the time being.
                return AppPageConfig.getInstance().getPages(); // Automatic registration page
            }
        })
        . debug ("pagelog") // start debugging
        . setcontainactivityclazz (xpageactivity. Class) // set the default container activity
        . enablewatcher (false) // set whether to enable memory leak monitoring
        .init(this);

You can see that the automatic registration here still needs some manual cooperation. If you only have one module at present, it may be OK. However, if you use multiple modules, you need to add the configuration classes generated by multiple modules one by one as above. This will make people feel very inconvenient to use, which obviously violates my writingXPageThe original intention of the framework!

Not only that, but it also brings many other problems:

  • 1. If the module name changes, you need to modify the class name of the configuration class accordingly.
  • 2. If the current module is not used@PageIf the annotation modifies the fragment, the configuration class will not be generated automatically, which will make many first-time users very confused.
  • 3. If the project has not been compiled, the configuration class will not be generated automatically, so the code will report an error that the class cannot be found, and then many novices are confused.

Version after 3.1.1

In order to solve the above problems, I implemented an automatically registered configuration class autopageconfiguration. Let’s take a look at how the latest version of xpage is registered:

PageConfig.getInstance()
        . debug ("pagelog") // start debugging
        . setcontainactivityclazz (xpageactivity. Class) // set the default container activity as required (not required)
        .init(this);            // Initialize page configuration

Yes, you are right. There is no manual implementation herePageConfigurationThe part of the interface can be said to really realize full-automatic page registration. Is it very convenient?

Xpage series | after this upgrade, it is finally fully automated registration!

How to automate registration

Seeing the above changes, do you really want to know how I realize complete automatic registration?

To answer this question, let’s take a look at how the configuration class automatically generated at compile time is implemented.

Apt technology realizes the automatic generation of page configuration class

In fact, the original scheme to realize the automatic generation of page configuration class was also completed after I studied the arouter source code and inspired by apt technology.

Because xpage realizes route jump mainly by the mapping relationship established by pageinfo and fragment. The idea at that time was to use APT Technology and@PageAnnotation to identify the fragments that need to be registered, and then scan all used fragments through APT Technology during compilation@PageThe annotation identifies the fragment of the annotation and converts the annotation information intoPageInfoAnd generate the corresponding page configuration class according to the module. In this configuration class, all the annotations under the module are stored@PagePage information forPageInfo

The following is a simple configuration class example generated automatically:

Xpage series | after this upgrade, it is finally fully automated registration!

You can see that the automatically generated configuration classes are stored in thecom.xuexiang.xpage.configUnder the package, the class names arePageConfigAs an end. Note that this is very important. It is the key to realize automatic registration later.

For detailed implementation details, see the source code of page configuration automatic generator pageconfigprocessor of xpage.

Scan the configuration class reflection under the specified package at runtime to realize automatic registration

Above, we found a rule when understanding how the page configuration class is automatically generated:

Automatically generated configuration classes are stored in thecom.xuexiang.xpage.configUnder the package, the class names arePageConfigAs an end.

So can we scan directly when runningcom.xuexiang.xpage.configAll classes under the package, and then find them toPageConfigAs the end of the configuration class, and then reflect itsgetPagesMethod to get all the configuration information directly, and then register it?

The following is the source code of the autopageconfiguration class I implemented according to the above conjecture:

public class AutoPageConfiguration implements PageConfiguration {
    /**
     *The package name where the page configuration is located
     */
    private static final String PAGE_CONFIG_PACKAGE_NAME = "com.xuexiang.xpage.config";
    /**
     *Page configuration generates the class suffix of the class
     */
    private static final String PAGE_CONFIG_CLASS_NAME_SUFFIX = "PageConfig";

    @Override
    public List<PageInfo> registerPages(Context context) {
        List<PageInfo> pageInfos = new ArrayList<>();
        Set<String> classSet = null;
        try {
            classSet = ClassUtils.getClassNames(context, PAGE_CONFIG_PACKAGE_NAME);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (classSet != null) {
            for (String className : classSet) {
                if (className != null && className.endsWith(PAGE_CONFIG_CLASS_NAME_SUFFIX)) {
                    try {
                        pageInfos.addAll(getPagesByClass(Class.forName(className)));
                    } catch (Exception e) {
                        PageLog.e(e);
                    }
                }
            }
        }
        return pageInfos;
    }

    private List<PageInfo> getPagesByClass(Class<?> clazz) throws Exception {
        //Get singleton object
        Method getInstanceMethod = clazz.getDeclaredMethod("getInstance");
        getInstanceMethod.setAccessible(true);
        Object instance = getInstanceMethod.invoke(null);
        //Get page information
        Method getPagesMethod = clazz.getDeclaredMethod("getPages");
        getPagesMethod.setAccessible(true);
        return (List<PageInfo>) getPagesMethod.invoke(instance);
    }
}

From the source code, we can see that I did this:

  • 1. UseClassUtils.getClassNamesGetcom.xuexiang.xpage.configClass names of all classes under the package. thereClassUtilsI also learned from the source code in arouter.
  • 2. Traverse the class name collection and determine whether the end of the class name isPageConfigFilter out all configuration classes.
  • 3. CallgetPagesByClassMethod, get all page information of the configuration class through reflection, then add it to the page collection, and finally return the information of all module configuration pages.

YesAutoPageConfigurationAfter that, the following is very simple. We just need to set mpageconfiguration toAutoPageConfigurationIn this way, automatic registration can be realized!

/**
 *Initialize page information
 *
 *@ param context context
 */
private void initPages(Context context) {
    if (mPageConfiguration == null) {
        //If it is not set, use the automatic registration configuration
        mPageConfiguration = new AutoPageConfiguration();
    }
    registerPageInfos(mPageConfiguration.registerPages(context));
    CoreConfig.init(context, getPages());
}

Add confusion configuration

You think it’s over here? It’s not that simple! It can be found that the above implementation scheme mainly depends on scanning classes and reflection registration. Therefore, if the code is confused, the scheme will fail. Therefore, we need to add the following configuration in the confusion configuration list to avoid confusion:

-keep class com.xuexiang.xpage.config.** { *; }

We need to make surecom.xuexiang.xpage.configThe classes under the package cannot be confused.

Here, the implementation of automatic registration is really finished. Let’s take a look at the new version of xpage and the updates in those places!

Xpage series | after this upgrade, it is finally fully automated registration!

Other updates

Remove leakcanary dependency

Until then, xpage had relied onLeakCanary, the main reason isLeakCanaryBefore version 2.0, it was quite inconvenient to use, so I made a default integration for ease of use.

But whenLeakCanaryWhen upgrading to version 2.0 or above, this problem seems to be gone. Because of the redesign,LeakCanaryThe use of became less invasive, so I considered removing itLeakCanaryDependence on.

Optimized keyboard processing for page clicks

Previously, a simple page click process was done in xpageactivity: when the user clicks on the non input box area, the keyboard will be hidden.

However, after doing so, it is found that the effect is not very good, because some pages may not need this function. If this is written into the activity, all fragments under this activity will have this function, which is very inflexible.

In addition, the user may also want to customize the touch event of the screen, so I redesigned it, delegated the processing of the touch event to each fragment, and the activity called the specified method for processing.

Related links

  • The most convenient Android page framework xpage guide in history
  • Who is more popular than navigation and xpage framework
  • Xpage project address: https://github.com/xuexiangjys/XPage

last

Thank you very much for your support for xpage. If you like, you can go to the GitHub homepage of the project: https://github.com/xuexiangjys/XPage Click star support!

More information, WeChat search official account is welcome: “my Android open source Tour”.