Full Code of Xiasm/EasyRouter for AI

master 2b06de13e0a4 cached
114 files
137.0 KB
39.4k tokens
198 symbols
1 requests
Download .txt
Repository: Xiasm/EasyRouter
Branch: master
Commit: 2b06de13e0a4
Files: 114
Total size: 137.0 KB

Directory structure:
gitextract_n0f08trr/

├── .gitignore
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── easyrouter/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── easyrouter/
│       │   │               ├── BussinessInterceptor.java
│       │   │               ├── Main2Activity.java
│       │   │               ├── MainActivity.java
│       │   │               ├── ShowActivity.java
│       │   │               └── app/
│       │   │                   └── MyApplication.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   ├── activity_main.xml
│       │       │   ├── activity_main2.xml
│       │       │   └── activity_show.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easyrouter/
│                           └── ExampleUnitTest.java
├── base/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── base/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── base/
│       │   │               └── providers/
│       │   │                   └── module1/
│       │   │                       └── Module1Providers.java
│       │   └── res/
│       │       └── values/
│       │           └── strings.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── base/
│                           └── ExampleUnitTest.java
├── build.gradle
├── config.gradle
├── easy-annotation/
│   ├── .gitignore
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easy/
│                           └── annotation/
│                               ├── Extra.java
│                               ├── Interceptor.java
│                               ├── Route.java
│                               └── modle/
│                                   └── RouteMeta.java
├── easy-compiler/
│   ├── .gitignore
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easy/
│                           └── compiler/
│                               ├── processor/
│                               │   ├── ExtraProcessor.java
│                               │   ├── InterceptorProcessor.java
│                               │   └── RouterProcessor.java
│                               └── utils/
│                                   ├── Constant.java
│                                   ├── LoadExtraBuilder.java
│                                   ├── Log.java
│                                   └── Utils.java
├── easy-core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── easy/
│       │                   └── core/
│       │                       └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── easy/
│       │   │               └── core/
│       │   │                   ├── EasyRouter.java
│       │   │                   ├── ExtraManager.java
│       │   │                   ├── Postcard.java
│       │   │                   ├── Warehouse.java
│       │   │                   ├── callback/
│       │   │                   │   ├── InterceptorCallback.java
│       │   │                   │   └── NavigationCallback.java
│       │   │                   ├── exception/
│       │   │                   │   └── NoRouteFoundException.java
│       │   │                   ├── implments/
│       │   │                   │   └── InterceptorImpl.java
│       │   │                   ├── template/
│       │   │                   │   ├── IExtra.java
│       │   │                   │   ├── IInterceptor.java
│       │   │                   │   ├── IInterceptorGroup.java
│       │   │                   │   ├── IRouteGroup.java
│       │   │                   │   ├── IRouteRoot.java
│       │   │                   │   └── IService.java
│       │   │                   ├── thread/
│       │   │                   │   └── DefaultPoolExecutor.java
│       │   │                   └── utils/
│       │   │                       ├── CancelableCountDownLatch.java
│       │   │                       ├── ClassUtils.java
│       │   │                       ├── UniqueKeyTreeMap.java
│       │   │                       └── Utils.java
│       │   └── res/
│       │       └── values/
│       │           └── strings.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easy/
│                           └── core/
│                               └── ExampleUnitTest.java
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── module1/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── module1/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── module1/
│       │   │               ├── LoginInterceptor.java
│       │   │               ├── Module1MainActivity.java
│       │   │               └── Module1ProvidersImpl.java
│       │   ├── module/
│       │   │   └── AndroidManifest.xml
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   └── activity_module1_main.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── module1/
│                           └── ExampleUnitTest.java
├── module2/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── module2/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── module2/
│       │   │               └── Module2MainActivity.java
│       │   ├── module/
│       │   │   └── AndroidManifest.xml
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   └── activity_module2_main.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── module2/
│                           └── ExampleUnitTest.java
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Intellij IDEA
.idea/
*.iml
*.ipr
*.iws
out/

# Gradle build folder
build/
.gradle/

# Android
local.properties
bin/
gen/

# JNI compile files
*.o
*.o.d

# OS autogen folder information
.DS_Store
Thumbs.db

# Temp files
*.bak
*.tmp
*.temp
*.swp
*.*~
~*.*

# Eclipse project files
.classpath
.settings/
.project

#Android 2.2 C/C++ compile
.externalNativeBuild/


================================================
FILE: README.md
================================================
### 简介
路由在项目中用了很长一段时间了,一直用的ARouter,很早的时候,我就把ARouter里里外外研究了一番,可以说里面干货多多,但时间长了就有些记不住了,甚至一些技术点都记的混淆了。
于是便萌生了写一篇技术博客的想法,后来又觉着干巴巴的写一篇文章不足以让我认识的更深刻,就想着可否按照ARouter的思想自己实现一个简单的路由框架呢?<br/>
后来,在我不断地学习推动以及参考众多资料的情况下,耗费了几个月的业余时间,终于完成了这个项目。
### 这个项目对你有什么帮助?
通常看来,我要理解ARouter,就要去读ARouter的源码,这当然是不错的方法,但需要花费很多的时间去理解源码,而这个项目能给你的好处是一步步有条理的指导你如何去设计路由框架、一些技术点的作用及为什么要用这些技术等等,并且重点放在讲解,直到最后设计出来一款自己的路由框架,所以说呢,干货多多,简要列举几点:

* 首先,你可以学习到如何搭建组件化架构

* 其次,你可以学习到apt、javapoet等框架开发利器

* 再者,你可以手动实现自己的依赖注入框架

* 最后,像instantrun处理、框架设计等等

### 项目理解推荐
既然你来了,我想我们的目的很明确,就是要从根本上理解路由。所以我推荐大家把demo clone下来在电脑上跑一遍,然后边浏览WIKI的文档边读代码,这样才能快速的理解设计的思想。<br/>

[文档指导,点击跳转wiki](https://github.com/Xiasm/EasyRouter/wiki)<br/>

##### 目录:<br/>


[一、从组件化引入路由设计需要满足的条件](https://github.com/Xiasm/EasyRouter/wiki/%E4%BB%8E%E7%BB%84%E4%BB%B6%E5%8C%96%E5%BC%95%E5%85%A5%E8%B7%AF%E7%94%B1%E8%AE%BE%E8%AE%A1%E9%9C%80%E8%A6%81%E6%BB%A1%E8%B6%B3%E7%9A%84%E6%9D%A1%E4%BB%B6)

[二、通过Route注解去探究如何实现路由跳转](https://github.com/Xiasm/EasyRouter/wiki/%E9%80%9A%E8%BF%87Route%E6%B3%A8%E8%A7%A3%E5%8E%BB%E6%8E%A2%E7%A9%B6%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0%E8%B7%AF%E7%94%B1%E8%B7%B3%E8%BD%AC)
<br/>

[三、利用apt和javapoet生成路由映射文件](https://github.com/Xiasm/EasyRouter/wiki/%E5%88%A9%E7%94%A8apt%E5%92%8Cjavapoet%E7%94%9F%E6%88%90%E8%B7%AF%E7%94%B1%E6%98%A0%E5%B0%84%E6%96%87%E4%BB%B6)
<br/>

[四、框架的设计](https://github.com/Xiasm/EasyRouter/wiki/%E6%A1%86%E6%9E%B6%E7%9A%84%E8%AE%BE%E8%AE%A1)
<br/>

[五、框架的初始化](https://github.com/Xiasm/EasyRouter/wiki/%E6%A1%86%E6%9E%B6%E7%9A%84%E5%88%9D%E5%A7%8B%E5%8C%96)
<br/>

[六、实现路由跳转](https://github.com/Xiasm/EasyRouter/wiki/%E5%AE%9E%E7%8E%B0%E8%B7%AF%E7%94%B1%E8%B7%B3%E8%BD%AC)
<br/>

[七、为什么需要依赖注入](https://github.com/Xiasm/EasyRouter/wiki/%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5)

[八、Activity的属性注入](https://github.com/Xiasm/EasyRouter/wiki/Activity%E7%9A%84%E5%B1%9E%E6%80%A7%E6%B3%A8%E5%85%A5)
<br/>

### 联系我

email:xiasem@163.com & devxiasm@gmail.com<br/>
微信:xsm0824mn003


================================================
FILE: app/.gitignore
================================================
/build


================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'

def cfg = rootProject.ext.android
def appId = rootProject.ext.appId

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId appId["app"]
        minSdkVersion cfg.minSdkVersion
        targetSdkVersion cfg.targetSdkVersion
        versionCode cfg.versionCode
        versionName cfg.versionName

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    annotationProcessor project(':easy-compiler')
    implementation project(':base')

    if (isModule) {
        implementation project(':module1')
        implementation project(':module2')
    }
}


================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile


================================================
FILE: app/src/androidTest/java/com/xsm/easyrouter/ExampleInstrumentedTest.java
================================================
package com.xsm.easyrouter;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.xsm.easyrouter", appContext.getPackageName());
    }
}


================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.xsm.easyrouter">

    <application
        android:name=".app.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name=".Main2Activity">
        </activity>
        <activity android:name=".ShowActivity">
        </activity>
    </application>

</manifest>

================================================
FILE: app/src/main/java/com/xsm/easyrouter/BussinessInterceptor.java
================================================
package com.xsm.easyrouter;

import android.content.Context;
import android.util.Log;

import com.xsm.easy.annotation.Interceptor;
import com.xsm.easy.core.Postcard;
import com.xsm.easy.core.callback.InterceptorCallback;
import com.xsm.easy.core.template.IInterceptor;

/**
 * @author: luoxiaohui
 * @date: 2019-06-18 18:02
 * @desc:
 */
@Interceptor(priority = 2, name = "test")
public class BussinessInterceptor implements IInterceptor {

    private static final String TAG = "BussinessInterceptor";

    /**
     * 拦截器流程
     *
     * @param postcard
     * @param callback
     * @author luoxiaohui
     * @createTime 2019-05-23 20:53
     */
    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {

        Log.e(TAG, "process()...");
        callback.onNext(postcard);
    }

    /**
     * 在调用EasyRouter.init()初始化时,会调用到此方法
     *
     * @param context
     * @author luoxiaohui
     * @createTime 2019-06-18 10:39
     */
    @Override
    public void init(Context context) {

        Log.e(TAG, "init()...");
    }
}


================================================
FILE: app/src/main/java/com/xsm/easyrouter/Main2Activity.java
================================================
package com.xsm.easyrouter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.xsm.easy.annotation.Route;

@Route(path = "/main/main2")
public class Main2Activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
    }
}


================================================
FILE: app/src/main/java/com/xsm/easyrouter/MainActivity.java
================================================
package com.xsm.easyrouter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.xsm.base.providers.module1.Module1Providers;
import com.xsm.easy.annotation.Route;
import com.xsm.easy.core.EasyRouter;
import com.xsm.easy.core.Postcard;
import com.xsm.easy.core.callback.NavigationCallback;

@Route(path = "/main/main")
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private Module1Providers module1Providers;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initProviders();
    }

    private void initProviders() {
        module1Providers = (Module1Providers) EasyRouter.getsInstance().build("/module1/providers").navigation();
    }

    public void startModule1MainActivity(View view) {
//        EasyRouter.getsInstance().build("/module1/module1main").navigation();
        EasyRouter.getsInstance().build("/module1/module1main")
                .withString("msg", "从MainActivity").navigation();
    }

    public void startModule2MainActivity(View view) {
        EasyRouter.getsInstance().build("/module2/module2main").navigation(this, new NavigationCallback() {
            @Override
            public void onFound(Postcard postcard) {

            }

            @Override
            public void onLost(Postcard postcard) {

            }

            @Override
            public void onArrival(Postcard postcard) {

            }

            @Override
            public void onInterrupt(Throwable throwable) {

                Log.e(TAG, throwable.getMessage());
            }
        });
    }

    public void add(View view) {
        int num = module1Providers.add(5, 6);
        Toast.makeText(this, "5+6=" + num, Toast.LENGTH_SHORT).show();
    }
}


================================================
FILE: app/src/main/java/com/xsm/easyrouter/ShowActivity.java
================================================
package com.xsm.easyrouter;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.xsm.easy.annotation.Route;

@Route(path = "/show/info")
public class ShowActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show);
    }
}


================================================
FILE: app/src/main/java/com/xsm/easyrouter/app/MyApplication.java
================================================
package com.xsm.easyrouter.app;

import android.app.Application;

import com.xsm.easy.core.EasyRouter;

/**
 * Author: 夏胜明
 * Date: 2018/7/30 0030
 * Email: xiasem@163.com
 * Description:
 */
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        EasyRouter.init(this);
    }
}


================================================
FILE: app/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportHeight="108"
    android:viewportWidth="108">
    <path
        android:fillColor="#26A69A"
        android:pathData="M0,0h108v108h-108z"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M9,0L9,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,0L19,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M29,0L29,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M39,0L39,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M49,0L49,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M59,0L59,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M69,0L69,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M79,0L79,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M89,0L89,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M99,0L99,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,9L108,9"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,19L108,19"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,29L108,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,39L108,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,49L108,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,59L108,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,69L108,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,79L108,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,89L108,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,99L108,99"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,29L89,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,39L89,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,49L89,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,59L89,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,69L89,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,79L89,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M29,19L29,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M39,19L39,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M49,19L49,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M59,19L59,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M69,19L69,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M79,19L79,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
</vector>


================================================
FILE: app/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt"
        android:width="108dp"
        android:height="108dp"
        android:viewportHeight="108"
        android:viewportWidth="108">
    <path
        android:fillType="evenOdd"
        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="78.5885"
                android:endY="90.9159"
                android:startX="48.7653"
                android:startY="61.0927"
                android:type="linear">
                <item
                    android:color="#44000000"
                    android:offset="0.0"/>
                <item
                    android:color="#00000000"
                    android:offset="1.0"/>
            </gradient>
        </aapt:attr>
    </path>
    <path
        android:fillColor="#FFFFFF"
        android:fillType="nonZero"
        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1"/>
</vector>


================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.xsm.easyrouter.MainActivity">

    <Button
        android:onClick="startModule1MainActivity"
        android:text="跳转Module1主Activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:onClick="startModule2MainActivity"
        android:text="跳转Module2主Activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:text="加法"
        android:onClick="add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>


================================================
FILE: app/src/main/res/layout/activity_main2.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="main 2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

================================================
FILE: app/src/main/res/layout/activity_show.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
</resources>


================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">EasyRouter</string>
</resources>


================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>


================================================
FILE: app/src/test/java/com/xsm/easyrouter/ExampleUnitTest.java
================================================
package com.xsm.easyrouter;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

================================================
FILE: base/.gitignore
================================================
/build


================================================
FILE: base/build.gradle
================================================
apply plugin: 'com.android.library'

def cfg = rootProject.ext.android
def librarys = rootProject.ext.dependencies

android {
    compileSdkVersion cfg.compileSdkVersion



    defaultConfig {
        minSdkVersion cfg.minSdkVersion
        targetSdkVersion cfg.targetSdkVersion
        versionCode cfg.versionCode
        versionName cfg.versionName

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    librarys.each { k, v -> api v }
    api project(':easy-core')
}


================================================
FILE: base/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile


================================================
FILE: base/src/androidTest/java/com/xsm/base/ExampleInstrumentedTest.java
================================================
package com.xsm.base;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.xsm.base.test", appContext.getPackageName());
    }
}


================================================
FILE: base/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.xsm.base"/>


================================================
FILE: base/src/main/java/com/xsm/base/providers/module1/Module1Providers.java
================================================
package com.xsm.base.providers.module1;

import com.xsm.easy.core.template.IService;

/**
 * Author: 夏胜明
 * Date: 2018/8/20 0020
 * Email: xiasem@163.com
 * Description:
 */
public interface Module1Providers extends IService {

    int add(int a, int b);

}


================================================
FILE: base/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">base</string>
</resources>


================================================
FILE: base/src/test/java/com/xsm/base/ExampleUnitTest.java
================================================
package com.xsm.base;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

//相当于引入头文件 将 config中的内容引入进来
apply from: "config.gradle"

buildscript {
    
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.0'
        

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}


================================================
FILE: config.gradle
================================================
ext {
    //true 集成模式 false 组件模式
    isModule = true

    android = [
            compileSdkVersion:26,
            minSdkVersion    :14,
            targetSdkVersion :26,
            versionCode      :1,
            versionName      :"1.0"
    ]

    appId = [
            "app":"com.xsm.easyrouter",
            "module1":"com.xsm.module1",
            "module2":"com.xsm.module2"
    ]

    supportLibrary = "26.1.0"

    dependencies = [
            "appcompat-v7":"com.android.support:appcompat-v7:${supportLibrary}"
    ]

}

================================================
FILE: easy-annotation/.gitignore
================================================
/build


================================================
FILE: easy-annotation/build.gradle
================================================
apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"


================================================
FILE: easy-annotation/src/main/java/com/xsm/easy/annotation/Extra.java
================================================
package com.xsm.easy.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Author: 夏胜明
 * Date: 2018/8/20 0020
 * Email: xiasem@163.com
 * Description:
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
public @interface Extra {
    String name() default "";
}


================================================
FILE: easy-annotation/src/main/java/com/xsm/easy/annotation/Interceptor.java
================================================
package com.xsm.easy.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author: luoxiaohui
 * @date: 2019-05-23 20:08
 * @desc:
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Interceptor {

    /**
     * 拦截器优先级
     * @author luoxiaohui
     * @createTime 2019-06-04 20:51
     */
    int priority();
    /**
     * 拦截器的名称
     * @author luoxiaohui
     * @createTime 2019-05-23 20:33
     */
    String name() default "";
}


================================================
FILE: easy-annotation/src/main/java/com/xsm/easy/annotation/Route.java
================================================
package com.xsm.easy.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Route {
    /**
     * 路由的路径
     * @return
     */
    String path();

    /**
     * 将路由节点进行分组,可以实现动态加载
     * @return
     */
    String group() default "";

}


================================================
FILE: easy-annotation/src/main/java/com/xsm/easy/annotation/modle/RouteMeta.java
================================================
package com.xsm.easy.annotation.modle;

import com.xsm.easy.annotation.Route;

import javax.lang.model.element.Element;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */

public class RouteMeta {
    public enum Type {
        ACTIVITY,ISERVICE
    }

    private Type type;

    /**
     * 节点(Activity)
     */
    private Element element;
    /**
     * 注解使用的类对象
     */
    private Class<?> destination;

    /**
     * 路由地址
     */
    private String path;

    /**
     * 路由组
     */
    private String group;

    public static RouteMeta build(Type type, Class<?> destination, String path, String
            group) {
        return new RouteMeta(type, null, destination, path, group);
    }

    public RouteMeta() {
    }

    public RouteMeta(Type type, Route route, Element element) {
        this(type, element, null, route.path(), route.group());
    }

    public RouteMeta(Type type, Element element, Class<?> destination, String path, String
            group) {
        this.type = type;
        this.destination = destination;
        this.element = element;
        this.path = path;
        this.group = group;
    }


    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    public Element getElement() {
        return element;
    }

    public void setElement(Element element) {
        this.element = element;
    }

    public Class<?> getDestination() {
        return destination;
    }

    public void setDestination(Class<?> destination) {
        this.destination = destination;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }
}


================================================
FILE: easy-compiler/.gitignore
================================================
/build


================================================
FILE: easy-compiler/build.gradle
================================================
apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.google.auto.service:auto-service:1.0-rc2'
    annotationProcessor 'com.google.auto.service:auto-service:1.0-rc2'
    implementation 'com.squareup:javapoet:1.7.0'
    implementation project(':easy-annotation')
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"


================================================
FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/processor/ExtraProcessor.java
================================================
package com.xsm.easy.compiler.processor;

import com.google.auto.service.AutoService;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.xsm.easy.annotation.Extra;
import com.xsm.easy.compiler.utils.Constant;
import com.xsm.easy.compiler.utils.LoadExtraBuilder;
import com.xsm.easy.compiler.utils.Log;
import com.xsm.easy.compiler.utils.Utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

import static javax.lang.model.element.Modifier.PUBLIC;

/**
 * Author: 夏胜明
 * Date: 2018/8/20 0020
 * Email: xiasem@163.com
 * Description:
 */
@AutoService(Processor.class)
@SupportedOptions(Constant.ARGUMENTS_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes({Constant.ANN_TYPE_EXTRA})
public class ExtraProcessor extends AbstractProcessor {

    /**
     * 节点工具类 (类、函数、属性都是节点)
     */
    private Elements elementUtils;

    /**
     * type(类信息)工具类
     */
    private Types typeUtils;
    /**
     * 类/资源生成器
     */
    private Filer filerUtils;

    /**
     * 记录所有需要注入的属性 key:类节点 value:需要注入的属性节点集合
     */
    private Map<TypeElement, List<Element>> parentAndChild = new HashMap<>();
    private Log log;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        //获得apt的日志输出
        log = Log.newLog(processingEnvironment.getMessager());
        elementUtils = processingEnv.getElementUtils();
        typeUtils = processingEnvironment.getTypeUtils();
        filerUtils = processingEnv.getFiler();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if (!Utils.isEmpty(set)) {
            Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Extra.class);
            if (!Utils.isEmpty(elements)) {
                try {
                    categories(elements);
                    generateAutoWired();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return true;
            }
        }
        return false;
    }

    private void generateAutoWired() throws IOException {
        TypeMirror typeActivity = elementUtils.getTypeElement(Constant.ACTIVITY).asType();
        TypeElement iExtra = elementUtils.getTypeElement(Constant.IEXTRA);

        if (!Utils.isEmpty(parentAndChild)) {
            // 参数 Object target
            ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, "target").build();
            for (Map.Entry<TypeElement, List<Element>> entry : parentAndChild.entrySet()) {
                TypeElement rawClassElement = entry.getKey();
                if (!typeUtils.isSubtype(rawClassElement.asType(), typeActivity)) {
                    throw new RuntimeException("just support activity filed: " + rawClassElement);
                }
                //封装的函数生成类
                LoadExtraBuilder loadExtra = new LoadExtraBuilder(objectParamSpec);
                loadExtra.setElementUtils(elementUtils);
                loadExtra.setTypeUtils(typeUtils);
                ClassName className = ClassName.get(rawClassElement);
                loadExtra.injectTarget(className);
                //遍历属性
                for (int i = 0; i < entry.getValue().size(); i++) {
                    Element element = entry.getValue().get(i);
                    loadExtra.buildStatement(element);
                }

                // 生成java类名
                String extraClassName = rawClassElement.getSimpleName() + Constant.NAME_OF_EXTRA;
                // 生成 XX$$Autowired
                JavaFile.builder(className.packageName(), TypeSpec.classBuilder(extraClassName)
                        .addSuperinterface(ClassName.get(iExtra))
                        .addModifiers(PUBLIC).addMethod(loadExtra.build()).build())
                        .build().writeTo(filerUtils);
                log.i("Generated Extra: " + className.packageName() + "." + extraClassName);
            }
        }
    }

    /**
     * 记录需要生成的类与属性
     *
     * @param elements
     * @throws IllegalAccessException
     */
    private void categories(Set<? extends Element> elements) {
        for (Element element : elements) {
            //获得父节点 (类)
            TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
            if (parentAndChild.containsKey(enclosingElement)) {
                parentAndChild.get(enclosingElement).add(element);
            } else {
                List<Element> childs = new ArrayList<>();
                childs.add(element);
                parentAndChild.put(enclosingElement, childs);
            }
        }
    }


}


================================================
FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/processor/InterceptorProcessor.java
================================================
package com.xsm.easy.compiler.processor;

import com.google.auto.service.AutoService;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.WildcardTypeName;
import com.xsm.easy.annotation.Interceptor;
import com.xsm.easy.compiler.utils.Constant;
import com.xsm.easy.compiler.utils.Log;
import com.xsm.easy.compiler.utils.Utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

/**
 * @author: luoxiaohui
 * @date: 2019-05-23 19:48
 * @desc: 拦截器
 */
@AutoService(Processor.class)
@SupportedOptions(Constant.ARGUMENTS_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes(Constant.ANNOTATION_TYPE_INTERCEPTOR)
public class InterceptorProcessor extends AbstractProcessor {

    private Map<Integer, Element> interceptors = new HashMap<>();
    /**
     * 节点工具类 (类、函数、属性都是节点)
     */
    private Elements elementUtils;

    /**
     * type(类信息)工具类
     */
    private Types typeUtils;

    /**
     * 文件生成器 类/资源
     */
    private Filer filerUtils;

    private TypeMirror iInterceptor;
    private Log log;
    private String moduleName = "";

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        log = Log.newLog(processingEnv.getMessager());
        elementUtils = processingEnv.getElementUtils();
        typeUtils = processingEnv.getTypeUtils();
        filerUtils = processingEnv.getFiler();
        iInterceptor = elementUtils.getTypeElement(Constant.IINTERCEPTOR).asType();

        Map<String, String> options = processingEnv.getOptions();
        if (!Utils.isEmpty(options)) {
            moduleName = options.get(Constant.ARGUMENTS_NAME);
        }
    }

    /**
     * {@inheritDoc}
     *
     * @param annotations
     * @param roundEnv
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (!Utils.isEmpty(annotations)) {
            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Interceptor.class);
            try {
                parseInterceptor(elements);
            } catch (Exception e) {
                log.i(e.getMessage());
            }
            return true;
        }
        return false;
    }

    /**
     * 解析拦截器
     *
     * @author luoxiaohui
     * @createTime 2019-05-23 20:12
     */
    private void parseInterceptor(Set<? extends Element> elements) throws IOException {
        if (!Utils.isEmpty(elements)) {

            for (Element element : elements) {
                if (verify(element)) {

                    Interceptor interceptor = element.getAnnotation(Interceptor.class);
                    interceptors.put(interceptor.priority(), element);
                }
            }

            TypeElement iInterceptor = elementUtils.getTypeElement(Constant.IINTERCEPTOR);
            TypeElement iInterceptorGroup = elementUtils.getTypeElement(Constant.IINTERCEPTOR_GROUP);
            /**
             * Map<String, Class<? extends IInterceptor></>>
             */
            ParameterizedTypeName parameterizedTypeName = ParameterizedTypeName.get(
                    ClassName.get(Map.class),
                    ClassName.get(Integer.class),
                    ParameterizedTypeName.get(
                            ClassName.get(Class.class),
                            WildcardTypeName.subtypeOf(ClassName.get(iInterceptor))
                    )
            );
            /**
             * 参数+变量名
             * Map<String, Class<? extends IInterceptor>> interceptors
             */
            ParameterSpec parameterSpec = ParameterSpec.builder(parameterizedTypeName, "interceptors").build();
            /**
             * 构建方法
             * public void loadInto(Map<String, Class<? extends IInterceptor>> interceptors){}
             */
            MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(Constant.METHOD_LOAD_INTO)
                    .addAnnotation(Override.class)
                    .addModifiers(Modifier.PUBLIC)
                    .addParameter(parameterSpec);
            if (!interceptors.isEmpty() && interceptors.size() > 0) {
                /**
                 * 构建方法体中的语句
                 */
                for (Map.Entry<Integer, Element> entry : interceptors.entrySet()) {
                    methodBuilder.addStatement("interceptors.put(" + entry.getKey() + ", $T.class)",
                            ClassName.get((TypeElement) entry.getValue()));
                }
            }
            /**
             * 将文件写入磁盘中
             * 路径是在app/build/source/api/debug/PACKAGE_OF_GENERATE_FILE下面
             */
            JavaFile.builder(Constant.PACKAGE_OF_GENERATE_FILE,
                    TypeSpec.classBuilder(Constant.NAME_OF_INTERCEPTOR + moduleName)
                            .addModifiers(Modifier.PUBLIC)
                            .addMethod(methodBuilder.build())
                            .addSuperinterface(ClassName.get(iInterceptorGroup))
                            .build()
            ).build().writeTo(filerUtils);
        }
    }

    /**
     * 验证节点是否含有拦截器注解
     *
     * @author luoxiaohui
     * @createTime 2019-05-23 20:21
     */
    private boolean verify(Element element) {

        Interceptor interceptor = element.getAnnotation(Interceptor.class);
        return interceptor != null && ((TypeElement) element).getInterfaces().contains(iInterceptor);
    }
}


================================================
FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/processor/RouterProcessor.java
================================================
package com.xsm.easy.compiler.processor;

import com.google.auto.service.AutoService;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.WildcardTypeName;
import com.xsm.easy.annotation.Route;
import com.xsm.easy.annotation.modle.RouteMeta;
import com.xsm.easy.compiler.utils.Constant;
import com.xsm.easy.compiler.utils.Log;
import com.xsm.easy.compiler.utils.Utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */

@AutoService(Processor.class)
/**
  处理器接收的参数 替代 {@link AbstractProcessor#getSupportedOptions()} 函数
 */
@SupportedOptions(Constant.ARGUMENTS_NAME)
/**
 * 指定使用的Java版本 替代 {@link AbstractProcessor#getSupportedSourceVersion()} 函数
 */
@SupportedSourceVersion(SourceVersion.RELEASE_7)
/**
 * 注册给哪些注解的  替代 {@link AbstractProcessor#getSupportedAnnotationTypes()} 函数
 */
@SupportedAnnotationTypes(Constant.ANNOTATION_TYPE_ROUTE)

public class RouterProcessor extends AbstractProcessor {
    /**
     * key:组名 value:类名
     */
    private Map<String, String> rootMap = new TreeMap<>();
    /**
     * 分组 key:组名 value:对应组的路由信息
     */
    private Map<String, List<RouteMeta>> groupMap = new HashMap<>();

    /**
     * 节点工具类 (类、函数、属性都是节点)
     */
    private Elements elementUtils;

    /**
     * type(类信息)工具类
     */
    private Types typeUtils;

    /**
     * 文件生成器 类/资源
     */
    private Filer filerUtils;

    private String moduleName;

    private Log log;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        //获得apt的日志输出
        log = Log.newLog(processingEnvironment.getMessager());
        elementUtils = processingEnvironment.getElementUtils();
        typeUtils = processingEnvironment.getTypeUtils();
        filerUtils = processingEnvironment.getFiler();

        //参数是模块名 为了防止多模块/组件化开发的时候 生成相同的 xx$$ROOT$$文件
        Map<String, String> options = processingEnvironment.getOptions();
        if (!Utils.isEmpty(options)) {
            moduleName = options.get(Constant.ARGUMENTS_NAME);
        }
        if (Utils.isEmpty(moduleName)) {
            throw new RuntimeException("Not set processor moudleName option !");
        }
        log.i("init RouterProcessor " + moduleName + " success !");
    }

    /**
     *
     * @param set 使用了支持处理注解的节点集合
     * @param roundEnvironment 表示当前或是之前的运行环境,可以通过该对象查找找到的注解。
     * @return true 表示后续处理器不会再处理(已经处理)
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if (!Utils.isEmpty(set)) {
            //被Route注解的节点集合
            Set<? extends Element> rootElements = roundEnvironment.getElementsAnnotatedWith(Route.class);
            if (!Utils.isEmpty(rootElements)) {
                processorRoute(rootElements);
            }
            return true;
        }
        return false;
    }

    private void processorRoute(Set<? extends Element> rootElements) {
        //获得Activity这个类的节点信息
        TypeElement activity = elementUtils.getTypeElement(Constant.ACTIVITY);
        TypeElement service = elementUtils.getTypeElement(Constant.ISERVICE);
        for (Element element : rootElements) {
            RouteMeta routeMeta;
            //类信息
            TypeMirror typeMirror = element.asType();
            log.i("Route class:" + typeMirror.toString());
            Route route = element.getAnnotation(Route.class);
            if (typeUtils.isSubtype(typeMirror, activity.asType())) {
                routeMeta = new RouteMeta(RouteMeta.Type.ACTIVITY, route, element);
            } else if (typeUtils.isSubtype(typeMirror, service.asType())) {
                routeMeta = new RouteMeta(RouteMeta.Type.ISERVICE, route, element);
            } else {
                throw new RuntimeException("Just support Activity or IService Route: " + element);
            }
            categories(routeMeta);
        }
        TypeElement iRouteGroup = elementUtils.getTypeElement(Constant.IROUTE_GROUP);
        TypeElement iRouteRoot = elementUtils.getTypeElement(Constant.IROUTE_ROOT);

        //生成Group记录分组表
        generatedGroup(iRouteGroup);

        //生成Root类 作用:记录<分组,对应的Group类>
        generatedRoot(iRouteRoot, iRouteGroup);
    }

    /**
     * 生成Root类  作用:记录<分组,对应的Group类>
     * @param iRouteRoot
     * @param iRouteGroup
     */
    private void generatedRoot(TypeElement iRouteRoot, TypeElement iRouteGroup) {
        //创建参数类型 Map<String,Class<? extends IRouteGroup>> routes>
        //Wildcard 通配符
        ParameterizedTypeName parameterizedTypeName = ParameterizedTypeName.get(
                ClassName.get(Map.class),
                ClassName.get(String.class),
                ParameterizedTypeName.get(
                        ClassName.get(Class.class),
                        WildcardTypeName.subtypeOf(ClassName.get(iRouteGroup))
                ));
        //参数 Map<String,Class<? extends IRouteGroup>> routes> routes
        ParameterSpec parameter = ParameterSpec.builder(parameterizedTypeName, "routes").build();
        //函数 public void loadInfo(Map<String,Class<? extends IRouteGroup>> routes> routes)
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(Constant.METHOD_LOAD_INTO)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .addParameter(parameter);
        //函数体
        for (Map.Entry<String, String> entry : rootMap.entrySet()) {
            methodBuilder.addStatement("routes.put($S, $T.class)", entry.getKey(), ClassName.get(Constant.PACKAGE_OF_GENERATE_FILE, entry.getValue()));
        }
        //生成$Root$类
        String className = Constant.NAME_OF_ROOT + moduleName;
        TypeSpec typeSpec = TypeSpec.classBuilder(className)
                .addSuperinterface(ClassName.get(iRouteRoot))
                .addModifiers(Modifier.PUBLIC)
                .addMethod(methodBuilder.build())
                .build();
        try {
            JavaFile.builder(Constant.PACKAGE_OF_GENERATE_FILE, typeSpec).build().writeTo(filerUtils);
            log.i("Generated RouteRoot:" + Constant.PACKAGE_OF_GENERATE_FILE + "." + className);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void generatedGroup(TypeElement iRouteGroup) {
        //创建参数类型 Map<String, RouteMeta>
        ParameterizedTypeName parameterizedTypeName = ParameterizedTypeName.get(
                ClassName.get(Map.class),
                ClassName.get(String.class),
                ClassName.get(RouteMeta.class));
        ParameterSpec altas = ParameterSpec.builder(parameterizedTypeName, "atlas").build();

        for (Map.Entry<String, List<RouteMeta>> entry : groupMap.entrySet()) {
            MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(Constant.METHOD_LOAD_INTO)
                    .addModifiers(Modifier.PUBLIC)
                    .addAnnotation(Override.class)
                    .addParameter(altas);

            String groupName = entry.getKey();
            List<RouteMeta> groupData = entry.getValue();
            for (RouteMeta routeMeta : groupData) {
                //函数体的添加
                methodBuilder.addStatement("atlas.put($S,$T.build($T.$L,$T.class,$S,$S))",
                        routeMeta.getPath(),
                        ClassName.get(RouteMeta.class),
                        ClassName.get(RouteMeta.Type.class),
                        routeMeta.getType(),
                        ClassName.get(((TypeElement) routeMeta.getElement())),
                        routeMeta.getPath(),
                        routeMeta.getGroup());
            }
            String groupClassName = Constant.NAME_OF_GROUP + groupName;
            TypeSpec typeSpec = TypeSpec.classBuilder(groupClassName)
                    .addSuperinterface(ClassName.get(iRouteGroup))
                    .addModifiers(Modifier.PUBLIC)
                    .addMethod(methodBuilder.build())
                    .build();
            JavaFile javaFile = JavaFile.builder(Constant.PACKAGE_OF_GENERATE_FILE, typeSpec).build();
            try {
                javaFile.writeTo(filerUtils);
            } catch (IOException e) {
                e.printStackTrace();
            }
            rootMap.put(groupName, groupClassName);

        }
    }

    /**
     * 检查是否配置 group 如果没有配置 则从path截取出组名
     * @param routeMeta
     */
    private void categories(RouteMeta routeMeta) {
        if (routeVerify(routeMeta)) {
            log.i("Group : " + routeMeta.getGroup() + " path=" + routeMeta.getPath());
            //分组与组中的路由信息
            List<RouteMeta> routeMetas = groupMap.get(routeMeta.getGroup());
            if (Utils.isEmpty(routeMetas)) {
                routeMetas = new ArrayList<>();
                routeMetas.add(routeMeta);
                groupMap.put(routeMeta.getGroup(), routeMetas);
            } else {
                routeMetas.add(routeMeta);
            }
        } else {
            log.i("Group info error:" + routeMeta.getPath());
        }
    }

    /**
     * 验证path路由地址的合法性
     * @param routeMeta
     * @return
     */
    private boolean routeVerify(RouteMeta routeMeta) {
        String path = routeMeta.getPath();
        String group = routeMeta.getGroup();
        // 必须以 / 开头来指定路由地址
        if (!path.startsWith("/")) {
            return false;
        }
        //如果group没有设置 我们从path中获得group
        if (Utils.isEmpty(group)) {
            String defaultGroup = path.substring(1, path.indexOf("/", 1));
            //截取出的group还是空
            if (Utils.isEmpty(defaultGroup)) {
                return false;
            }
            routeMeta.setGroup(defaultGroup);
        }
        return true;
    }

}


================================================
FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Constant.java
================================================
package com.xsm.easy.compiler.utils;

import com.squareup.javapoet.ClassName;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */

public class Constant {
    public static final ClassName ROUTER = ClassName.get("com.xsm.easy.core", "EasyRouter");

    public static final String ACTIVITY = "android.app.Activity";
    public static final String ISERVICE = "com.xsm.easy.core.template.IService";

    public static final String ARGUMENTS_NAME = "moduleName";
    public static final String ANNOTATION_TYPE_ROUTE = "com.xsm.easy.annotation.Route";
    public static final String ANN_TYPE_EXTRA = "com.xsm.easy.annotation.Extra";
    public static final String ANNOTATION_TYPE_INTERCEPTOR = "com.xsm.easy.annotation.Interceptor";

    public static final String IROUTE_GROUP = "com.xsm.easy.core.template.IRouteGroup";
    public static final String IROUTE_ROOT = "com.xsm.easy.core.template.IRouteRoot";
    public static final String IEXTRA = "com.xsm.easy.core.template.IExtra";
    public static final String IINTERCEPTOR = "com.xsm.easy.core.template.IInterceptor";
    public static final String IINTERCEPTOR_GROUP = "com.xsm.easy.core.template.IInterceptorGroup";

    public static final String SEPARATOR = "_";
    public static final String PROJECT = "EaseRouter";
    public static final String NAME_OF_GROUP = PROJECT + SEPARATOR + "Group" + SEPARATOR;
    public static final String NAME_OF_ROOT = PROJECT + SEPARATOR + "Root" + SEPARATOR;
    public static final String PACKAGE_OF_GENERATE_FILE = "com.xsm.easyrouter.routes";

    public static final String METHOD_LOAD_INTO = "loadInto";
    public static final String METHOD_LOAD_EXTRA = "loadExtra";

    public static final String PARCELABLE = "android.os.Parcelable";

    private static final String LANG = "java.lang";
    public static final String BYTE = LANG + ".Byte";
    public static final String SHORT = LANG + ".Short";
    public static final String INTEGER = LANG + ".Integer";
    public static final String LONG = LANG + ".Long";
    public static final String FLOAT = LANG + ".Float";
    public static final String DOUBEL = LANG + ".Double";
    public static final String BOOLEAN = LANG + ".Boolean";
    public static final String STRING = LANG + ".String";
    public static final String ARRAY = "ARRAY";

    public static final String ARRAYLIST = "java.util.ArrayList";
    public static final String LIST = "java.util.List";

    public static final String BYTEARRAY = "byte[]";
    public static final String SHORTARRAY = "short[]";
    public static final String BOOLEANARRAY = "boolean[]";
    public static final String CHARARRAY = "char[]";
    public static final String DOUBLEARRAY = "double[]";
    public static final String FLOATARRAY = "float[]";
    public static final String INTARRAY = "int[]";
    public static final String LONGARRAY = "long[]";
    public static final String STRINGARRAY = "java.lang.String[]";


    public static final String NAME_OF_EXTRA = SEPARATOR + "Extra";
    public static final String NAME_OF_INTERCEPTOR = PROJECT + SEPARATOR + "Interceptor" + SEPARATOR;


}


================================================
FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/LoadExtraBuilder.java
================================================
package com.xsm.easy.compiler.utils;

import com.squareup.javapoet.ArrayTypeName;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.xsm.easy.annotation.Extra;

import java.util.List;

import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

/**
 * Author: 夏胜明
 * Date: 2018/8/20 0020
 * Email: xiasem@163.com
 * Description:
 */
public class LoadExtraBuilder {
    private static final String INJECT_TARGET = "$T t = ($T)target";
    private MethodSpec.Builder builder;
    private Elements elementUtils;
    private Types typeUtils;

    private TypeMirror parcelableType;
    private TypeMirror iServiceType;

    public LoadExtraBuilder(ParameterSpec parameterSpec) {
        // 函数 public void loadExtra(Object target)
        builder = MethodSpec.methodBuilder(Constant.METHOD_LOAD_EXTRA)
                .addAnnotation(Override.class)
                .addModifiers(Modifier.PUBLIC)
                .addParameter(parameterSpec);
    }

    public void setElementUtils(Elements elementUtils) {
        this.elementUtils = elementUtils;
        parcelableType = elementUtils.getTypeElement(Constant.PARCELABLE).asType();
        iServiceType = elementUtils.getTypeElement(Constant.ISERVICE).asType();
    }

    public void setTypeUtils(Types typeUtils) {
        this.typeUtils = typeUtils;
    }

    public void buildStatement(Element element) {
        TypeMirror typeMirror = element.asType();
        int type = typeMirror.getKind().ordinal();
        //属性名 String text 获得text
        String fieldName = element.getSimpleName().toString();
        //获得注解 name值
        String extraName = element.getAnnotation(Extra.class).name();
        extraName = Utils.isEmpty(extraName) ? fieldName : extraName;
        String defaultValue = "t." + fieldName;
        String statement = defaultValue + " = t.getIntent().";
        if (type == TypeKind.BOOLEAN.ordinal()) {
            statement += "getBooleanExtra($S, " + defaultValue + ")";
        } else if (type == TypeKind.BYTE.ordinal()) {
            statement += "getByteExtra($S, " + defaultValue + ")";
        } else if (type == TypeKind.SHORT.ordinal()) {
            statement += "getShortExtra($S, " + defaultValue + ")";
        } else if (type == TypeKind.INT.ordinal()) {
            statement += "getIntExtra($S, " + defaultValue + ")";
        } else if (type == TypeKind.LONG.ordinal()) {
            statement += "getLongExtra($S, " + defaultValue + ")";
        } else if (type == TypeKind.CHAR.ordinal()) {
            statement += "getCharExtra($S, " + defaultValue + ")";
        } else if (type == TypeKind.FLOAT.ordinal()) {
            statement += "getFloatExtra($S, " + defaultValue + ")";
        } else if (type == TypeKind.DOUBLE.ordinal()) {
            statement += "getDoubleExtra($S, " + defaultValue + ")";
        } else {
            //数组类型
            if (type == TypeKind.ARRAY.ordinal()) {
                addArrayStatement(statement, fieldName, extraName, typeMirror, element);
            } else {
                //Object
                addObjectStatement(statement, fieldName, extraName, typeMirror, element);
            }
            return;
        }
        builder.addStatement(statement, extraName);
    }

    /**
     * 添加对象 String/List/Parcelable
     *
     * @param statement
     * @param extraName
     * @param typeMirror
     * @param element
     */
    private void addObjectStatement(String statement, String fieldName, String extraName,
                                    TypeMirror typeMirror,
                                    Element element) {
        //Parcelable
        if (typeUtils.isSubtype(typeMirror, parcelableType)) {
            statement += "getParcelableExtra($S)";
        } else if (typeMirror.toString().equals(Constant.STRING)) {
            statement += "getStringExtra($S)";
        } else if (typeUtils.isSubtype(typeMirror, iServiceType)) {
            statement = "t." + fieldName + " = ($T) $T.getInstance().build($S).navigation()";
            builder.addStatement(statement, TypeName.get(element.asType()), Constant.ROUTER, extraName);
            return;
        } else {
            //List
            TypeName typeName = ClassName.get(typeMirror);
            //泛型
            if (typeName instanceof ParameterizedTypeName) {
                //list 或 arraylist
                ClassName rawType = ((ParameterizedTypeName) typeName).rawType;
                //泛型类型
                List<TypeName> typeArguments = ((ParameterizedTypeName) typeName)
                        .typeArguments;
                if (!rawType.toString().equals(Constant.ARRAYLIST) && !rawType.toString()
                        .equals(Constant.LIST)) {
                    throw new RuntimeException("Not Support Inject Type:" + typeMirror + " " +
                            element);
                }
                if (typeArguments.isEmpty() || typeArguments.size() != 1) {
                    throw new RuntimeException("List Must Specify Generic Type:" + typeArguments);
                }
                TypeName typeArgumentName = typeArguments.get(0);
                TypeElement typeElement = elementUtils.getTypeElement(typeArgumentName
                        .toString());
                // Parcelable 类型
                if (typeUtils.isSubtype(typeElement.asType(), parcelableType)) {
                    statement += "getParcelableArrayListExtra($S)";
                } else if (typeElement.asType().toString().equals(Constant.STRING)) {
                    statement += "getStringArrayListExtra($S)";
                } else if (typeElement.asType().toString().equals(Constant.INTEGER)) {
                    statement += "getIntegerArrayListExtra($S)";
                } else {
                    throw new RuntimeException("Not Support Generic Type : " + typeMirror + " " +
                            element);
                }
            } else {
                throw new RuntimeException("Not Support Extra Type : " + typeMirror + " " +
                        element);
            }
        }
        builder.addStatement(statement, extraName);
    }

    /**
     * 添加数组
     *
     * @param statement
     * @param fieldName
     * @param typeMirror
     * @param element
     */
    private void addArrayStatement(String statement, String fieldName, String extraName, TypeMirror
            typeMirror, Element element) {
        //数组
        switch (typeMirror.toString()) {
            case Constant.BOOLEANARRAY:
                statement += "getBooleanArrayExtra($S)";
                break;
            case Constant.INTARRAY:
                statement += "getIntArrayExtra($S)";
                break;
            case Constant.SHORTARRAY:
                statement += "getShortArrayExtra($S)";
                break;
            case Constant.FLOATARRAY:
                statement += "getFloatArrayExtra($S)";
                break;
            case Constant.DOUBLEARRAY:
                statement += "getDoubleArrayExtra($S)";
                break;
            case Constant.BYTEARRAY:
                statement += "getByteArrayExtra($S)";
                break;
            case Constant.CHARARRAY:
                statement += "getCharArrayExtra($S)";
                break;
            case Constant.LONGARRAY:
                statement += "getLongArrayExtra($S)";
                break;
            case Constant.STRINGARRAY:
                statement += "getStringArrayExtra($S)";
                break;
            default:
                //Parcelable 数组
                String defaultValue = "t." + fieldName;
                //object数组 componentType获得object类型
                ArrayTypeName arrayTypeName = (ArrayTypeName) ClassName.get(typeMirror);
                TypeElement typeElement = elementUtils.getTypeElement(arrayTypeName
                        .componentType.toString());
                //是否为 Parcelable 类型
                if (!typeUtils.isSubtype(typeElement.asType(), parcelableType)) {
                    throw new RuntimeException("Not Support Extra Type:" + typeMirror + " " +
                            element);
                }
                statement = "$T[] " + fieldName + " = t.getIntent()" +
                        ".getParcelableArrayExtra" +
                        "($S)";
                builder.addStatement(statement, parcelableType, extraName);
                builder.beginControlFlow("if( null != $L)", fieldName);
                statement = defaultValue + " = new $T[" + fieldName + ".length]";
                builder.addStatement(statement, arrayTypeName.componentType)
                        .beginControlFlow("for (int i = 0; i < " + fieldName + "" +
                                ".length; " +
                                "i++)")
                        .addStatement(defaultValue + "[i] = ($T)" + fieldName + "[i]",
                                arrayTypeName.componentType)
                        .endControlFlow();
                builder.endControlFlow();
                return;
        }
        builder.addStatement(statement, extraName);
    }

    /**
     * 加入 $T t = ($T)target
     *
     * @param className
     */
    public void injectTarget(ClassName className) {
        builder.addStatement(INJECT_TARGET, className, className);

    }

    public MethodSpec build() {
        return builder.build();
    }
}


================================================
FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Log.java
================================================
package com.xsm.easy.compiler.utils;

import javax.annotation.processing.Messager;
import javax.tools.Diagnostic;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */

public class Log {
    private Messager messager;

    private Log(Messager messager) {
        this.messager = messager;
    }

    public static Log newLog(Messager messager) {
        return new Log(messager);
    }

    public void i(String msg) {
        messager.printMessage(Diagnostic.Kind.NOTE, msg);
    }
}


================================================
FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Utils.java
================================================
package com.xsm.easy.compiler.utils;

import java.util.Collection;
import java.util.Map;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */

public class Utils {
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    public static boolean isEmpty(Collection<?> coll) {
        return coll == null || coll.isEmpty();
    }

    public static boolean isEmpty(final Map<?, ?> map) {
        return map == null || map.isEmpty();
    }
}


================================================
FILE: easy-core/.gitignore
================================================
/build


================================================
FILE: easy-core/build.gradle
================================================
apply plugin: 'com.android.library'

android {
    compileSdkVersion 26



    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    // compile被废弃
    // api:同compile
    // implementation: 不会进行传递依赖
    // 即router-annotation模块只对 本模块(router-core) 开放,
    // 无法在 app 模块中使用
    api project(':easy-annotation')
}


================================================
FILE: easy-core/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile


================================================
FILE: easy-core/src/androidTest/java/com/xsm/easy/core/ExampleInstrumentedTest.java
================================================
package com.xsm.easy.core;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.xsm.easy.core.test", appContext.getPackageName());
    }
}


================================================
FILE: easy-core/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.xsm.easy.core"/>


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/EasyRouter.java
================================================
package com.xsm.easy.core;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.ActivityCompat;
import android.text.TextUtils;
import android.util.Log;

import com.xsm.easy.annotation.modle.RouteMeta;
import com.xsm.easy.core.callback.InterceptorCallback;
import com.xsm.easy.core.callback.NavigationCallback;
import com.xsm.easy.core.exception.NoRouteFoundException;
import com.xsm.easy.core.implments.InterceptorImpl;
import com.xsm.easy.core.template.IInterceptor;
import com.xsm.easy.core.template.IInterceptorGroup;
import com.xsm.easy.core.template.IRouteGroup;
import com.xsm.easy.core.template.IRouteRoot;
import com.xsm.easy.core.template.IService;
import com.xsm.easy.core.utils.ClassUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Set;

/**
 * Author: 夏胜明
 * Date: 2018/4/3 0003
 * Email: xiasem@163.com
 * Description:
 */

public class EasyRouter {
    private static final String TAG = "EasyRouter";
    private static final String ROUTE_ROOT_PAKCAGE = "com.xsm.easyrouter.routes";
    private static final String SDK_NAME = "EaseRouter";
    private static final String SEPARATOR = "_";
    private static final String SUFFIX_ROOT = "Root";
    private static final String SUFFIX_INTERCEPTOR = "Interceptor";

    private static EasyRouter sInstance;
    private static Application mContext;
    private Handler mHandler;

    private EasyRouter() {
        mHandler = new Handler(Looper.getMainLooper());
    }

    public static EasyRouter getsInstance() {
        if (sInstance == null) {
            synchronized (EasyRouter.class) {
                if (sInstance == null) {
                    sInstance = new EasyRouter();
                }
            }
        }
        return sInstance;
    }

    public static void init(Application application) {
        mContext = application;
        try {
            loadInfo();
            InterceptorImpl.init(application.getApplicationContext());
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "初始化失败!", e);
        }
    }


    /**
     * 分组表制作
     */
    private static void loadInfo() throws PackageManager.NameNotFoundException, InterruptedException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获得所有 apt生成的路由类的全类名 (路由表)
        Set<String> routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
        for (String className : routerMap) {
            if (className.startsWith(ROUTE_ROOT_PAKCAGE + "." + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                //root中注册的是分组信息 将分组信息加入仓库中
                ((IRouteRoot) Class.forName(className).getConstructor().newInstance()).loadInto(Warehouse.groupsIndex);
            } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + "." + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTOR)) {

                ((IInterceptorGroup) Class.forName(className).getConstructor().newInstance()).loadInto(Warehouse.interceptorsIndex);
            }
        }
        for (Map.Entry<String, Class<? extends IRouteGroup>> stringClassEntry : Warehouse.groupsIndex.entrySet()) {
            Log.d(TAG, "Root映射表[ " + stringClassEntry.getKey() + " : " + stringClassEntry.getValue() + "]");
        }

    }

    public Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new RuntimeException("路由地址无效!");
        } else {
            return build(path, extractGroup(path));
        }
    }

    public Postcard build(String path, String group) {
        if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
            throw new RuntimeException("路由地址无效!");
        } else {
            return new Postcard(path, group);
        }
    }

    /**
     * 获得组别
     *
     * @param path
     * @return
     */
    private String extractGroup(String path) {
        if (TextUtils.isEmpty(path) || !path.startsWith("/")) {
            throw new RuntimeException(path + " : 不能提取group.");
        }
        try {
            String defaultGroup = path.substring(1, path.indexOf("/", 1));
            if (TextUtils.isEmpty(defaultGroup)) {
                throw new RuntimeException(path + " : 不能提取group.");
            } else {
                return defaultGroup;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {

        if (callback != null) {

            InterceptorImpl.onInterceptions(postcard, new InterceptorCallback() {
                @Override
                public void onNext(Postcard postcard) {
                    _navigation(context, postcard, requestCode, callback);
                }

                @Override
                public void onInterrupt(String interruptMsg) {

                    callback.onInterrupt(new Throwable(interruptMsg));
                }
            });
        }else{

            return _navigation(context, postcard, requestCode, callback);
        }

        return null;
    }

    protected Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        try {
            prepareCard(postcard);
        } catch (NoRouteFoundException e) {
            e.printStackTrace();
            //没找到
            if (null != callback) {
                callback.onLost(postcard);
            }
            return null;
        }
        if (null != callback) {
            callback.onFound(postcard);
        }

        switch (postcard.getType()) {
            case ACTIVITY:
                final Context currentContext = null == context ? mContext : context;
                final Intent intent = new Intent(currentContext, postcard.getDestination());
                intent.putExtras(postcard.getExtras());
                int flags = postcard.getFlags();
                if (-1 != flags) {
                    intent.setFlags(flags);
                } else if (!(currentContext instanceof Activity)) {
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //可能需要返回码
                        if (requestCode > 0) {
                            ActivityCompat.startActivityForResult((Activity) currentContext, intent,
                                    requestCode, postcard.getOptionsBundle());
                        } else {
                            ActivityCompat.startActivity(currentContext, intent, postcard
                                    .getOptionsBundle());
                        }

                        if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) &&
                                currentContext instanceof Activity) {
                            //老版本
                            ((Activity) currentContext).overridePendingTransition(postcard
                                            .getEnterAnim()
                                    , postcard.getExitAnim());
                        }
                        //跳转完成
                        if (null != callback) {
                            callback.onArrival(postcard);
                        }
                    }
                });
                break;
            case ISERVICE:
                return postcard.getService();
            default:
                break;
        }
        return null;
    }

    /**
     * 准备卡片
     *
     * @param card
     */
    private void prepareCard(Postcard card) {
        RouteMeta routeMeta = Warehouse.routes.get(card.getPath());
        if (null == routeMeta) {
            Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(card.getGroup());
            if (null == groupMeta) {
                throw new NoRouteFoundException("没找到对应路由:分组=" + card.getGroup() + "   路径=" + card.getPath());
            }
            IRouteGroup iGroupInstance;
            try {
                iGroupInstance = groupMeta.getConstructor().newInstance();
            } catch (Exception e) {
                throw new RuntimeException("路由分组映射表记录失败.", e);
            }
            iGroupInstance.loadInto(Warehouse.routes);
            //已经准备过了就可以移除了 (不会一直存在内存中)
            Warehouse.groupsIndex.remove(card.getGroup());
            //再次进入 else
            prepareCard(card);
        } else {
            //类 要跳转的activity 或IService实现类
            card.setDestination(routeMeta.getDestination());
            card.setType(routeMeta.getType());
            switch (routeMeta.getType()) {
                case ISERVICE:
                    Class<?> destination = routeMeta.getDestination();
                    IService service = Warehouse.services.get(destination);
                    if (null == service) {
                        try {
                            service = (IService) destination.getConstructor().newInstance();
                            Warehouse.services.put(destination, service);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    card.setService(service);
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 注入
     *
     * @param instance
     */
    public void inject(Activity instance) {
        ExtraManager.getInstance().loadExtras(instance);
    }
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/ExtraManager.java
================================================
package com.xsm.easy.core;

import android.app.Activity;
import android.util.LruCache;

import com.xsm.easy.core.template.IExtra;

/**
 * Author: 夏胜明
 * Date: 2018/4/25 0025
 * Email: xiasem@163.com
 * Description:
 */

public class ExtraManager {
    public static final String SUFFIX_AUTOWIRED = "_Extra";
    private static ExtraManager instance;
    private LruCache<String, IExtra> classCache;

    public static ExtraManager getInstance() {
        if (instance == null) {
            synchronized (ExtraManager.class) {
                if (instance == null) {
                    instance = new ExtraManager();
                }
            }
        }
        return instance;
    }


    public ExtraManager() {
        classCache = new LruCache<>(66);
    }


    /**
     * 注入
     *
     * @param instance
     */
    public void loadExtras(Activity instance) {
        //查找对应activity的缓存
        String className = instance.getClass().getName();
        IExtra iExtra = classCache.get(className);
        try {
            if (null == iExtra) {
                iExtra = (IExtra) Class.forName(instance.getClass().getName() +
                        SUFFIX_AUTOWIRED).getConstructor().newInstance();
            }
            iExtra.loadExtra(instance);
            classCache.put(className, iExtra);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/Postcard.java
================================================
package com.xsm.easy.core;

import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityOptionsCompat;

import com.xsm.easy.annotation.modle.RouteMeta;
import com.xsm.easy.core.callback.NavigationCallback;
import com.xsm.easy.core.template.IService;

import java.util.ArrayList;

/**
 * Author: 夏胜明
 * Date: 2018/4/24 0024
 * Email: xiasem@163.com
 * Description:
 */

public class Postcard extends RouteMeta {
    private Bundle mBundle;
    private int flags = -1;
    //新版风格
    private Bundle optionsCompat;
    //老版
    private int enterAnim;
    private int exitAnim;

    //服务
    private IService service;

    public Postcard(String path, String group) {
        this(path, group, null);
    }

    public Postcard(String path, String group, Bundle bundle) {
        setPath(path);
        setGroup(group);
        this.mBundle = (null == bundle ? new Bundle() : bundle);
    }

    public Bundle getExtras() {return mBundle;}

    public int getEnterAnim() {return enterAnim;}

    public int getExitAnim() {return exitAnim;}

    public IService getService() {
        return service;
    }

    public void setService(IService service) {
        this.service = service;
    }

    /**
     * Intent.FLAG_ACTIVITY**
     * @param flag
     * @return
     */
    public Postcard withFlags(int flag) {
        this.flags = flag;
        return this;
    }

    public int getFlags() {
        return flags;
    }

    /**
     * 跳转动画
     *
     * @param enterAnim
     * @param exitAnim
     * @return
     */
    public Postcard withTransition(int enterAnim, int exitAnim) {
        this.enterAnim = enterAnim;
        this.exitAnim = exitAnim;
        return this;
    }

    /**
     * 转场动画
     *
     * @param compat
     * @return
     */
    public Postcard withOptionsCompat(ActivityOptionsCompat compat) {
        if (null != compat) {
            this.optionsCompat = compat.toBundle();
        }
        return this;
    }

    public Postcard withString(@Nullable String key, @Nullable String value) {
        mBundle.putString(key, value);
        return this;
    }


    public Postcard withBoolean(@Nullable String key, boolean value) {
        mBundle.putBoolean(key, value);
        return this;
    }


    public Postcard withShort(@Nullable String key, short value) {
        mBundle.putShort(key, value);
        return this;
    }


    public Postcard withInt(@Nullable String key, int value) {
        mBundle.putInt(key, value);
        return this;
    }


    public Postcard withLong(@Nullable String key, long value) {
        mBundle.putLong(key, value);
        return this;
    }


    public Postcard withDouble(@Nullable String key, double value) {
        mBundle.putDouble(key, value);
        return this;
    }


    public Postcard withByte(@Nullable String key, byte value) {
        mBundle.putByte(key, value);
        return this;
    }


    public Postcard withChar(@Nullable String key, char value) {
        mBundle.putChar(key, value);
        return this;
    }


    public Postcard withFloat(@Nullable String key, float value) {
        mBundle.putFloat(key, value);
        return this;
    }


    public Postcard withParcelable(@Nullable String key, @Nullable Parcelable value) {
        mBundle.putParcelable(key, value);
        return this;
    }


    public Postcard withStringArray(@Nullable String key, @Nullable String[] value) {
        mBundle.putStringArray(key, value);
        return this;
    }


    public Postcard withBooleanArray(@Nullable String key, boolean[] value) {
        mBundle.putBooleanArray(key, value);
        return this;
    }


    public Postcard withShortArray(@Nullable String key, short[] value) {
        mBundle.putShortArray(key, value);
        return this;
    }


    public Postcard withIntArray(@Nullable String key, int[] value) {
        mBundle.putIntArray(key, value);
        return this;
    }


    public Postcard withLongArray(@Nullable String key, long[] value) {
        mBundle.putLongArray(key, value);
        return this;
    }


    public Postcard withDoubleArray(@Nullable String key, double[] value) {
        mBundle.putDoubleArray(key, value);
        return this;
    }


    public Postcard withByteArray(@Nullable String key, byte[] value) {
        mBundle.putByteArray(key, value);
        return this;
    }


    public Postcard withCharArray(@Nullable String key, char[] value) {
        mBundle.putCharArray(key, value);
        return this;
    }


    public Postcard withFloatArray(@Nullable String key, float[] value) {
        mBundle.putFloatArray(key, value);
        return this;
    }


    public Postcard withParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
        mBundle.putParcelableArray(key, value);
        return this;
    }

    public Postcard withParcelableArrayList(@Nullable String key, @Nullable ArrayList<? extends
            Parcelable> value) {
        mBundle.putParcelableArrayList(key, value);
        return this;
    }

    public Postcard withIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
        mBundle.putIntegerArrayList(key, value);
        return this;
    }

    public Postcard withStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
        mBundle.putStringArrayList(key, value);
        return this;
    }

    public Bundle getOptionsBundle() {
        return optionsCompat;
    }

    public Object navigation() {
        return EasyRouter.getsInstance().navigation(null, this, -1, null);
    }

    public Object navigation(Context context) {
        return EasyRouter.getsInstance().navigation(context, this, -1, null);
    }


    public Object navigation(Context context, NavigationCallback callback) {
        return EasyRouter.getsInstance().navigation(context, this, -1, callback);
    }

    public Object navigation(Context context, int requestCode) {
        return EasyRouter.getsInstance().navigation(context, this, requestCode, null);
    }

    public Object navigation(Context context, int requestCode, NavigationCallback callback) {
        return EasyRouter.getsInstance().navigation(context, this, requestCode, callback);
    }


}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/Warehouse.java
================================================
package com.xsm.easy.core;

import com.xsm.easy.annotation.modle.RouteMeta;
import com.xsm.easy.core.template.IInterceptor;
import com.xsm.easy.core.template.IRouteGroup;
import com.xsm.easy.core.template.IService;
import com.xsm.easy.core.utils.UniqueKeyTreeMap;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author: 夏胜明
 * Date: 2018/4/24 0024
 * Email: xiasem@163.com
 * Description:
 */

public class Warehouse {

    // root 映射表 保存分组信息
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();

    // group 映射表 保存组中的所有数据
    static Map<String, RouteMeta> routes = new HashMap<>();

    // group 映射表 保存组中的所有数据
    static Map<Class, IService> services = new HashMap<>();
    // TestServiceImpl.class , TestServiceImpl 没有再反射

    /**
     * 以键值对优先级的方式保存拦截器对象
     */
    public static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>();
    /**
     * 以集合的方式保存所有拦截器对象
     */
    public static List<IInterceptor> interceptors = new ArrayList<>();
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/callback/InterceptorCallback.java
================================================
package com.xsm.easy.core.callback;

import com.xsm.easy.core.Postcard;

/**
 * @author: luoxiaohui
 * @date: 2019-05-23 20:41
 * @desc: 拦截器回调
 */
public interface InterceptorCallback {

    /**
     * 未拦截,走正常流程
     * @author luoxiaohui
     * @createTime 2019-05-23 20:50
     */
    void onNext(Postcard postcard);

    /**
     * 拦截器拦截成功,中断流程
     * @author luoxiaohui
     * @createTime 2019-05-23 20:42
     */
    void onInterrupt(String interruptMsg);
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/callback/NavigationCallback.java
================================================
package com.xsm.easy.core.callback;

import com.xsm.easy.core.Postcard;

/**
 * Author: 夏胜明
 * Date: 2018/4/25 0025
 * Email: xiasem@163.com
 * Description:
 */

public interface NavigationCallback {

    /**
     * 找到跳转页面
     * @param postcard
     */
    void onFound(Postcard postcard);

    /**
     * 未找到
     * @param postcard
     */
    void onLost(Postcard postcard);

    /**
     * 成功跳转
     * @param postcard
     */
    void onArrival(Postcard postcard);

    /**
     * 中断了路由跳转
     * @author luoxiaohui
     * @createTime 2019-06-18 17:00
     */
    void onInterrupt(Throwable throwable);
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/exception/NoRouteFoundException.java
================================================
package com.xsm.easy.core.exception;

/**
 * Author: 夏胜明
 * Date: 2018/4/25 0025
 * Email: xiasem@163.com
 * Description:
 */

public class NoRouteFoundException extends RuntimeException {

    public NoRouteFoundException(String detailMessage) {
        super(detailMessage);
    }
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/implments/InterceptorImpl.java
================================================
package com.xsm.easy.core.implments;

import android.content.Context;

import com.xsm.easy.core.Postcard;
import com.xsm.easy.core.Warehouse;
import com.xsm.easy.core.callback.InterceptorCallback;
import com.xsm.easy.core.template.IInterceptor;
import com.xsm.easy.core.thread.DefaultPoolExecutor;
import com.xsm.easy.core.utils.CancelableCountDownLatch;
import com.xsm.easy.core.utils.Utils;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: luoxiaohui
 * @date: 2019-06-18 14:08
 * @desc: 拦截器实现,在初始化路由,以及调用路由时,都需要调用到此类
 */
public class InterceptorImpl {

    /**
     * 初始化路由时,需要轮询每个拦截器中的init()方法
     *
     * @author luoxiaohui
     * @createTime 2019-06-18 14:10
     */
    public static void init(final Context context) {

        DefaultPoolExecutor.executor.execute(new Runnable() {
            @Override
            public void run() {
                if (!Utils.isEmpty(Warehouse.interceptorsIndex)) {
                    for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
                        Class<? extends IInterceptor> interceptorClass = entry.getValue();
                        try {
                            IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
                            iInterceptor.init(context);
                            Warehouse.interceptors.add(iInterceptor);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });
    }

    /**
     * 执行拦截逻辑
     *
     * @author luoxiaohui
     * @createTime 2019-06-18 14:56
     */
    public static void onInterceptions(final Postcard postcard, final InterceptorCallback callback) {

        if (Warehouse.interceptors.size() > 0) {
            DefaultPoolExecutor.executor.execute(new Runnable() {
                @Override
                public void run() {

                    CancelableCountDownLatch countDownLatch = new CancelableCountDownLatch(Warehouse.interceptors.size());
                    execute(0, countDownLatch, postcard);
                    try {
                        countDownLatch.await(300, TimeUnit.SECONDS);
                        if (countDownLatch.getCount() > 0){

                            callback.onInterrupt("拦截器处理超时");
                        }else if(!Utils.isEmpty(countDownLatch.getMsg())){

                            callback.onInterrupt(countDownLatch.getMsg());
                        }else {

                            callback.onNext(postcard);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        } else {

            callback.onNext(postcard);
        }
    }


    /**
     * 以递归的方式走完所有拦截器的process()方法
     *
     * @author luoxiaohui
     * @createTime 2019-06-18 15:22
     */
    private static void execute(final int index, final CancelableCountDownLatch countDownLatch, final Postcard postcard) {
        if (index < Warehouse.interceptors.size()){

            IInterceptor iInterceptor = Warehouse.interceptors.get(index);
            iInterceptor.process(postcard, new InterceptorCallback() {
                @Override
                public void onNext(Postcard postcard) {

                    countDownLatch.countDown();
                    execute(index + 1, countDownLatch, postcard);
                }

                @Override
                public void onInterrupt(String msg) {

                    countDownLatch.cancel(msg);
                }
            });
        }
    }
}


































================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/template/IExtra.java
================================================
package com.xsm.easy.core.template;

/**
 * 注入
 */
public interface IExtra {
    void loadExtra(Object target);
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/template/IInterceptor.java
================================================
package com.xsm.easy.core.template;

import android.content.Context;

import com.xsm.easy.core.Postcard;
import com.xsm.easy.core.callback.InterceptorCallback;

/**
 * @author: luoxiaohui
 * @date: 2019-05-23 20:52
 * @desc:
 */
public interface IInterceptor {
    
    /**
     * 拦截器流程
     * @author luoxiaohui
     * @createTime 2019-05-23 20:53
     */
    void process(Postcard postcard, InterceptorCallback callback);

    /**
     * 在调用EasyRouter.init()初始化时,会调用到此方法
     * @author luoxiaohui
     * @createTime 2019-06-18 10:39
     */
    void init(Context context);
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/template/IInterceptorGroup.java
================================================
package com.xsm.easy.core.template;

import java.util.Map;

/**
 * @author: luoxiaohui
 * @date: 2019-05-23 20:36
 * @desc:
 */
public interface IInterceptorGroup {

    /**
     * key为拦截器的优先级,value为拦截器
     * @author luoxiaohui
     * @createTime 2019-05-23 20:54
     * @param map
     */
    void loadInto(Map<Integer, Class<? extends IInterceptor>> map);
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/template/IRouteGroup.java
================================================
package com.xsm.easy.core.template;

import com.xsm.easy.annotation.modle.RouteMeta;

import java.util.Map;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */

public interface IRouteGroup {
    void loadInto(Map<String, RouteMeta> atlas);
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/template/IRouteRoot.java
================================================
package com.xsm.easy.core.template;

import java.util.Map;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description:
 */

public interface IRouteRoot {
    void loadInto(Map<String, Class<? extends IRouteGroup>> routes);
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/template/IService.java
================================================
package com.xsm.easy.core.template;

/**
 * Author: 夏胜明
 * Date: 2018/3/29 0029
 * Email: xiasem@163.com
 * Description: 用于组件之间业务通信
 */

public interface IService {
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/thread/DefaultPoolExecutor.java
================================================
package com.xsm.easy.core.thread;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Author: 夏胜明
 * Date: 2018/4/3 0003
 * Email: xiasem@163.com
 * Description:
 */

public class DefaultPoolExecutor {

    public static ThreadPoolExecutor executor;
    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "EasyRouter #" + mCount.getAndIncrement());
        }
    };

    //核心线程和最大线程都是cpu核心数+1
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int MAX_CORE_POOL_SIZE = CPU_COUNT + 1;
    //存活30秒 回收线程
    private static final long SURPLUS_THREAD_LIFE = 30L;

    public static ThreadPoolExecutor newDefaultPoolExecutor(int corePoolSize) {
        if (corePoolSize == 0) {
            return null;
        }
        corePoolSize = Math.min(corePoolSize, MAX_CORE_POOL_SIZE);
        executor = new ThreadPoolExecutor(corePoolSize,
                corePoolSize, SURPLUS_THREAD_LIFE, TimeUnit.SECONDS, new
                ArrayBlockingQueue<Runnable>(64), sThreadFactory);
        //核心线程也会被销毁
        executor.allowCoreThreadTimeOut(true);
        return executor;
    }



}



























================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/utils/CancelableCountDownLatch.java
================================================
package com.xsm.easy.core.utils;

import java.util.concurrent.CountDownLatch;

/**
 * @author: luoxiaohui
 * @date: 2019-06-18 14:46
 * @desc:
 */
public class CancelableCountDownLatch extends CountDownLatch {

    private String msg = "";

    public CancelableCountDownLatch(int count) {
        super(count);
    }

    /**
     * 当遇到特殊情况时,需要将计步器清0
     *
     * @author luoxiaohui
     * @createTime 2019-06-18 14:47
     */
    public void cancel(String msg) {
        this.msg = msg;
        while (getCount() > 0) {
            countDown();
        }
    }

    public String getMsg(){
        return msg;
    }
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/utils/ClassUtils.java
================================================
package com.xsm.easy.core.utils;

import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;

import com.xsm.easy.core.thread.DefaultPoolExecutor;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;

import dalvik.system.DexFile;

/**
 * Author: 夏胜明
 * Date: 2018/4/3 0003
 * Email: xiasem@163.com
 * Description:
 */

public class ClassUtils {

    /**
     * 获得程序所有的apk(instant run会产生很多split apk)
     * @param context
     * @return
     * @throws PackageManager.NameNotFoundException
     */
    private static List<String> getSourcePaths(Context context) throws PackageManager.NameNotFoundException {
        ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
        List<String> sourcePaths = new ArrayList<>();
        sourcePaths.add(applicationInfo.sourceDir);
        //instant run
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (null != applicationInfo.splitSourceDirs) {
                sourcePaths.addAll(Arrays.asList(applicationInfo.splitSourceDirs));
            }
        }
        return sourcePaths;
    }

    /**
     * 得到路由表的类名
     * @param context
     * @param packageName
     * @return
     * @throws PackageManager.NameNotFoundException
     * @throws InterruptedException
     */
    public static Set<String> getFileNameByPackageName(Application context, final String packageName)
            throws PackageManager.NameNotFoundException, InterruptedException {
        final Set<String> classNames = new HashSet<>();
        List<String> paths = getSourcePaths(context);
        //使用同步计数器判断均处理完成
        final CountDownLatch countDownLatch = new CountDownLatch(paths.size());
        ThreadPoolExecutor threadPoolExecutor = DefaultPoolExecutor.newDefaultPoolExecutor(paths.size());
        for (final String path : paths) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    DexFile dexFile = null;
                    try {
                        //加载 apk中的dex 并遍历 获得所有包名为 {packageName} 的类
                        dexFile = new DexFile(path);
                        Enumeration<String> dexEntries = dexFile.entries();
                        while (dexEntries.hasMoreElements()) {
                            String className = dexEntries.nextElement();
                            if (!TextUtils.isEmpty(className) && className.startsWith(packageName)) {
                                classNames.add(className);
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (null != dexFile) {
                            try {
                                dexFile.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        //释放一个
                        countDownLatch.countDown();
                    }
                }
            });
        }
        //等待执行完成
        countDownLatch.await();
        return classNames;
    }


}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/utils/UniqueKeyTreeMap.java
================================================
package com.xsm.easy.core.utils;

import java.util.TreeMap;

/**
 * @author: luoxiaohui
 * @date: 2019-06-17 15:38
 * @desc: 主要用于拦截器优先级
 */
public class UniqueKeyTreeMap<K, V> extends TreeMap<K, V> {

    @Override
    public V put(K key, V value) {
        if (containsKey(key)){

            throw new RuntimeException("优先级为" + key + "的拦截器已经存在,不允许再次添加同级别的拦截器!");
        }else{

            return super.put(key, value);
        }
    }
}


================================================
FILE: easy-core/src/main/java/com/xsm/easy/core/utils/Utils.java
================================================
package com.xsm.easy.core.utils;

import java.util.Collection;
import java.util.Map;

/**
 * @author: luoxiaohui
 * @date: 2019-06-18 14:21
 * @desc: 判断集合,Map等是否为空
 */
public class Utils {

    public static boolean isEmpty(String str){
        return str == null || str.equals("") || str.isEmpty();
    }

    public static boolean isEmpty(Collection<?> coll) {
        return coll == null || coll.isEmpty();
    }

    public static boolean isEmpty(final Map<?, ?> map) {
        return map == null || map.isEmpty();
    }
}


================================================
FILE: easy-core/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">easy-core</string>
</resources>


================================================
FILE: easy-core/src/test/java/com/xsm/easy/core/ExampleUnitTest.java
================================================
package com.xsm.easy.core;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Tue Mar 27 09:07:20 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip


================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true


================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: module1/.gitignore
================================================
/build


================================================
FILE: module1/build.gradle
================================================
if (isModule) {
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

def cfg = rootProject.ext.android
def appId = rootProject.ext.appId

android {
    compileSdkVersion cfg.compileSdkVersion

    defaultConfig {
        if (!isModule) {
            applicationId appId.module1
        }
        minSdkVersion cfg.minSdkVersion
        targetSdkVersion cfg.targetSdkVersion
        versionCode cfg.versionCode
        versionName cfg.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }

        //添加一条 boolean类型的变量
        buildConfigField("boolean", "isModule", String.valueOf(isModule))

        sourceSets {
            main {
                if (isModule) {
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                } else {
                    manifest.srcFile 'src/main/module/AndroidManifest.xml'
                    java.srcDirs 'src/main/module/java', 'src/main/java'
                }
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    annotationProcessor project(':easy-compiler')
    implementation project(':base')
}


================================================
FILE: module1/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile


================================================
FILE: module1/src/androidTest/java/com/xsm/module1/ExampleInstrumentedTest.java
================================================
package com.xsm.module1;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.xsm.module1", appContext.getPackageName());
    }
}


================================================
FILE: module1/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.xsm.module1">

    <application>
        <activity android:name=".Module1MainActivity"/>
    </application>

</manifest>


================================================
FILE: module1/src/main/java/com/xsm/module1/LoginInterceptor.java
================================================
package com.xsm.module1;

import android.content.Context;
import android.util.Log;

import com.xsm.easy.annotation.Interceptor;
import com.xsm.easy.core.Postcard;
import com.xsm.easy.core.callback.InterceptorCallback;
import com.xsm.easy.core.template.IInterceptor;

/**
 * @author: luoxiaohui
 * @date: 2019-05-30 20:35
 * @desc:
 */
@Interceptor(priority = 1, name = "login")
public class LoginInterceptor implements IInterceptor {

    private static final String TAG = "LoginInterceptor";

    /**
     * 拦截器流程
     *
     * @param postcard
     * @param callback
     * @author luoxiaohui
     * @createTime 2019-05-23 20:53
     */
    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {

        Log.e(TAG, "process()...");
        callback.onNext(postcard);
    }

    /**
     * 在调用EasyRouter.init()初始化时,会调用到此方法
     *
     * @param context
     * @author luoxiaohui
     * @createTime 2019-06-18 10:39
     */
    @Override
    public void init(Context context) {

        Log.e(TAG, "init()...");
    }
}


================================================
FILE: module1/src/main/java/com/xsm/module1/Module1MainActivity.java
================================================
package com.xsm.module1;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import com.xsm.easy.annotation.Extra;
import com.xsm.easy.annotation.Route;
import com.xsm.easy.core.EasyRouter;

@Route(path = "/module1/module1main")
public class Module1MainActivity extends AppCompatActivity {

    @Extra
    String msg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_module1_main);
        EasyRouter.getsInstance().inject(this);
        Toast.makeText(this, "msg=" + msg, Toast.LENGTH_SHORT).show();

    }
}


================================================
FILE: module1/src/main/java/com/xsm/module1/Module1ProvidersImpl.java
================================================
package com.xsm.module1;

import com.xsm.base.providers.module1.Module1Providers;
import com.xsm.easy.annotation.Route;

/**
 * Author: 夏胜明
 * Date: 2018/8/20 0020
 * Email: xiasem@163.com
 * Description:
 */
@Route(path = "/module1/providers")
public class Module1ProvidersImpl implements Module1Providers {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

}


================================================
FILE: module1/src/main/module/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.xsm.module1">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Module1MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

================================================
FILE: module1/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportHeight="108"
    android:viewportWidth="108">
    <path
        android:fillColor="#26A69A"
        android:pathData="M0,0h108v108h-108z"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M9,0L9,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,0L19,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M29,0L29,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M39,0L39,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M49,0L49,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M59,0L59,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M69,0L69,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M79,0L79,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M89,0L89,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M99,0L99,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,9L108,9"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,19L108,19"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,29L108,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,39L108,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,49L108,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,59L108,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,69L108,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,79L108,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,89L108,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,99L108,99"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,29L89,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,39L89,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,49L89,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,59L89,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,69L89,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,79L89,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M29,19L29,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M39,19L39,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M49,19L49,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M59,19L59,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M69,19L69,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M79,19L79,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
</vector>


================================================
FILE: module1/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt"
        android:width="108dp"
        android:height="108dp"
        android:viewportHeight="108"
        android:viewportWidth="108">
    <path
        android:fillType="evenOdd"
        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="78.5885"
                android:endY="90.9159"
                android:startX="48.7653"
                android:startY="61.0927"
                android:type="linear">
                <item
                    android:color="#44000000"
                    android:offset="0.0"/>
                <item
                    android:color="#00000000"
                    android:offset="1.0"/>
            </gradient>
        </aapt:attr>
    </path>
    <path
        android:fillColor="#FFFFFF"
        android:fillType="nonZero"
        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1"/>
</vector>


================================================
FILE: module1/src/main/res/layout/activity_module1_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.xsm.module1.Module1MainActivity">

    <TextView
        android:text="Module1"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>


================================================
FILE: module1/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: module1/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: module1/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
</resources>


================================================
FILE: module1/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">Module1</string>
</resources>


================================================
FILE: module1/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>


================================================
FILE: module1/src/test/java/com/xsm/module1/ExampleUnitTest.java
================================================
package com.xsm.module1;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

================================================
FILE: module2/.gitignore
================================================
/build


================================================
FILE: module2/build.gradle
================================================
if (isModule) {
    apply plugin: 'com.android.library'
} else {
    apply plugin: 'com.android.application'
}

def cfg = rootProject.ext.android
def appId = rootProject.ext.appId

android {
    compileSdkVersion cfg.compileSdkVersion

    defaultConfig {
        if (!isModule) {
            applicationId appId.module2
        }
        minSdkVersion cfg.minSdkVersion
        targetSdkVersion cfg.targetSdkVersion
        versionCode cfg.versionCode
        versionName cfg.versionName
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }

        //添加一条 boolean类型的变量
        buildConfigField("boolean", "isModule", String.valueOf(isModule))

        sourceSets {
            main {
                if (isModule) {
                    manifest.srcFile 'src/main/AndroidManifest.xml'
                } else {
                    manifest.srcFile 'src/main/module/AndroidManifest.xml'
                    java.srcDirs 'src/main/module/java', 'src/main/java'
                }
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    annotationProcessor project(':easy-compiler')
    implementation project(':base')
}


================================================
FILE: module2/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile


================================================
FILE: module2/src/androidTest/java/com/xsm/module2/ExampleInstrumentedTest.java
================================================
package com.xsm.module2;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.xsm.module2", appContext.getPackageName());
    }
}


================================================
FILE: module2/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.xsm.module2">

    <application>
        <activity android:name=".Module2MainActivity"/>
    </application>

</manifest>


================================================
FILE: module2/src/main/java/com/xsm/module2/Module2MainActivity.java
================================================
package com.xsm.module2;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.xsm.easy.annotation.Route;

@Route(path = "/module2/module2main")
public class Module2MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_module2_main);
    }
}


================================================
FILE: module2/src/main/module/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.xsm.module2">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Module2MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

================================================
FILE: module2/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportHeight="108"
    android:viewportWidth="108">
    <path
        android:fillColor="#26A69A"
        android:pathData="M0,0h108v108h-108z"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M9,0L9,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,0L19,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M29,0L29,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M39,0L39,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M49,0L49,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M59,0L59,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M69,0L69,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M79,0L79,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M89,0L89,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M99,0L99,108"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,9L108,9"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,19L108,19"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,29L108,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,39L108,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,49L108,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,59L108,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,69L108,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,79L108,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,89L108,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M0,99L108,99"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,29L89,29"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,39L89,39"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,49L89,49"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,59L89,59"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,69L89,69"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M19,79L89,79"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M29,19L29,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M39,19L39,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M49,19L49,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M59,19L59,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M69,19L69,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
    <path
        android:fillColor="#00000000"
        android:pathData="M79,19L79,89"
        android:strokeColor="#33FFFFFF"
        android:strokeWidth="0.8"/>
</vector>


================================================
FILE: module2/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt"
        android:width="108dp"
        android:height="108dp"
        android:viewportHeight="108"
        android:viewportWidth="108">
    <path
        android:fillType="evenOdd"
        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="78.5885"
                android:endY="90.9159"
                android:startX="48.7653"
                android:startY="61.0927"
                android:type="linear">
                <item
                    android:color="#44000000"
                    android:offset="0.0"/>
                <item
                    android:color="#00000000"
                    android:offset="1.0"/>
            </gradient>
        </aapt:attr>
    </path>
    <path
        android:fillColor="#FFFFFF"
        android:fillType="nonZero"
        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
        android:strokeColor="#00000000"
        android:strokeWidth="1"/>
</vector>


================================================
FILE: module2/src/main/res/layout/activity_module2_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.xsm.module2.Module2MainActivity">

    <TextView
        android:text="Module2"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>


================================================
FILE: module2/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: module2/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background"/>
    <foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

================================================
FILE: module2/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
</resources>


================================================
FILE: module2/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">Module2</string>
</resources>


================================================
FILE: module2/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>


================================================
FILE: module2/src/test/java/com/xsm/module2/ExampleUnitTest.java
================================================
package com.xsm.module2;

import org.junit.Test;

import static org.junit.Assert.*;

/**
 * Example local unit test, which will execute on the development machine (host).
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

================================================
FILE: settings.gradle
================================================
include ':app', ':easy-compiler', ':easy-annotation', ':easy-core', ':module1', ':module2', ':base'
Download .txt
gitextract_n0f08trr/

├── .gitignore
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── easyrouter/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── easyrouter/
│       │   │               ├── BussinessInterceptor.java
│       │   │               ├── Main2Activity.java
│       │   │               ├── MainActivity.java
│       │   │               ├── ShowActivity.java
│       │   │               └── app/
│       │   │                   └── MyApplication.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   ├── activity_main.xml
│       │       │   ├── activity_main2.xml
│       │       │   └── activity_show.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easyrouter/
│                           └── ExampleUnitTest.java
├── base/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── base/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── base/
│       │   │               └── providers/
│       │   │                   └── module1/
│       │   │                       └── Module1Providers.java
│       │   └── res/
│       │       └── values/
│       │           └── strings.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── base/
│                           └── ExampleUnitTest.java
├── build.gradle
├── config.gradle
├── easy-annotation/
│   ├── .gitignore
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easy/
│                           └── annotation/
│                               ├── Extra.java
│                               ├── Interceptor.java
│                               ├── Route.java
│                               └── modle/
│                                   └── RouteMeta.java
├── easy-compiler/
│   ├── .gitignore
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easy/
│                           └── compiler/
│                               ├── processor/
│                               │   ├── ExtraProcessor.java
│                               │   ├── InterceptorProcessor.java
│                               │   └── RouterProcessor.java
│                               └── utils/
│                                   ├── Constant.java
│                                   ├── LoadExtraBuilder.java
│                                   ├── Log.java
│                                   └── Utils.java
├── easy-core/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── easy/
│       │                   └── core/
│       │                       └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── easy/
│       │   │               └── core/
│       │   │                   ├── EasyRouter.java
│       │   │                   ├── ExtraManager.java
│       │   │                   ├── Postcard.java
│       │   │                   ├── Warehouse.java
│       │   │                   ├── callback/
│       │   │                   │   ├── InterceptorCallback.java
│       │   │                   │   └── NavigationCallback.java
│       │   │                   ├── exception/
│       │   │                   │   └── NoRouteFoundException.java
│       │   │                   ├── implments/
│       │   │                   │   └── InterceptorImpl.java
│       │   │                   ├── template/
│       │   │                   │   ├── IExtra.java
│       │   │                   │   ├── IInterceptor.java
│       │   │                   │   ├── IInterceptorGroup.java
│       │   │                   │   ├── IRouteGroup.java
│       │   │                   │   ├── IRouteRoot.java
│       │   │                   │   └── IService.java
│       │   │                   ├── thread/
│       │   │                   │   └── DefaultPoolExecutor.java
│       │   │                   └── utils/
│       │   │                       ├── CancelableCountDownLatch.java
│       │   │                       ├── ClassUtils.java
│       │   │                       ├── UniqueKeyTreeMap.java
│       │   │                       └── Utils.java
│       │   └── res/
│       │       └── values/
│       │           └── strings.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── easy/
│                           └── core/
│                               └── ExampleUnitTest.java
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── module1/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── module1/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── module1/
│       │   │               ├── LoginInterceptor.java
│       │   │               ├── Module1MainActivity.java
│       │   │               └── Module1ProvidersImpl.java
│       │   ├── module/
│       │   │   └── AndroidManifest.xml
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   └── activity_module1_main.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── module1/
│                           └── ExampleUnitTest.java
├── module2/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── xsm/
│       │               └── module2/
│       │                   └── ExampleInstrumentedTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── xsm/
│       │   │           └── module2/
│       │   │               └── Module2MainActivity.java
│       │   ├── module/
│       │   │   └── AndroidManifest.xml
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   └── activity_module2_main.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── xsm/
│                       └── module2/
│                           └── ExampleUnitTest.java
└── settings.gradle
Download .txt
SYMBOL INDEX (198 symbols across 47 files)

FILE: app/src/androidTest/java/com/xsm/easyrouter/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 19) | @Test

FILE: app/src/main/java/com/xsm/easyrouter/BussinessInterceptor.java
  class BussinessInterceptor (line 16) | @Interceptor(priority = 2, name = "test")
    method process (line 29) | @Override
    method init (line 43) | @Override

FILE: app/src/main/java/com/xsm/easyrouter/Main2Activity.java
  class Main2Activity (line 8) | @Route(path = "/main/main2")
    method onCreate (line 11) | @Override

FILE: app/src/main/java/com/xsm/easyrouter/MainActivity.java
  class MainActivity (line 15) | @Route(path = "/main/main")
    method onCreate (line 21) | @Override
    method initProviders (line 28) | private void initProviders() {
    method startModule1MainActivity (line 32) | public void startModule1MainActivity(View view) {
    method startModule2MainActivity (line 38) | public void startModule2MainActivity(View view) {
    method add (line 63) | public void add(View view) {

FILE: app/src/main/java/com/xsm/easyrouter/ShowActivity.java
  class ShowActivity (line 8) | @Route(path = "/show/info")
    method onCreate (line 11) | @Override

FILE: app/src/main/java/com/xsm/easyrouter/app/MyApplication.java
  class MyApplication (line 13) | public class MyApplication extends Application {
    method onCreate (line 15) | @Override

FILE: app/src/test/java/com/xsm/easyrouter/ExampleUnitTest.java
  class ExampleUnitTest (line 12) | public class ExampleUnitTest {
    method addition_isCorrect (line 13) | @Test

FILE: base/src/androidTest/java/com/xsm/base/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 19) | @Test

FILE: base/src/main/java/com/xsm/base/providers/module1/Module1Providers.java
  type Module1Providers (line 11) | public interface Module1Providers extends IService {
    method add (line 13) | int add(int a, int b);

FILE: base/src/test/java/com/xsm/base/ExampleUnitTest.java
  class ExampleUnitTest (line 12) | public class ExampleUnitTest {
    method addition_isCorrect (line 13) | @Test

FILE: easy-annotation/src/main/java/com/xsm/easy/annotation/modle/RouteMeta.java
  class RouteMeta (line 14) | public class RouteMeta {
    type Type (line 15) | public enum Type {
    method build (line 40) | public static RouteMeta build(Type type, Class<?> destination, String ...
    method RouteMeta (line 45) | public RouteMeta() {
    method RouteMeta (line 48) | public RouteMeta(Type type, Route route, Element element) {
    method RouteMeta (line 52) | public RouteMeta(Type type, Element element, Class<?> destination, Str...
    method getType (line 62) | public Type getType() {
    method setType (line 66) | public void setType(Type type) {
    method getElement (line 70) | public Element getElement() {
    method setElement (line 74) | public void setElement(Element element) {
    method getDestination (line 78) | public Class<?> getDestination() {
    method setDestination (line 82) | public void setDestination(Class<?> destination) {
    method getPath (line 86) | public String getPath() {
    method setPath (line 90) | public void setPath(String path) {
    method getGroup (line 94) | public String getGroup() {
    method setGroup (line 98) | public void setGroup(String group) {

FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/processor/ExtraProcessor.java
  class ExtraProcessor (line 45) | @AutoService(Processor.class)
    method init (line 71) | @Override
    method process (line 81) | @Override
    method generateAutoWired (line 98) | private void generateAutoWired() throws IOException {
    method categories (line 140) | private void categories(Set<? extends Element> elements) {

FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/processor/InterceptorProcessor.java
  class InterceptorProcessor (line 42) | @AutoService(Processor.class)
    method init (line 68) | @Override
    method process (line 89) | @Override
    method parseInterceptor (line 109) | private void parseInterceptor(Set<? extends Element> elements) throws ...
    method verify (line 175) | private boolean verify(Element element) {

FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/processor/RouterProcessor.java
  class RouterProcessor (line 48) | @AutoService(Processor.class)
    method init (line 91) | @Override
    method process (line 117) | @Override
    method processorRoute (line 130) | private void processorRoute(Set<? extends Element> rootElements) {
    method generatedRoot (line 164) | private void generatedRoot(TypeElement iRouteRoot, TypeElement iRouteG...
    method generatedGroup (line 200) | private void generatedGroup(TypeElement iRouteGroup) {
    method categories (line 248) | private void categories(RouteMeta routeMeta) {
    method routeVerify (line 270) | private boolean routeVerify(RouteMeta routeMeta) {

FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Constant.java
  class Constant (line 12) | public class Constant {

FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/LoadExtraBuilder.java
  class LoadExtraBuilder (line 27) | public class LoadExtraBuilder {
    method LoadExtraBuilder (line 36) | public LoadExtraBuilder(ParameterSpec parameterSpec) {
    method setElementUtils (line 44) | public void setElementUtils(Elements elementUtils) {
    method setTypeUtils (line 50) | public void setTypeUtils(Types typeUtils) {
    method buildStatement (line 54) | public void buildStatement(Element element) {
    method addObjectStatement (line 101) | private void addObjectStatement(String statement, String fieldName, St...
    method addArrayStatement (line 161) | private void addArrayStatement(String statement, String fieldName, Str...
    method injectTarget (line 228) | public void injectTarget(ClassName className) {
    method build (line 233) | public MethodSpec build() {

FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Log.java
  class Log (line 13) | public class Log {
    method Log (line 16) | private Log(Messager messager) {
    method newLog (line 20) | public static Log newLog(Messager messager) {
    method i (line 24) | public void i(String msg) {

FILE: easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Utils.java
  class Utils (line 13) | public class Utils {
    method isEmpty (line 14) | public static boolean isEmpty(CharSequence cs) {
    method isEmpty (line 18) | public static boolean isEmpty(Collection<?> coll) {
    method isEmpty (line 22) | public static boolean isEmpty(final Map<?, ?> map) {

FILE: easy-core/src/androidTest/java/com/xsm/easy/core/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 19) | @Test

FILE: easy-core/src/main/java/com/xsm/easy/core/EasyRouter.java
  class EasyRouter (line 37) | public class EasyRouter {
    method EasyRouter (line 49) | private EasyRouter() {
    method getsInstance (line 53) | public static EasyRouter getsInstance() {
    method init (line 64) | public static void init(Application application) {
    method loadInfo (line 79) | private static void loadInfo() throws PackageManager.NameNotFoundExcep...
    method build (line 97) | public Postcard build(String path) {
    method build (line 105) | public Postcard build(String path, String group) {
    method extractGroup (line 119) | private String extractGroup(String path) {
    method navigation (line 136) | protected Object navigation(final Context context, final Postcard post...
    method _navigation (line 160) | protected Object _navigation(final Context context, final Postcard pos...
    method prepareCard (line 225) | private void prepareCard(Postcard card) {
    method inject (line 272) | public void inject(Activity instance) {

FILE: easy-core/src/main/java/com/xsm/easy/core/ExtraManager.java
  class ExtraManager (line 15) | public class ExtraManager {
    method getInstance (line 20) | public static ExtraManager getInstance() {
    method ExtraManager (line 32) | public ExtraManager() {
    method loadExtras (line 42) | public void loadExtras(Activity instance) {

FILE: easy-core/src/main/java/com/xsm/easy/core/Postcard.java
  class Postcard (line 22) | public class Postcard extends RouteMeta {
    method Postcard (line 34) | public Postcard(String path, String group) {
    method Postcard (line 38) | public Postcard(String path, String group, Bundle bundle) {
    method getExtras (line 44) | public Bundle getExtras() {return mBundle;}
    method getEnterAnim (line 46) | public int getEnterAnim() {return enterAnim;}
    method getExitAnim (line 48) | public int getExitAnim() {return exitAnim;}
    method getService (line 50) | public IService getService() {
    method setService (line 54) | public void setService(IService service) {
    method withFlags (line 63) | public Postcard withFlags(int flag) {
    method getFlags (line 68) | public int getFlags() {
    method withTransition (line 79) | public Postcard withTransition(int enterAnim, int exitAnim) {
    method withOptionsCompat (line 91) | public Postcard withOptionsCompat(ActivityOptionsCompat compat) {
    method withString (line 98) | public Postcard withString(@Nullable String key, @Nullable String valu...
    method withBoolean (line 104) | public Postcard withBoolean(@Nullable String key, boolean value) {
    method withShort (line 110) | public Postcard withShort(@Nullable String key, short value) {
    method withInt (line 116) | public Postcard withInt(@Nullable String key, int value) {
    method withLong (line 122) | public Postcard withLong(@Nullable String key, long value) {
    method withDouble (line 128) | public Postcard withDouble(@Nullable String key, double value) {
    method withByte (line 134) | public Postcard withByte(@Nullable String key, byte value) {
    method withChar (line 140) | public Postcard withChar(@Nullable String key, char value) {
    method withFloat (line 146) | public Postcard withFloat(@Nullable String key, float value) {
    method withParcelable (line 152) | public Postcard withParcelable(@Nullable String key, @Nullable Parcela...
    method withStringArray (line 158) | public Postcard withStringArray(@Nullable String key, @Nullable String...
    method withBooleanArray (line 164) | public Postcard withBooleanArray(@Nullable String key, boolean[] value) {
    method withShortArray (line 170) | public Postcard withShortArray(@Nullable String key, short[] value) {
    method withIntArray (line 176) | public Postcard withIntArray(@Nullable String key, int[] value) {
    method withLongArray (line 182) | public Postcard withLongArray(@Nullable String key, long[] value) {
    method withDoubleArray (line 188) | public Postcard withDoubleArray(@Nullable String key, double[] value) {
    method withByteArray (line 194) | public Postcard withByteArray(@Nullable String key, byte[] value) {
    method withCharArray (line 200) | public Postcard withCharArray(@Nullable String key, char[] value) {
    method withFloatArray (line 206) | public Postcard withFloatArray(@Nullable String key, float[] value) {
    method withParcelableArray (line 212) | public Postcard withParcelableArray(@Nullable String key, @Nullable Pa...
    method withParcelableArrayList (line 217) | public Postcard withParcelableArrayList(@Nullable String key, @Nullabl...
    method withIntegerArrayList (line 223) | public Postcard withIntegerArrayList(@Nullable String key, @Nullable A...
    method withStringArrayList (line 228) | public Postcard withStringArrayList(@Nullable String key, @Nullable Ar...
    method getOptionsBundle (line 233) | public Bundle getOptionsBundle() {
    method navigation (line 237) | public Object navigation() {
    method navigation (line 241) | public Object navigation(Context context) {
    method navigation (line 246) | public Object navigation(Context context, NavigationCallback callback) {
    method navigation (line 250) | public Object navigation(Context context, int requestCode) {
    method navigation (line 254) | public Object navigation(Context context, int requestCode, NavigationC...

FILE: easy-core/src/main/java/com/xsm/easy/core/Warehouse.java
  class Warehouse (line 21) | public class Warehouse {

FILE: easy-core/src/main/java/com/xsm/easy/core/callback/InterceptorCallback.java
  type InterceptorCallback (line 10) | public interface InterceptorCallback {
    method onNext (line 17) | void onNext(Postcard postcard);
    method onInterrupt (line 24) | void onInterrupt(String interruptMsg);

FILE: easy-core/src/main/java/com/xsm/easy/core/callback/NavigationCallback.java
  type NavigationCallback (line 12) | public interface NavigationCallback {
    method onFound (line 18) | void onFound(Postcard postcard);
    method onLost (line 24) | void onLost(Postcard postcard);
    method onArrival (line 30) | void onArrival(Postcard postcard);
    method onInterrupt (line 37) | void onInterrupt(Throwable throwable);

FILE: easy-core/src/main/java/com/xsm/easy/core/exception/NoRouteFoundException.java
  class NoRouteFoundException (line 10) | public class NoRouteFoundException extends RuntimeException {
    method NoRouteFoundException (line 12) | public NoRouteFoundException(String detailMessage) {

FILE: easy-core/src/main/java/com/xsm/easy/core/implments/InterceptorImpl.java
  class InterceptorImpl (line 22) | public class InterceptorImpl {
    method init (line 30) | public static void init(final Context context) {
    method onInterceptions (line 57) | public static void onInterceptions(final Postcard postcard, final Inte...
    method execute (line 96) | private static void execute(final int index, final CancelableCountDown...

FILE: easy-core/src/main/java/com/xsm/easy/core/template/IExtra.java
  type IExtra (line 6) | public interface IExtra {
    method loadExtra (line 7) | void loadExtra(Object target);

FILE: easy-core/src/main/java/com/xsm/easy/core/template/IInterceptor.java
  type IInterceptor (line 13) | public interface IInterceptor {
    method process (line 20) | void process(Postcard postcard, InterceptorCallback callback);
    method init (line 27) | void init(Context context);

FILE: easy-core/src/main/java/com/xsm/easy/core/template/IInterceptorGroup.java
  type IInterceptorGroup (line 10) | public interface IInterceptorGroup {
    method loadInto (line 18) | void loadInto(Map<Integer, Class<? extends IInterceptor>> map);

FILE: easy-core/src/main/java/com/xsm/easy/core/template/IRouteGroup.java
  type IRouteGroup (line 14) | public interface IRouteGroup {
    method loadInto (line 15) | void loadInto(Map<String, RouteMeta> atlas);

FILE: easy-core/src/main/java/com/xsm/easy/core/template/IRouteRoot.java
  type IRouteRoot (line 12) | public interface IRouteRoot {
    method loadInto (line 13) | void loadInto(Map<String, Class<? extends IRouteGroup>> routes);

FILE: easy-core/src/main/java/com/xsm/easy/core/template/IService.java
  type IService (line 10) | public interface IService {

FILE: easy-core/src/main/java/com/xsm/easy/core/thread/DefaultPoolExecutor.java
  class DefaultPoolExecutor (line 16) | public class DefaultPoolExecutor {
    method newThread (line 22) | @Override
    method newDefaultPoolExecutor (line 34) | public static ThreadPoolExecutor newDefaultPoolExecutor(int corePoolSi...

FILE: easy-core/src/main/java/com/xsm/easy/core/utils/CancelableCountDownLatch.java
  class CancelableCountDownLatch (line 10) | public class CancelableCountDownLatch extends CountDownLatch {
    method CancelableCountDownLatch (line 14) | public CancelableCountDownLatch(int count) {
    method cancel (line 24) | public void cancel(String msg) {
    method getMsg (line 31) | public String getMsg(){

FILE: easy-core/src/main/java/com/xsm/easy/core/utils/ClassUtils.java
  class ClassUtils (line 31) | public class ClassUtils {
    method getSourcePaths (line 39) | private static List<String> getSourcePaths(Context context) throws Pac...
    method getFileNameByPackageName (line 60) | public static Set<String> getFileNameByPackageName(Application context...

FILE: easy-core/src/main/java/com/xsm/easy/core/utils/UniqueKeyTreeMap.java
  class UniqueKeyTreeMap (line 10) | public class UniqueKeyTreeMap<K, V> extends TreeMap<K, V> {
    method put (line 12) | @Override

FILE: easy-core/src/main/java/com/xsm/easy/core/utils/Utils.java
  class Utils (line 11) | public class Utils {
    method isEmpty (line 13) | public static boolean isEmpty(String str){
    method isEmpty (line 17) | public static boolean isEmpty(Collection<?> coll) {
    method isEmpty (line 21) | public static boolean isEmpty(final Map<?, ?> map) {

FILE: easy-core/src/test/java/com/xsm/easy/core/ExampleUnitTest.java
  class ExampleUnitTest (line 12) | public class ExampleUnitTest {
    method addition_isCorrect (line 13) | @Test

FILE: module1/src/androidTest/java/com/xsm/module1/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 19) | @Test

FILE: module1/src/main/java/com/xsm/module1/LoginInterceptor.java
  class LoginInterceptor (line 16) | @Interceptor(priority = 1, name = "login")
    method process (line 29) | @Override
    method init (line 43) | @Override

FILE: module1/src/main/java/com/xsm/module1/Module1MainActivity.java
  class Module1MainActivity (line 11) | @Route(path = "/module1/module1main")
    method onCreate (line 17) | @Override

FILE: module1/src/main/java/com/xsm/module1/Module1ProvidersImpl.java
  class Module1ProvidersImpl (line 12) | @Route(path = "/module1/providers")
    method add (line 15) | @Override

FILE: module1/src/test/java/com/xsm/module1/ExampleUnitTest.java
  class ExampleUnitTest (line 12) | public class ExampleUnitTest {
    method addition_isCorrect (line 13) | @Test

FILE: module2/src/androidTest/java/com/xsm/module2/ExampleInstrumentedTest.java
  class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
    method useAppContext (line 19) | @Test

FILE: module2/src/main/java/com/xsm/module2/Module2MainActivity.java
  class Module2MainActivity (line 8) | @Route(path = "/module2/module2main")
    method onCreate (line 11) | @Override

FILE: module2/src/test/java/com/xsm/module2/ExampleUnitTest.java
  class ExampleUnitTest (line 12) | public class ExampleUnitTest {
    method addition_isCorrect (line 13) | @Test
Condensed preview — 114 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (160K chars).
[
  {
    "path": ".gitignore",
    "chars": 362,
    "preview": "# Intellij IDEA\n.idea/\n*.iml\n*.ipr\n*.iws\nout/\n\n# Gradle build folder\nbuild/\n.gradle/\n\n# Android\nlocal.properties\nbin/\nge"
  },
  {
    "path": "README.md",
    "chars": 1982,
    "preview": "### 简介\n路由在项目中用了很长一段时间了,一直用的ARouter,很早的时候,我就把ARouter里里外外研究了一番,可以说里面干货多多,但时间长了就有些记不住了,甚至一些技术点都记的混淆了。\n于是便萌生了写一篇技术博客的想法,后来又觉"
  },
  {
    "path": "app/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "chars": 1336,
    "preview": "apply plugin: 'com.android.application'\n\ndef cfg = rootProject.ext.android\ndef appId = rootProject.ext.appId\n\nandroid {\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "app/src/androidTest/java/com/xsm/easyrouter/ExampleInstrumentedTest.java",
    "chars": 737,
    "preview": "package com.xsm.easyrouter;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 860,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          pa"
  },
  {
    "path": "app/src/main/java/com/xsm/easyrouter/BussinessInterceptor.java",
    "chars": 1059,
    "preview": "package com.xsm.easyrouter;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport com.xsm.easy.annotation.In"
  },
  {
    "path": "app/src/main/java/com/xsm/easyrouter/Main2Activity.java",
    "chars": 401,
    "preview": "package com.xsm.easyrouter;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\n\nimport com.xsm."
  },
  {
    "path": "app/src/main/java/com/xsm/easyrouter/MainActivity.java",
    "chars": 1974,
    "preview": "package com.xsm.easyrouter;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.u"
  },
  {
    "path": "app/src/main/java/com/xsm/easyrouter/ShowActivity.java",
    "chars": 398,
    "preview": "package com.xsm.easyrouter;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\n\nimport com.xsm."
  },
  {
    "path": "app/src/main/java/com/xsm/easyrouter/app/MyApplication.java",
    "chars": 350,
    "preview": "package com.xsm.easyrouter.app;\n\nimport android.app.Application;\n\nimport com.xsm.easy.core.EasyRouter;\n\n/**\n * Author: 夏"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5577,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    androi"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1897,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "chars": 963,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    "
  },
  {
    "path": "app/src/main/res/layout/activity_main2.xml",
    "chars": 385,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    "
  },
  {
    "path": "app/src/main/res/layout/activity_show.xml",
    "chars": 375,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    andr"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"color"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "chars": 73,
    "preview": "<resources>\n    <string name=\"app_name\">EasyRouter</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "chars": 383,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "app/src/test/java/com/xsm/easyrouter/ExampleUnitTest.java",
    "chars": 396,
    "preview": "package com.xsm.easyrouter;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, "
  },
  {
    "path": "base/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "base/build.gradle",
    "chars": 969,
    "preview": "apply plugin: 'com.android.library'\n\ndef cfg = rootProject.ext.android\ndef librarys = rootProject.ext.dependencies\n\nandr"
  },
  {
    "path": "base/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "base/src/androidTest/java/com/xsm/base/ExampleInstrumentedTest.java",
    "chars": 730,
    "preview": "package com.xsm.base;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport andro"
  },
  {
    "path": "base/src/main/AndroidManifest.xml",
    "chars": 104,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.xsm.base\"/>\n"
  },
  {
    "path": "base/src/main/java/com/xsm/base/providers/module1/Module1Providers.java",
    "chars": 258,
    "preview": "package com.xsm.base.providers.module1;\n\nimport com.xsm.easy.core.template.IService;\n\n/**\n * Author: 夏胜明\n * Date: 2018/8"
  },
  {
    "path": "base/src/main/res/values/strings.xml",
    "chars": 67,
    "preview": "<resources>\n    <string name=\"app_name\">base</string>\n</resources>\n"
  },
  {
    "path": "base/src/test/java/com/xsm/base/ExampleUnitTest.java",
    "chars": 390,
    "preview": "package com.xsm.base;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which "
  },
  {
    "path": "build.gradle",
    "chars": 603,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\n//相当于引入头文件 将 config"
  },
  {
    "path": "config.gradle",
    "chars": 530,
    "preview": "ext {\n    //true 集成模式 false 组件模式\n    isModule = true\n\n    android = [\n            compileSdkVersion:26,\n            minS"
  },
  {
    "path": "easy-annotation/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "easy-annotation/build.gradle",
    "chars": 165,
    "preview": "apply plugin: 'java-library'\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n}\n\nsourceCompa"
  },
  {
    "path": "easy-annotation/src/main/java/com/xsm/easy/annotation/Extra.java",
    "chars": 405,
    "preview": "package com.xsm.easy.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport"
  },
  {
    "path": "easy-annotation/src/main/java/com/xsm/easy/annotation/Interceptor.java",
    "chars": 595,
    "preview": "package com.xsm.easy.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport"
  },
  {
    "path": "easy-annotation/src/main/java/com/xsm/easy/annotation/Route.java",
    "chars": 525,
    "preview": "package com.xsm.easy.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport"
  },
  {
    "path": "easy-annotation/src/main/java/com/xsm/easy/annotation/modle/RouteMeta.java",
    "chars": 1896,
    "preview": "package com.xsm.easy.annotation.modle;\n\nimport com.xsm.easy.annotation.Route;\n\nimport javax.lang.model.element.Element;\n"
  },
  {
    "path": "easy-compiler/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "easy-compiler/build.gradle",
    "chars": 398,
    "preview": "apply plugin: 'java-library'\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementa"
  },
  {
    "path": "easy-compiler/src/main/java/com/xsm/easy/compiler/processor/ExtraProcessor.java",
    "chars": 5615,
    "preview": "package com.xsm.easy.compiler.processor;\n\nimport com.google.auto.service.AutoService;\nimport com.squareup.javapoet.Class"
  },
  {
    "path": "easy-compiler/src/main/java/com/xsm/easy/compiler/processor/InterceptorProcessor.java",
    "chars": 6402,
    "preview": "package com.xsm.easy.compiler.processor;\n\nimport com.google.auto.service.AutoService;\nimport com.squareup.javapoet.Class"
  },
  {
    "path": "easy-compiler/src/main/java/com/xsm/easy/compiler/processor/RouterProcessor.java",
    "chars": 10804,
    "preview": "package com.xsm.easy.compiler.processor;\n\nimport com.google.auto.service.AutoService;\nimport com.squareup.javapoet.Class"
  },
  {
    "path": "easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Constant.java",
    "chars": 3132,
    "preview": "package com.xsm.easy.compiler.utils;\n\nimport com.squareup.javapoet.ClassName;\n\n/**\n * Author: 夏胜明\n * Date: 2018/3/29 002"
  },
  {
    "path": "easy-compiler/src/main/java/com/xsm/easy/compiler/utils/LoadExtraBuilder.java",
    "chars": 9763,
    "preview": "package com.xsm.easy.compiler.utils;\n\nimport com.squareup.javapoet.ArrayTypeName;\nimport com.squareup.javapoet.ClassName"
  },
  {
    "path": "easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Log.java",
    "chars": 522,
    "preview": "package com.xsm.easy.compiler.utils;\n\nimport javax.annotation.processing.Messager;\nimport javax.tools.Diagnostic;\n\n/**\n "
  },
  {
    "path": "easy-compiler/src/main/java/com/xsm/easy/compiler/utils/Utils.java",
    "chars": 527,
    "preview": "package com.xsm.easy.compiler.utils;\n\nimport java.util.Collection;\nimport java.util.Map;\n\n/**\n * Author: 夏胜明\n * Date: 20"
  },
  {
    "path": "easy-core/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "easy-core/build.gradle",
    "chars": 986,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion 26\n\n\n\n    defaultConfig {\n        minSdkVersion 14\n"
  },
  {
    "path": "easy-core/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "easy-core/src/androidTest/java/com/xsm/easy/core/ExampleInstrumentedTest.java",
    "chars": 740,
    "preview": "package com.xsm.easy.core;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport "
  },
  {
    "path": "easy-core/src/main/AndroidManifest.xml",
    "chars": 109,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.xsm.easy.core\"/>\n"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/EasyRouter.java",
    "chars": 9857,
    "preview": "package com.xsm.easy.core;\n\nimport android.app.Activity;\nimport android.app.Application;\nimport android.content.Context;"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/ExtraManager.java",
    "chars": 1395,
    "preview": "package com.xsm.easy.core;\n\nimport android.app.Activity;\nimport android.util.LruCache;\n\nimport com.xsm.easy.core.templat"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/Postcard.java",
    "chars": 6325,
    "preview": "package com.xsm.easy.core;\n\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.os.Parcelable;\nimpo"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/Warehouse.java",
    "chars": 1078,
    "preview": "package com.xsm.easy.core;\n\nimport com.xsm.easy.annotation.modle.RouteMeta;\nimport com.xsm.easy.core.template.IIntercept"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/callback/InterceptorCallback.java",
    "chars": 462,
    "preview": "package com.xsm.easy.core.callback;\n\nimport com.xsm.easy.core.Postcard;\n\n/**\n * @author: luoxiaohui\n * @date: 2019-05-23"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/callback/NavigationCallback.java",
    "chars": 608,
    "preview": "package com.xsm.easy.core.callback;\n\nimport com.xsm.easy.core.Postcard;\n\n/**\n * Author: 夏胜明\n * Date: 2018/4/25 0025\n * E"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/exception/NoRouteFoundException.java",
    "chars": 285,
    "preview": "package com.xsm.easy.core.exception;\n\n/**\n * Author: 夏胜明\n * Date: 2018/4/25 0025\n * Email: xiasem@163.com\n * Description"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/implments/InterceptorImpl.java",
    "chars": 3809,
    "preview": "package com.xsm.easy.core.implments;\n\nimport android.content.Context;\n\nimport com.xsm.easy.core.Postcard;\nimport com.xsm"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/template/IExtra.java",
    "chars": 114,
    "preview": "package com.xsm.easy.core.template;\n\n/**\n * 注入\n */\npublic interface IExtra {\n    void loadExtra(Object target);\n}\n"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/template/IInterceptor.java",
    "chars": 577,
    "preview": "package com.xsm.easy.core.template;\n\nimport android.content.Context;\n\nimport com.xsm.easy.core.Postcard;\nimport com.xsm."
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/template/IInterceptorGroup.java",
    "chars": 361,
    "preview": "package com.xsm.easy.core.template;\n\nimport java.util.Map;\n\n/**\n * @author: luoxiaohui\n * @date: 2019-05-23 20:36\n * @de"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/template/IRouteGroup.java",
    "chars": 280,
    "preview": "package com.xsm.easy.core.template;\n\nimport com.xsm.easy.annotation.modle.RouteMeta;\n\nimport java.util.Map;\n\n/**\n * Auth"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/template/IRouteRoot.java",
    "chars": 250,
    "preview": "package com.xsm.easy.core.template;\n\nimport java.util.Map;\n\n/**\n * Author: 夏胜明\n * Date: 2018/3/29 0029\n * Email: xiasem@"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/template/IService.java",
    "chars": 167,
    "preview": "package com.xsm.easy.core.template;\n\n/**\n * Author: 夏胜明\n * Date: 2018/3/29 0029\n * Email: xiasem@163.com\n * Description:"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/thread/DefaultPoolExecutor.java",
    "chars": 1529,
    "preview": "package com.xsm.easy.core.thread;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.ThreadFac"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/utils/CancelableCountDownLatch.java",
    "chars": 621,
    "preview": "package com.xsm.easy.core.utils;\n\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * @author: luoxiaohui\n * @date: 2019"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/utils/ClassUtils.java",
    "chars": 3609,
    "preview": "package com.xsm.easy.core.utils;\n\nimport android.app.Application;\nimport android.content.Context;\nimport android.content"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/utils/UniqueKeyTreeMap.java",
    "chars": 441,
    "preview": "package com.xsm.easy.core.utils;\n\nimport java.util.TreeMap;\n\n/**\n * @author: luoxiaohui\n * @date: 2019-06-17 15:38\n * @d"
  },
  {
    "path": "easy-core/src/main/java/com/xsm/easy/core/utils/Utils.java",
    "chars": 527,
    "preview": "package com.xsm.easy.core.utils;\n\nimport java.util.Collection;\nimport java.util.Map;\n\n/**\n * @author: luoxiaohui\n * @dat"
  },
  {
    "path": "easy-core/src/main/res/values/strings.xml",
    "chars": 72,
    "preview": "<resources>\n    <string name=\"app_name\">easy-core</string>\n</resources>\n"
  },
  {
    "path": "easy-core/src/test/java/com/xsm/easy/core/ExampleUnitTest.java",
    "chars": 395,
    "preview": "package com.xsm.easy.core;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, w"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Tue Mar 27 09:07:20 CST 2018\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 730,
    "preview": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will o"
  },
  {
    "path": "gradlew",
    "chars": 4971,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2314,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem "
  },
  {
    "path": "module1/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "module1/build.gradle",
    "chars": 1813,
    "preview": "if (isModule) {\n    apply plugin: 'com.android.library'\n} else {\n    apply plugin: 'com.android.application'\n}\n\ndef cfg "
  },
  {
    "path": "module1/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "module1/src/androidTest/java/com/xsm/module1/ExampleInstrumentedTest.java",
    "chars": 731,
    "preview": "package com.xsm.module1;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport an"
  },
  {
    "path": "module1/src/main/AndroidManifest.xml",
    "chars": 213,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.xsm.module1\">\n\n    <applicat"
  },
  {
    "path": "module1/src/main/java/com/xsm/module1/LoginInterceptor.java",
    "chars": 1049,
    "preview": "package com.xsm.module1;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport com.xsm.easy.annotation.Inter"
  },
  {
    "path": "module1/src/main/java/com/xsm/module1/Module1MainActivity.java",
    "chars": 672,
    "preview": "package com.xsm.module1;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.widg"
  },
  {
    "path": "module1/src/main/java/com/xsm/module1/Module1ProvidersImpl.java",
    "chars": 390,
    "preview": "package com.xsm.module1;\n\nimport com.xsm.base.providers.module1.Module1Providers;\nimport com.xsm.easy.annotation.Route;\n"
  },
  {
    "path": "module1/src/main/module/AndroidManifest.xml",
    "chars": 721,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          pa"
  },
  {
    "path": "module1/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5577,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    androi"
  },
  {
    "path": "module1/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1897,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n"
  },
  {
    "path": "module1/src/main/res/layout/activity_module1_main.xml",
    "chars": 601,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    "
  },
  {
    "path": "module1/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "module1/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "module1/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"color"
  },
  {
    "path": "module1/src/main/res/values/strings.xml",
    "chars": 70,
    "preview": "<resources>\n    <string name=\"app_name\">Module1</string>\n</resources>\n"
  },
  {
    "path": "module1/src/main/res/values/styles.xml",
    "chars": 383,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "module1/src/test/java/com/xsm/module1/ExampleUnitTest.java",
    "chars": 393,
    "preview": "package com.xsm.module1;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, whi"
  },
  {
    "path": "module2/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "module2/build.gradle",
    "chars": 1874,
    "preview": "if (isModule) {\n    apply plugin: 'com.android.library'\n} else {\n    apply plugin: 'com.android.application'\n}\n\ndef cfg "
  },
  {
    "path": "module2/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "module2/src/androidTest/java/com/xsm/module2/ExampleInstrumentedTest.java",
    "chars": 731,
    "preview": "package com.xsm.module2;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport an"
  },
  {
    "path": "module2/src/main/AndroidManifest.xml",
    "chars": 213,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.xsm.module2\">\n\n    <applicat"
  },
  {
    "path": "module2/src/main/java/com/xsm/module2/Module2MainActivity.java",
    "chars": 420,
    "preview": "package com.xsm.module2;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\n\nimport com.xsm.eas"
  },
  {
    "path": "module2/src/main/module/AndroidManifest.xml",
    "chars": 721,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          pa"
  },
  {
    "path": "module2/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5577,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    androi"
  },
  {
    "path": "module2/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1897,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n"
  },
  {
    "path": "module2/src/main/res/layout/activity_module2_main.xml",
    "chars": 600,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    "
  },
  {
    "path": "module2/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "module2/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "module2/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"color"
  },
  {
    "path": "module2/src/main/res/values/strings.xml",
    "chars": 70,
    "preview": "<resources>\n    <string name=\"app_name\">Module2</string>\n</resources>\n"
  },
  {
    "path": "module2/src/main/res/values/styles.xml",
    "chars": 383,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "module2/src/test/java/com/xsm/module2/ExampleUnitTest.java",
    "chars": 393,
    "preview": "package com.xsm.module2;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, whi"
  },
  {
    "path": "settings.gradle",
    "chars": 100,
    "preview": "include ':app', ':easy-compiler', ':easy-annotation', ':easy-core', ':module1', ':module2', ':base'\n"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the Xiasm/EasyRouter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 114 files (137.0 KB), approximately 39.4k tokens, and a symbol index with 198 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!