Repository: HCDarren/DRouter
Branch: master
Commit: a2b02ee10977
Files: 106
Total size: 117.8 KB
Directory structure:
gitextract_w0jpccmc/
├── .gitignore
├── .idea/
│ ├── gradle.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── runConfigurations.xml
│ └── vcs.xml
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── darren/
│ │ └── drouter/
│ │ └── ExampleInstrumentedTest.kt
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── darren/
│ │ │ └── drouter/
│ │ │ ├── BaseApplication.java
│ │ │ └── MainActivity.java
│ │ └── res/
│ │ ├── drawable/
│ │ │ └── ic_launcher_background.xml
│ │ ├── drawable-v24/
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout/
│ │ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26/
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── darren/
│ └── drouter/
│ └── ExampleUnitTest.kt
├── base-core/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── base/
│ │ └── core/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ └── res/
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── com/
│ └── base/
│ └── core/
│ └── ExampleUnitTest.java
├── build.gradle
├── circle-module/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── example/
│ │ └── circle_module/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── circle_module/
│ │ │ ├── CircleAction.java
│ │ │ ├── CircleActivity.java
│ │ │ ├── CircleInterceptor.java
│ │ │ ├── CircleInterceptor1.java
│ │ │ └── CircleInterceptor2.java
│ │ └── res/
│ │ ├── layout/
│ │ │ └── activity_circle.xml
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── circle_module/
│ └── ExampleUnitTest.java
├── drouter-api/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── drouter/
│ │ └── api/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── drouter/
│ │ │ └── api/
│ │ │ ├── action/
│ │ │ │ ├── IRouterAction.java
│ │ │ │ ├── IRouterInterceptor.java
│ │ │ │ └── IRouterModule.java
│ │ │ ├── core/
│ │ │ │ ├── DRouter.java
│ │ │ │ └── RouterForward.java
│ │ │ ├── exception/
│ │ │ │ ├── InitException.java
│ │ │ │ ├── RouterActionException.java
│ │ │ │ └── RouterModuleException.java
│ │ │ ├── extra/
│ │ │ │ ├── ActionWrapper.java
│ │ │ │ ├── Consts.java
│ │ │ │ ├── DefaultLogger.java
│ │ │ │ ├── ErrorActionWrapper.java
│ │ │ │ └── ILogger.java
│ │ │ ├── interceptor/
│ │ │ │ ├── ActionInterceptor.java
│ │ │ │ ├── ActionInterceptorChain.java
│ │ │ │ ├── CallActionInterceptor.java
│ │ │ │ └── ErrorActionInterceptor.java
│ │ │ ├── result/
│ │ │ │ ├── ActionCallback.java
│ │ │ │ └── RouterResult.java
│ │ │ ├── thread/
│ │ │ │ ├── ActionPost.java
│ │ │ │ ├── ActionPostQueue.java
│ │ │ │ ├── AsyncPoster.java
│ │ │ │ ├── BackgroundPoster.java
│ │ │ │ ├── HandlerPoster.java
│ │ │ │ ├── Poster.java
│ │ │ │ └── PosterSupport.java
│ │ │ └── utils/
│ │ │ ├── ClassUtils.java
│ │ │ └── MapUtils.java
│ │ └── res/
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── com/
│ └── drouter/
│ └── api/
│ └── ExampleUnitTest.java
├── drouter-base/
│ ├── .gitignore
│ ├── build.gradle
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── drouter/
│ └── base/
│ ├── ThreadMode.java
│ └── annotation/
│ ├── Action.java
│ └── Interceptor.java
├── drouter-compiler/
│ ├── .gitignore
│ ├── build.gradle
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── drouter/
│ └── compiler/
│ ├── Consts.java
│ ├── InterceptorProcessor.java
│ ├── ModuleProcessor.java
│ └── util/
│ └── TextUtils.java
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── login-module/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── login/
│ │ └── module/
│ │ └── ExampleInstrumentedTest.java
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── login/
│ │ │ └── module/
│ │ │ ├── LoginAction.java
│ │ │ └── LoginActivity.java
│ │ └── res/
│ │ ├── layout/
│ │ │ └── activity_login.xml
│ │ └── values/
│ │ └── strings.xml
│ └── test/
│ └── java/
│ └── com/
│ └── login/
│ └── module/
│ └── ExampleUnitTest.java
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
================================================
FILE: .idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/base-core" />
<option value="$PROJECT_DIR$/circle-module" />
<option value="$PROJECT_DIR$/drouter-api" />
<option value="$PROJECT_DIR$/drouter-base" />
<option value="$PROJECT_DIR$/drouter-compiler" />
<option value="$PROJECT_DIR$/login-module" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownProjectSettings">
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true">
<PanelProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
</PanelProvider>
</PreviewSettings>
<ParserSettings gitHubSyntaxChange="false">
<PegdownExtensions>
<option name="ABBREVIATIONS" value="false" />
<option name="ANCHORLINKS" value="true" />
<option name="ASIDE" value="false" />
<option name="ATXHEADERSPACE" value="true" />
<option name="AUTOLINKS" value="true" />
<option name="DEFINITIONS" value="false" />
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
<option name="FENCED_CODE_BLOCKS" value="true" />
<option name="FOOTNOTES" value="false" />
<option name="HARDWRAPS" value="false" />
<option name="HTML_DEEP_PARSER" value="false" />
<option name="INSERTED" value="false" />
<option name="QUOTES" value="false" />
<option name="RELAXEDHRULES" value="true" />
<option name="SMARTS" value="false" />
<option name="STRIKETHROUGH" value="true" />
<option name="SUBSCRIPT" value="false" />
<option name="SUPERSCRIPT" value="false" />
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
<option name="SUPPRESS_INLINE_HTML" value="false" />
<option name="TABLES" value="true" />
<option name="TASKLISTITEMS" value="true" />
<option name="TOC" value="false" />
<option name="WIKILINKS" value="true" />
</PegdownExtensions>
<ParserOptions>
<option name="COMMONMARK_LISTS" value="true" />
<option name="DUMMY" value="false" />
<option name="EMOJI_SHORTCUTS" value="true" />
<option name="FLEXMARK_FRONT_MATTER" value="false" />
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
<option name="GFM_TABLE_RENDERING" value="true" />
<option name="GITBOOK_URL_ENCODING" value="false" />
<option name="GITHUB_EMOJI_URL" value="false" />
<option name="GITHUB_LISTS" value="false" />
<option name="GITHUB_WIKI_LINKS" value="true" />
<option name="JEKYLL_FRONT_MATTER" value="false" />
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
</ParserOptions>
</ParserSettings>
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false">
<GeneratorProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
</GeneratorProvider>
<headerTop />
<headerBottom />
<bodyTop />
<bodyBottom />
</HtmlSettings>
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssTextEnabled="false" isDynamicPageWidth="true">
<StylesheetProvider>
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
</StylesheetProvider>
<ScriptProviders />
<cssText />
</CssSettings>
<HtmlExportSettings updateOnSave="false" parentDir="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
<LinkMapSettings>
<textMaps />
</LinkMapSettings>
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="masterDetails">
<states>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>1.8</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>
================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/DRouter.iml" filepath="$PROJECT_DIR$/DRouter.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/base-core/base-core.iml" filepath="$PROJECT_DIR$/base-core/base-core.iml" />
<module fileurl="file://$PROJECT_DIR$/circle-module/circle-module.iml" filepath="$PROJECT_DIR$/circle-module/circle-module.iml" />
<module fileurl="file://$PROJECT_DIR$/drouter-api/drouter-api.iml" filepath="$PROJECT_DIR$/drouter-api/drouter-api.iml" />
<module fileurl="file://$PROJECT_DIR$/drouter-base/drouter-base.iml" filepath="$PROJECT_DIR$/drouter-base/drouter-base.iml" />
<module fileurl="file://$PROJECT_DIR$/drouter-compiler/drouter-compiler.iml" filepath="$PROJECT_DIR$/drouter-compiler/drouter-compiler.iml" />
<module fileurl="file://$PROJECT_DIR$/login-module/login-module.iml" filepath="$PROJECT_DIR$/login-module/login-module.iml" />
</modules>
</component>
</project>
================================================
FILE: .idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
================================================
FILE: README.md
================================================
# Android 平台多模块多组件开发的路由库
### **一. DRouter 基本介绍**
**1.** 该库所涉及到的类大概在 30 个左右,源码并不多相信我们都能读懂里面的内容,这里罗列一下源码中所涉及到的一些知识点:
  (1) 编译时注解自动生成 Module、Action 和 Intercepter
  (2) 线程、线程池、线程同步异步和 Handler
  (3) 责任链模式、享元模式、策略模式、模板模式 ...
**2.** 作为一个多模块的路由通信库,相信它已支持了所有跨模块通信的使用场景,功能介绍如下:
  (1) 支持依赖注入,可单独作为依赖注入框架使用
  (2) 支持线程切换和调度(原始线程,主线程,同步,异步)
  (3) 支持多模块工程下的所有跨模块通信使用场景
  (4) 支持添加多个拦截器,可根据优先级自定义拦截顺序
  (5) 支持权限和网络检测、登录拦截跳转和数据埋点等功能
**3.** 笔者阅读了大量的开源库源码,本库的所有代码思想都来自其中,很感激这些大牛的开源和分享精神:
  [(1) ARouter](https://github.com/alibaba/ARouter)
  [(2) butterknife](https://github.com/JakeWharton/butterknife)
  [(3) okhttp](https://github.com/square/okhttp)
  [(4) EventBus](https://github.com/greenrobot/EventBus)
  [(5) RxJava](https://github.com/ReactiveX/RxJava)
  [(6) retrofit](https://github.com/square/retrofit)
### **二. DRouter 基本使用**
1. 在需要跨模块通信的Module中添加依赖和配置
```
defaultConfig {
......
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
dependencies {
.......
annotationProcessor project(':drouter-compiler')
}
```
2. 初始化 SDK
```
public class BaseApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
// 开启 debug
DRouter.openDebug();
// 初始化且只能初始化一次,参数必须是 Application
DRouter.getInstance().init(this);
}
}
```
3. 在 Module 中创建需要执行的 Action
```
// path 必须是以在 gradle 中配置的 moduleName + "/" 开头,否则编译通不过。
// threadMode 支持 POSTING 、MAIN、BACKGROUND、ASYNC 默认情况下是 POSTING(原始线程)
@Action(path = "login/action", threadMode = ThreadMode.MAIN)
public class LoginAction implements IRouterAction {
@Override
public RouterResult invokeAction(Context context, Map<String, Object> requestData) {
// 通信执行方法支持所有场景,启动 Activity,Service,Provider,弹框,缓存数据,获取 Fragment 等等等等
Intent intent = new Intent(context, LoginActivity.class);
intent.putExtra("key", (String) requestData.get("key"));
context.startActivity(intent);
return new RouterResult.Builder().success().object(100).build();
}
}
```
4. 可在任意 Module 中执行跳转
```
// 根据 action 查询只执行对应方法,不处理返回回调,参数携带随意
DRouter.getInstance()
.action("login/action")
.context(this)
.param("key", "value")
.invokeAction();
// 根据 action 查询执行对应方法,并处理返回回调
DRouter.getInstance()
.action("circlemodule/test")
.context(this)
.invokeAction(new ActionCallback() {
@Override
public void onInterrupt() {
Log.e("TAG", "被拦截了");
}
@Override
public void onResult(RouterResult result) {
// 注意该方法的执行线程是由 Action 的 threadMode 决定的,也就是说和 Action 在同一个线程
Log.e("TAG", "result = " + result.toString());
}
});
```
5. 在任意模块下都可添加拦截
```
// priority 优先级越高,拦截器执行越优先
@Interceptor(priority = 18)
public class CircleInterceptor implements ActionInterceptor {
@Override
public void intercept(ActionChain chain) {
ActionPost actionPost = chain.action();
// 圈子详情页必须是要登录,如果没有登录即可拦截跳转到登录页面,否则继续往下执行。
if (chain.actionPath().equals("circlemodule/test")) {
Toast.makeText(actionPost.context, "拦截圈子,跳转到登录", Toast.LENGTH_LONG).show();
// 跳转到登录页面
DRouter.getInstance()
.action("login/action")
.context(actionPost.context)
.invokeAction();
// 这个方法调用后便会拦截整条链
chain.onInterrupt();
}
// 继续向下转发
chain.proceed(actionPost);
}
}
```
6.混淆配置
```
-keep public class com.drouter.assist.**{*;}
```
### **三. 其他**
1. 简书详细介绍地址:https://www.jianshu.com/p/d0e1320704e4
2. 视频详细讲解地址:https://pan.baidu.com/s/1kWoIA95
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.darren.drouter"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
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 "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
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'
/*compile 'com.alibaba:arouter-api:1.2.1.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.0.3'*/
implementation project(':login-module')
implementation project(':circle-module')
}
================================================
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/darren/drouter/ExampleInstrumentedTest.kt
================================================
package com.darren.drouter
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getTargetContext()
assertEquals("com.darren.drouter", appContext.packageName)
}
}
================================================
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.darren.drouter">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:name=".BaseApplication"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
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>
</application>
</manifest>
================================================
FILE: app/src/main/java/com/darren/drouter/BaseApplication.java
================================================
package com.darren.drouter;
import android.app.Application;
import com.drouter.api.core.DRouter;
/**
* description:
* author: Darren on 2018/1/22 11:27
* email: 240336124@qq.com
* version: 1.0
*/
public class BaseApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
DRouter.openDebug();
DRouter.getInstance().init(this);
}
}
================================================
FILE: app/src/main/java/com/darren/drouter/MainActivity.java
================================================
package com.darren.drouter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.drouter.api.core.DRouter;
import com.drouter.api.result.ActionCallback;
import com.drouter.api.result.RouterResult;
/**
* description:
* author: Darren on 2018/1/22 09:43
* email: 240336124@qq.com
* version: 1.0
*/
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void jumpLogin(View view) {
DRouter.getInstance()
.action("login/action")
.context(this)
.param("key", "value")
.invokeAction();
}
public void jumpCircle(View view) {
DRouter.getInstance()
.action("circlemodule/test")
.context(this)
.param("key", "value")
.invokeAction(new ActionCallback() {
@Override
public void onInterrupt() {
Log.e("TAG", "被拦截了");
}
@Override
public void onResult(RouterResult result) {
Log.e("TAG", "result = " + result.toString());
}
});
}
}
================================================
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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.darren.drouter.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="主 App 模块"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="jumpLogin"
android:text="跳转到登录模块" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="jumpCircle"
android:text="跳转到圈子模块" />
</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">DRouter</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/darren/drouter/ExampleUnitTest.kt
================================================
package com.darren.drouter
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
================================================
FILE: base-core/.gitignore
================================================
/build
================================================
FILE: base-core/build.gradle
================================================
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 15
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(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:26.1.0'
compile project(':drouter-api')
annotationProcessor project(':drouter-compiler')
}
================================================
FILE: base-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: base-core/src/androidTest/java/com/base/core/ExampleInstrumentedTest.java
================================================
package com.base.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.base.core.test", appContext.getPackageName());
}
}
================================================
FILE: base-core/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.base.core" />
================================================
FILE: base-core/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">base-core</string>
</resources>
================================================
FILE: base-core/src/test/java/com/base/core/ExampleUnitTest.java
================================================
package com.base.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: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.1.51'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// 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: circle-module/.gitignore
================================================
/build
================================================
FILE: circle-module/build.gradle
================================================
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
repositories {
mavenCentral()
}
defaultConfig {
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
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: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'
implementation project(':base-core')
annotationProcessor project(':drouter-compiler')
}
================================================
FILE: circle-module/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: circle-module/src/androidTest/java/com/example/circle_module/ExampleInstrumentedTest.java
================================================
package com.example.circle_module;
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.example.circle_module.test", appContext.getPackageName());
}
}
================================================
FILE: circle-module/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.circle_module">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity android:name=".CircleActivity" />
</application>
</manifest>
================================================
FILE: circle-module/src/main/java/com/example/circle_module/CircleAction.java
================================================
package com.example.circle_module;
import android.content.Context;
import android.content.Intent;
import com.drouter.api.action.IRouterAction;
import com.drouter.api.result.RouterResult;
import com.drouter.base.ThreadMode;
import com.drouter.base.annotation.Action;
import java.util.Map;
/**
* description:
* author: Darren on 2018/1/22 10:57
* email: 240336124@qq.com
* version: 1.0
*/
@Action(path = "circlemodule/test", threadMode = ThreadMode.MAIN)
public class CircleAction implements IRouterAction {
@Override
public RouterResult invokeAction(Context context, Map<String, Object> requestData) {
Intent intent = new Intent(context, CircleActivity.class);
intent.putExtra("key", (String) requestData.get("key"));
context.startActivity(intent);
return new RouterResult.Builder().success().build();
}
}
================================================
FILE: circle-module/src/main/java/com/example/circle_module/CircleActivity.java
================================================
package com.example.circle_module;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.drouter.api.core.DRouter;
import com.drouter.api.result.ActionCallback;
import com.drouter.api.result.RouterResult;
/**
* description:
* author: Darren on 2018/1/22 15:08
* email: 240336124@qq.com
* version: 1.0
*/
public class CircleActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_circle);
}
public void click(View view) {
DRouter.getInstance()
.action("login/action")
.context(CircleActivity.this)
.param("key", "value")
.invokeAction(new ActionCallback() {
@Override
public void onInterrupt() {
Log.e("TAG", "被拦截了");
}
@Override
public void onResult(RouterResult result) {
Log.e("TAG", "result = " + result.toString());
}
});
}
}
================================================
FILE: circle-module/src/main/java/com/example/circle_module/CircleInterceptor.java
================================================
package com.example.circle_module;
import android.widget.Toast;
import com.drouter.api.core.DRouter;
import com.drouter.api.interceptor.ActionInterceptor;
import com.drouter.api.thread.ActionPost;
import com.drouter.base.annotation.Interceptor;
/**
* description:
* author: Darren on 2018/1/24 16:14
* email: 240336124@qq.com
* version: 1.0
*/
@Interceptor(priority = 18)
public class CircleInterceptor implements ActionInterceptor {
@Override
public void intercept(ActionChain chain) {
ActionPost actionPost = chain.action();
if (chain.actionPath().equals("circlemodule/test")) {
Toast.makeText(actionPost.context, "拦截圈子,跳转到登录", Toast.LENGTH_LONG).show();
// 拦截
chain.onInterrupt();
// 跳转到登录页面
DRouter.getInstance()
.action("login/action")
.context(actionPost.context)
.invokeAction();
}
// 继续向下转发
chain.proceed(actionPost);
}
}
================================================
FILE: circle-module/src/main/java/com/example/circle_module/CircleInterceptor1.java
================================================
package com.example.circle_module;
import com.drouter.api.interceptor.ActionInterceptor;
import com.drouter.api.thread.ActionPost;
import com.drouter.base.annotation.Interceptor;
/**
* description:
* author: Darren on 2018/1/24 16:14
* email: 240336124@qq.com
* version: 1.0
*/
@Interceptor(priority = 6)
public class CircleInterceptor1 implements ActionInterceptor {
@Override
public void intercept(ActionChain chain) {
ActionPost actionPost = chain.action();
if (chain.actionPath().equals("circlemodule/test")) {
// 拦截
chain.onInterrupt();
}
// 继续向下转发
chain.proceed(actionPost);
}
}
================================================
FILE: circle-module/src/main/java/com/example/circle_module/CircleInterceptor2.java
================================================
package com.example.circle_module;
import com.drouter.api.interceptor.ActionInterceptor;
import com.drouter.api.thread.ActionPost;
import com.drouter.base.annotation.Interceptor;
/**
* description:
* author: Darren on 2018/1/24 16:14
* email: 240336124@qq.com
* version: 1.0
*/
@Interceptor(priority = 10)
public class CircleInterceptor2 implements ActionInterceptor {
@Override
public void intercept(ActionChain chain) {
ActionPost actionPost = chain.action();
if (chain.actionPath().equals("circlemodule/test")) {
// 拦截
chain.onInterrupt();
}
// 继续向下转发
chain.proceed(actionPost);
}
}
================================================
FILE: circle-module/src/main/res/layout/activity_circle.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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/test"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="圈子模块" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:onClick="click"
android:text="点击跳转到登录模块" />
</LinearLayout>
================================================
FILE: circle-module/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">circle-module</string>
</resources>
================================================
FILE: circle-module/src/test/java/com/example/circle_module/ExampleUnitTest.java
================================================
package com.example.circle_module;
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: drouter-api/.gitignore
================================================
/build
================================================
FILE: drouter-api/build.gradle
================================================
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 15
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(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
compile project(':drouter-base')
}
================================================
FILE: drouter-api/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: drouter-api/src/androidTest/java/com/drouter/api/ExampleInstrumentedTest.java
================================================
package com.drouter.api;
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.drouter.api.test", appContext.getPackageName());
}
}
================================================
FILE: drouter-api/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.drouter.api" />
================================================
FILE: drouter-api/src/main/java/com/drouter/api/action/IRouterAction.java
================================================
package com.drouter.api.action;
import android.content.Context;
import com.drouter.api.result.RouterResult;
import java.util.Map;
/**
* description:
* author: Darren on 2018/1/22 10:32
* email: 240336124@qq.com
* version: 1.0
*/
public interface IRouterAction {
// 执行 Action 方法
RouterResult invokeAction(Context context, Map<String, Object> requestData);
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/action/IRouterInterceptor.java
================================================
package com.drouter.api.action;
import com.drouter.api.interceptor.ActionInterceptor;
import java.util.List;
/**
* description:
* author: Darren on 2018/1/22 11:08
* email: 240336124@qq.com
* version: 1.0
*/
public interface IRouterInterceptor {
// 通过 Action 的名称找到 Action
List<ActionInterceptor> getInterceptors();
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/action/IRouterModule.java
================================================
package com.drouter.api.action;
import com.drouter.api.extra.ActionWrapper;
/**
* description:
* author: Darren on 2018/1/22 11:08
* email: 240336124@qq.com
* version: 1.0
*/
public interface IRouterModule {
// 通过 Action 的名称找到 Action
ActionWrapper findAction(String actionName);
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/core/DRouter.java
================================================
package com.drouter.api.core;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
import android.widget.Toast;
import com.drouter.api.action.IRouterAction;
import com.drouter.api.action.IRouterInterceptor;
import com.drouter.api.action.IRouterModule;
import com.drouter.api.exception.InitException;
import com.drouter.api.extra.ActionWrapper;
import com.drouter.api.extra.Consts;
import com.drouter.api.extra.DefaultLogger;
import com.drouter.api.extra.ErrorActionWrapper;
import com.drouter.api.extra.ILogger;
import com.drouter.api.interceptor.ActionInterceptor;
import com.drouter.api.interceptor.CallActionInterceptor;
import com.drouter.api.interceptor.ErrorActionInterceptor;
import com.drouter.api.thread.PosterSupport;
import com.drouter.api.utils.ClassUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* description:
* author: Darren on 2018/1/22 09:59
* email: 240336124@qq.com
* version: 1.0
*/
public class DRouter {
// 是否被初始化
private volatile static boolean hasInit = false;
// 是否是 debugable 状态
private volatile static boolean debuggable = false;
// 日志打印
public volatile static ILogger logger = new DefaultLogger();
// 缓存的 RouterAction
private volatile static Map<String, ActionWrapper> cacheRouterActions = new HashMap();
// 缓存的 RouterModule
private volatile static Map<String, IRouterModule> cacheRouterModules = new HashMap();
// 所有 moudle
private static List<String> mAllModuleClassName;
private Context mApplicationContext;
private static List<ActionInterceptor> interceptors = new ArrayList<>();
public static synchronized void openDebug() {
debuggable = true;
logger.showLog(true);
logger.d(Consts.TAG, "DRouter openDebug");
}
private volatile static DRouter instance = null;
public static boolean debuggable() {
return debuggable;
}
private DRouter() {
}
/**
* Get instance of router. A
* All feature U use, will be starts here.
*/
public static DRouter getInstance() {
if (instance == null) {
synchronized (DRouter.class) {
if (instance == null) {
instance = new DRouter();
}
}
}
return instance;
}
/**
* 初始化数据
*/
public void init(Application context) {
if (hasInit) {
throw new InitException("ARouter already initialized, It can only be initialized once.");
}
hasInit = true;
this.mApplicationContext = context;
// 获取 com.drotuer.assist 包名下的所有类名信息
try {
mAllModuleClassName = ClassUtils.getFileNameByPackageName(context, Consts.ROUTER_MODULE_PACK_NAME);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (String className : mAllModuleClassName) {
logger.d(Consts.TAG, "扫描到: " + className);
}
// 添加并且实例化所有拦截器
scanAddInterceptors(context);
}
// 扫描并且添加拦截器
private void scanAddInterceptors(final Context context) {
PosterSupport.getExecutorService().execute(new Runnable() {
@Override
public void run() {
// 1. 错误拦截器
interceptors.add(new ErrorActionInterceptor());
// 2. module 自定义的拦截器
try {
List<String> interceptorGroups = ClassUtils.getFileNameByPackageName(context, Consts.ROUTER_INTERCEPTOR_PACK_NAME);
// 循环所有的 Group 拦截器
for (String interceptorGroup : interceptorGroups) {
if (interceptorGroup.contains(Consts.ROUTER_INTERCEPTOR_GROUP_PREFIX)) {
IRouterInterceptor routerInterceptor = (IRouterInterceptor) Class.forName(interceptorGroup).newInstance();
List<ActionInterceptor> interceptorClasses = routerInterceptor.getInterceptors();
for (int i = interceptorClasses.size() - 1; i >= 0; i--) {
ActionInterceptor interceptor = interceptorClasses.get(i);
// 添加到拦截器链表
interceptors.add(interceptor);
}
}
}
} catch (Exception e) {
e.printStackTrace();
String message = "Instance interceptor error: " + e.getMessage();
logger.e(Consts.TAG, message);
}
// 3. 最后添加 Action 执行调用的拦截器
interceptors.add(new CallActionInterceptor());
}
});
}
public RouterForward action(String actionName) {
// 1. 动态先查找加载 Module
// actionName 的格式必须是 xxx/xxx
if (!actionName.contains("/")) {
String message = "action name format error -> <" + actionName + ">, like: moduleName/actionName";
debugMessage(message);
return new RouterForward(new ErrorActionWrapper(), interceptors);
}
// 2.获取 moduleName,实例化 Module,并缓存
String moduleName = actionName.split("/")[0];
String moduleClassName = searchModuleClassName(moduleName);
if (TextUtils.isEmpty(moduleClassName)) {
String message = String.format("Please check to the action name is correct: according to the <%s> cannot find module %s.", actionName, moduleName);
debugMessage(message);
return new RouterForward(new ErrorActionWrapper(), interceptors);
}
IRouterModule routerModule = cacheRouterModules.get(moduleClassName);
if (routerModule == null) {
try {
Class<? extends IRouterModule> moduleClass = (Class<? extends IRouterModule>) Class.forName(moduleClassName);
routerModule = moduleClass.newInstance();
cacheRouterModules.put(moduleClassName, routerModule);
} catch (Exception e) {
e.printStackTrace();
String message = "instance module error: " + e.getMessage();
debugMessage(message);
return new RouterForward(new ErrorActionWrapper(), interceptors);
}
}
// 3. 从 Module 中获取 ActionWrapper 类名,然后创建缓存 ActionWrapper
ActionWrapper actionWrapper = cacheRouterActions.get(actionName);
if (actionWrapper == null) {
actionWrapper = routerModule.findAction(actionName);
} else {
return new RouterForward(actionWrapper, interceptors);
}
if (actionWrapper == null) {
String message = String.format("Please check to the action name is correct: according to the <%s> cannot find action.", actionName);
debugMessage(message);
return new RouterForward(new ErrorActionWrapper(), interceptors);
}
Class<? extends IRouterAction> actionClass = actionWrapper.getActionClass();
IRouterAction routerAction = actionWrapper.getRouterAction();
if (routerAction == null) {
try {
if (!IRouterAction.class.isAssignableFrom(actionClass)) {
String message = actionClass.getCanonicalName() + " must be implements IRouterAction.";
debugMessage(message);
return new RouterForward(new ErrorActionWrapper(), interceptors);
}
// 创建 RouterAction 实例,并缓存起来
routerAction = actionClass.newInstance();
actionWrapper.setRouterAction(routerAction);
cacheRouterActions.put(actionName, actionWrapper);
} catch (Exception e) {
String message = "instance action error: " + e.getMessage();
debugMessage(message);
return new RouterForward(new ErrorActionWrapper(), interceptors);
}
}
return new RouterForward(actionWrapper, interceptors);
}
/**
* 显示 debug 信息
*
* @param message
*/
private void debugMessage(String message) {
if (debuggable) {
logger.e(Consts.TAG, message);
showToast(message);
}
}
/**
* 打印显示 Toast
*
* @param message
*/
private void showToast(String message) {
Toast.makeText(mApplicationContext, message, Toast.LENGTH_LONG).show();
}
/**
* 根据 moduleName 查询 module 的全类名
*
* @param moduleName
* @return
*/
private String searchModuleClassName(String moduleName) {
for (String moduleClassName : mAllModuleClassName) {
if (moduleClassName.contains(moduleName)) {
return moduleClassName;
}
}
return null;
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/core/RouterForward.java
================================================
package com.drouter.api.core;
import android.content.Context;
import com.drouter.api.extra.ActionWrapper;
import com.drouter.api.interceptor.ActionInterceptor;
import com.drouter.api.interceptor.ActionInterceptorChain;
import com.drouter.api.result.ActionCallback;
import com.drouter.api.thread.ActionPost;
import com.drouter.base.ThreadMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* description: 路由转发
* author: Darren on 2018/1/22 11:20
* email: 240336124@qq.com
* version: 1.0
*/
public class RouterForward {
private ActionWrapper mActionWrapper;
private Context mContext;
private Map<String, Object> mParams;
private ThreadMode mThreadMode = null;
// 所有拦截器表
private List<ActionInterceptor> interceptors;
/**
* 指定 threadMode 这里指定的优先级高于 Action 注解上的 threadMode
*
* @param threadMode
* @return
*/
public RouterForward threadMode(ThreadMode threadMode) {
this.mThreadMode = threadMode;
return this;
}
RouterForward(ActionWrapper actionWrapper, List<ActionInterceptor> interceptors) {
this.mActionWrapper = actionWrapper;
mParams = new HashMap<>();
this.interceptors = interceptors;
}
/**
* 执行 Action
*
* @return
*/
public void invokeAction() {
invokeAction(ActionCallback.DEFAULT_ACTION_CALLBACK);
}
/**
* 执行 Action
*
* @return
*/
public void invokeAction(ActionCallback actionCallback) {
// 先封装 actionPost
mActionWrapper.setThreadMode(getThreadMode());
ActionPost actionPost = ActionPost.obtainActionPost(mActionWrapper, mContext, mParams, actionCallback);
// 开始拦截器的流程
ActionInterceptor.ActionChain chain = new ActionInterceptorChain(interceptors, actionPost, 0);
chain.proceed(actionPost);
}
/**
* 路由转发方法传递的 threadMode 优先级高于 Action 注解上的 threadMode
*
* @return
*/
public ThreadMode getThreadMode() {
return mThreadMode == null ? mActionWrapper.getThreadMode() : mThreadMode;
}
public RouterForward context(Context context) {
this.mContext = context;
return this;
}
public RouterForward param(String key, Object value) {
mParams.put(key, value);
return this;
}
public RouterForward param(Map<String, Object> params) {
mParams.putAll(params);
return this;
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/exception/InitException.java
================================================
package com.drouter.api.exception;
/**
* description: 初始化异常类
* author: Darren on 2018/1/22 10:26
* email: 240336124@qq.com
* version: 1.0
*/
public class InitException extends RuntimeException {
public InitException(String message) {
super(message);
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/exception/RouterActionException.java
================================================
package com.drouter.api.exception;
/**
* description: Router Action Exception
* author: Darren on 2018/1/22 10:44
* email: 240336124@qq.com
* version: 1.0
*/
public class RouterActionException extends RuntimeException{
public RouterActionException(String message) {
super(message);
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/exception/RouterModuleException.java
================================================
package com.drouter.api.exception;
/**
* description: Router Module Exception
* author: Darren on 2018/1/22 10:44
* email: 240336124@qq.com
* version: 1.0
*/
public class RouterModuleException extends RuntimeException{
public RouterModuleException(String message) {
super(message);
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/extra/ActionWrapper.java
================================================
package com.drouter.api.extra;
import com.drouter.api.action.IRouterAction;
import com.drouter.base.ThreadMode;
/**
* description:
* author: Darren on 2018/1/23 14:22
* email: 240336124@qq.com
* version: 1.0
*/
public class ActionWrapper {
private Class<? extends IRouterAction> actionClass;
private String path;
private ThreadMode threadMode;
private boolean extraProcess;
private IRouterAction routerAction;
ActionWrapper() {
}
public void setRouterAction(IRouterAction routerAction) {
this.routerAction = routerAction;
}
public void setThreadMode(ThreadMode threadMode) {
this.threadMode = threadMode;
}
public IRouterAction getRouterAction() {
return routerAction;
}
private ActionWrapper(Class<? extends IRouterAction> actionClass, String path, boolean extraProcess, ThreadMode threadMode) {
this.actionClass = actionClass;
this.path = path;
this.extraProcess = extraProcess;
this.threadMode = threadMode;
}
public Class<? extends IRouterAction> getActionClass() {
return actionClass;
}
public ThreadMode getThreadMode() {
return threadMode;
}
public String getPath() {
return path;
}
public boolean isExtraProcess() {
return extraProcess;
}
public static ActionWrapper build(Class<? extends IRouterAction> actionClass, String path, boolean extraProcess, ThreadMode threadMode) {
return new ActionWrapper(actionClass, path, extraProcess, threadMode);
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/extra/Consts.java
================================================
package com.drouter.api.extra;
/**
* description:
* author: Darren on 2018/1/22 10:01
* email: 240336124@qq.com
* version: 1.0
*/
public class Consts {
public static final String SDK_NAME = "DRouter";
public static final String TAG = SDK_NAME;
public static final String SUFFIX_INTERCEPTORS = "Interceptors";
public static final String ROUTER_MODULE_PACK_NAME = "com.drouter.assist.module";
public static final String ROUTER_INTERCEPTOR_PACK_NAME = "com.drouter.assist.interceptor";
public static final String ROUTER_INTERCEPTOR_GROUP_PREFIX = "DRouter$$Interceptor$$";
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/extra/DefaultLogger.java
================================================
package com.drouter.api.extra;
import android.text.TextUtils;
import android.util.Log;
/**
* description:
* author: Darren on 2018/1/22 10:05
* email: 240336124@qq.com
* version: 1.0
*/
public class DefaultLogger implements ILogger {
boolean isShowLog = false;
private String defaultTag = "DRouter";
@Override
public void showLog(boolean isShowLog) {
this.isShowLog = isShowLog;
}
@Override
public void d(String tag, String message) {
if (isShowLog) {
Log.d(TextUtils.isEmpty(tag) ? getDefaultTag() : tag, message);
}
}
@Override
public void i(String tag, String message) {
if (isShowLog) {
Log.i(TextUtils.isEmpty(tag) ? getDefaultTag() : tag, message);
}
}
@Override
public void w(String tag, String message) {
if (isShowLog) {
Log.w(TextUtils.isEmpty(tag) ? getDefaultTag() : tag, message);
}
}
@Override
public void e(String tag, String message) {
if (isShowLog) {
Log.e(TextUtils.isEmpty(tag) ? getDefaultTag() : tag, message);
}
}
public String getDefaultTag() {
return defaultTag;
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/extra/ErrorActionWrapper.java
================================================
package com.drouter.api.extra;
/**
* description:
* author: Darren on 2018/1/23 15:45
* email: 240336124@qq.com
* version: 1.0
*/
public class ErrorActionWrapper extends ActionWrapper {
public ErrorActionWrapper() {
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/extra/ILogger.java
================================================
package com.drouter.api.extra;
/**
* description:
* author: Darren on 2018/1/22 10:02
* email: 240336124@qq.com
* version: 1.0
*/
public interface ILogger {
void showLog(boolean isShowLog);
void d(String tag, String message);
void i(String tag, String message);
void w(String tag, String message);
void e(String tag, String message);
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/ActionInterceptor.java
================================================
package com.drouter.api.interceptor;
import com.drouter.api.thread.ActionPost;
/**
* description: 拦截器
* author: Darren on 2018/1/22 11:59
* email: 240336124@qq.com
* version: 1.0
*/
public interface ActionInterceptor {
void intercept(ActionChain chain);
interface ActionChain {
// 打断拦截
void onInterrupt();
// 分发给下一个拦截器
void proceed(ActionPost actionPost);
// 获取 ActionPost
ActionPost action();
String actionPath();
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/ActionInterceptorChain.java
================================================
package com.drouter.api.interceptor;
import com.drouter.api.thread.ActionPost;
import java.util.List;
/**
* description:
* author: Darren on 2018/1/24 09:38
* email: 240336124@qq.com
* version: 1.0
*/
public class ActionInterceptorChain implements ActionInterceptor.ActionChain {
// 是否被拦截了
private boolean isInterrupt = false;
private List<ActionInterceptor> interceptors;
private ActionPost actionPost;
private int index;
public ActionInterceptorChain(List<ActionInterceptor> interceptors, ActionPost actionPost, int index) {
this.interceptors = interceptors;
this.actionPost = actionPost;
this.index = index;
}
@Override
public void onInterrupt() {
isInterrupt = true;
actionPost.actionCallback.onInterrupt();
}
@Override
public void proceed(ActionPost actionPost) { // 0
if (!isInterrupt && index < interceptors.size()) {
// 继续往下分发
ActionInterceptor.ActionChain next = new ActionInterceptorChain(interceptors, actionPost, index + 1);
// 0 拦截器
ActionInterceptor interceptor = interceptors.get(index);
// 执行第一个
interceptor.intercept(next);
}
}
@Override
public ActionPost action() {
return actionPost;
}
@Override
public String actionPath() {
return actionPost.actionWrapper.getPath();
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/CallActionInterceptor.java
================================================
package com.drouter.api.interceptor;
import android.os.Looper;
import com.drouter.api.action.IRouterAction;
import com.drouter.api.extra.ActionWrapper;
import com.drouter.api.result.RouterResult;
import com.drouter.api.thread.ActionPost;
import com.drouter.api.thread.PosterSupport;
/**
* description: 执行 Action 方法的最后一个拦截器
* author: Darren on 2018/1/24 09:03
* email: 240336124@qq.com
* version: 1.0
*/
public class CallActionInterceptor implements ActionInterceptor {
@Override
public void intercept(ActionChain chain) {
// 执行 Action 方法
ActionPost actionPost = chain.action();
invokeAction(actionPost, Looper.myLooper() == Looper.getMainLooper());
}
/**
* 处理线程切换
*
* @param isMainThread
* @return
*/
private void invokeAction(ActionPost actionPost, boolean isMainThread) {
switch (actionPost.actionWrapper.getThreadMode()) {
case POSTING:
invokeAction(actionPost);
case MAIN:
if (isMainThread) {
invokeAction(actionPost);
} else {
PosterSupport.getMainPoster().enqueue(actionPost);
}
break;
case BACKGROUND:
if (isMainThread) {
PosterSupport.getBackgroundPoster().enqueue(actionPost);
} else {
invokeAction(actionPost);
}
break;
case ASYNC:
PosterSupport.getAsyncPoster().enqueue(actionPost);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + actionPost.actionWrapper.getThreadMode());
}
}
/**
* 执行 Action
*
* @param actionPost
*/
private void invokeAction(ActionPost actionPost) {
ActionWrapper actionWrapper = actionPost.actionWrapper;
IRouterAction routerAction = actionWrapper.getRouterAction();
RouterResult routerResult = routerAction.invokeAction(actionPost.context, actionPost.params);
actionPost.actionCallback.onResult(routerResult);
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/ErrorActionInterceptor.java
================================================
package com.drouter.api.interceptor;
import com.drouter.api.extra.ErrorActionWrapper;
import com.drouter.api.thread.ActionPost;
/**
* description: 错误的 Action 拦截器,放在拦截链的第一个位置
* author: Darren on 2018/1/24 09:03
* email: 240336124@qq.com
* version: 1.0
*/
public class ErrorActionInterceptor implements ActionInterceptor {
@Override
public void intercept(ActionChain chain) {
ActionPost actionPost = chain.action();
// 拦截错误
if (actionPost.actionWrapper instanceof ErrorActionWrapper) {
chain.onInterrupt();
}
// 继续分发
chain.proceed(actionPost);
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/result/ActionCallback.java
================================================
package com.drouter.api.result;
/**
* description:
* author: Darren on 2018/1/24 09:05
* email: 240336124@qq.com
* version: 1.0
*/
public interface ActionCallback {
// 被拦截了
void onInterrupt();
// 没被拦截返回结果
void onResult(RouterResult result);
// 默认的 ActionCallback
ActionCallback DEFAULT_ACTION_CALLBACK = new ActionCallback() {
@Override
public void onInterrupt() {
}
@Override
public void onResult(RouterResult result) {
}
};
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/result/RouterResult.java
================================================
package com.drouter.api.result;
/**
* description: 路由的返回结果
* author: Darren on 2018/1/22 10:35
* email: 240336124@qq.com
* version: 1.0
*/
public class RouterResult {
static final int SUCCEED_CODE = 0x000011;
static final int ERROR_CODE = 0x000022;
private String msg;
private int code;
private Object object;
public int getCode() {
return code;
}
private RouterResult(Builder builder) {
this.code = builder.code;
this.msg = builder.msg;
this.object = builder.object;
}
@Override
public String toString() {
return super.toString() + "{" +
"msg='" + msg + '\'' +
", code=" + code +
", object=" + object +
'}';
}
public String getMsg() {
return msg;
}
public Object getObject() {
return object;
}
/**
* 返回是否成功
*
* @return
*/
public boolean isSucceed() {
return code == SUCCEED_CODE;
}
public static class Builder {
int code = SUCCEED_CODE;
String msg;
Object object;
public Builder error() {
this.code = ERROR_CODE;
return this;
}
public Builder success() {
this.code = SUCCEED_CODE;
return this;
}
public Builder msg(String msg) {
this.msg = msg;
return this;
}
public Builder object(Object object) {
this.object = object;
return this;
}
public RouterResult build() {
return new RouterResult(this);
}
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/thread/ActionPost.java
================================================
package com.drouter.api.thread;
import android.content.Context;
import com.drouter.api.extra.ActionWrapper;
import com.drouter.api.result.ActionCallback;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* description:
* author: Darren on 2018/1/23 16:11
* email: 240336124@qq.com
* version: 1.0
*/
public final class ActionPost {
private final static List<ActionPost> pendingPostPool = new ArrayList<ActionPost>();
public Context context;
public ActionWrapper actionWrapper;
public Map<String, Object> params;
public ActionCallback actionCallback;
ActionPost next;
private ActionPost(ActionWrapper actionWrapper, Context context, Map<String, Object> params, ActionCallback actionCallback) {
this.context = context;
this.actionWrapper = actionWrapper;
this.params = params;
this.actionCallback = actionCallback;
}
public static ActionPost obtainActionPost(ActionWrapper actionWrapper, Context context, Map<String, Object> params, ActionCallback actionCallback) {
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
ActionPost actionPost = pendingPostPool.remove(size - 1);
actionPost.context = context;
actionPost.actionWrapper = actionWrapper;
actionPost.params = params;
actionPost.next = null;
actionPost.actionCallback = actionCallback;
return actionPost;
}
}
return new ActionPost(actionWrapper, context, params, actionCallback);
}
public void releasePendingPost() {
this.context = null;
this.actionWrapper = null;
this.next = null;
this.actionCallback = null;
synchronized (pendingPostPool) {
// Don't let the pool grow indefinitely
if (pendingPostPool.size() < 10000) {
pendingPostPool.add(this);
}
}
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/thread/ActionPostQueue.java
================================================
package com.drouter.api.thread;
/**
* description:
* author: Darren on 2018/1/23 16:13
* email: 240336124@qq.com
* version: 1.0
*/
public class ActionPostQueue {
private ActionPost head;
private ActionPost tail;
synchronized void enqueue(ActionPost pendingPost) {
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
if (tail != null) {
tail.next = pendingPost;
tail = pendingPost;
} else if (head == null) {
head = tail = pendingPost;
} else {
throw new IllegalStateException("Head present, but no tail");
}
notifyAll();
}
synchronized ActionPost poll() {
ActionPost pendingPost = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
}
return pendingPost;
}
synchronized ActionPost poll(int maxMillisToWait) throws InterruptedException {
if (head == null) {
wait(maxMillisToWait);
}
return poll();
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/thread/AsyncPoster.java
================================================
package com.drouter.api.thread;
import com.drouter.api.action.IRouterAction;
import com.drouter.api.extra.ActionWrapper;
import com.drouter.api.result.RouterResult;
/**
* description: 处理异步
* author: Darren on 2018/1/23 16:46
* email: 240336124@qq.com
* version: 1.0
*/
public class AsyncPoster implements Runnable, Poster {
private final ActionPostQueue queue;
AsyncPoster() {
queue = new ActionPostQueue();
}
@Override
public void run() {
ActionPost actionPost = queue.poll();
if (actionPost == null) {
throw new IllegalStateException("No pending post available");
}
ActionWrapper actionWrapper = actionPost.actionWrapper;
IRouterAction routerAction = actionWrapper.getRouterAction();
RouterResult routerResult = routerAction.invokeAction(actionPost.context, actionPost.params);
actionPost.actionCallback.onResult(routerResult);
actionPost.releasePendingPost();
}
@Override
public void enqueue(ActionPost actionPost) {
queue.enqueue(actionPost);
PosterSupport.getExecutorService().execute(this);
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/thread/BackgroundPoster.java
================================================
package com.drouter.api.thread;
import com.drouter.api.action.IRouterAction;
import com.drouter.api.core.DRouter;
import com.drouter.api.extra.ActionWrapper;
import com.drouter.api.extra.Consts;
import com.drouter.api.result.RouterResult;
/**
* description:
* author: Darren on 2018/1/23 17:01
* email: 240336124@qq.com
* version: 1.0
*/
final class BackgroundPoster implements Runnable, Poster {
private final ActionPostQueue queue;
private volatile boolean executorRunning;
BackgroundPoster() {
queue = new ActionPostQueue();
}
@Override
public void enqueue(ActionPost actionPost) {
synchronized (this) {
queue.enqueue(actionPost);
if (!executorRunning) {
executorRunning = true;
PosterSupport.getExecutorService().execute(this);
}
}
}
@Override
public void run() {
try {
try {
while (true) {
ActionPost actionPost = queue.poll(1000);
if (actionPost == null) {
synchronized (this) {
// Check again, this time in synchronized
actionPost = queue.poll();
if (actionPost == null) {
executorRunning = false;
return;
}
}
}
ActionWrapper actionWrapper = actionPost.actionWrapper;
IRouterAction routerAction = actionWrapper.getRouterAction();
RouterResult routerResult = routerAction.invokeAction(actionPost.context, actionPost.params);
actionPost.actionCallback.onResult(routerResult);
actionPost.releasePendingPost();
}
} catch (InterruptedException e) {
DRouter.logger.e(Consts.TAG, Thread.currentThread().getName() + " was interruppted");
}
} finally {
executorRunning = false;
}
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/thread/HandlerPoster.java
================================================
package com.drouter.api.thread;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import com.drouter.api.action.IRouterAction;
import com.drouter.api.extra.ActionWrapper;
import com.drouter.api.result.RouterResult;
/**
* description: 处理主线程切换
* author: Darren on 2018/1/23 16:10
* email: 240336124@qq.com
* version: 1.0
*/
public class HandlerPoster extends Handler implements Poster {
private final ActionPostQueue queue;
private final int maxMillisInsideHandleMessage;
private boolean handlerActive;
protected HandlerPoster(Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new ActionPostQueue();
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) {
ActionPost actionPost = queue.poll();
if (actionPost == null) {
synchronized (this) {
// Check again, this time in synchronized
actionPost = queue.poll();
if (actionPost == null) {
handlerActive = false;
return;
}
}
}
ActionWrapper actionWrapper = actionPost.actionWrapper;
IRouterAction routerAction = actionWrapper.getRouterAction();
RouterResult routerResult = routerAction.invokeAction(actionPost.context, actionPost.params);
actionPost.actionCallback.onResult(routerResult);
actionPost.releasePendingPost();
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new RuntimeException("Could not send handler message");
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
@Override
public void enqueue(ActionPost actionPost) {
synchronized (this) {
queue.enqueue(actionPost);
if (!handlerActive) {
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new RuntimeException("Could not send handler message");
}
}
}
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/thread/Poster.java
================================================
package com.drouter.api.thread;
/**
* description:
* author: Darren on 2018/1/23 16:05
* email: 240336124@qq.com
* version: 1.0
*/
public interface Poster {
void enqueue(ActionPost actionPost);
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/thread/PosterSupport.java
================================================
package com.drouter.api.thread;
import android.os.Looper;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* description:
* author: Darren on 2018/1/23 16:08
* email: 240336124@qq.com
* version: 1.0
*/
public class PosterSupport {
private static volatile Poster mainPoster, backgroundPoster, asyncPoster;
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();
public static Poster getMainPoster() {
if (mainPoster == null) {
synchronized (PosterSupport.class) {
if (mainPoster == null) {
mainPoster = new HandlerPoster(Looper.getMainLooper(), 10);
}
}
}
return mainPoster;
}
public static ExecutorService getExecutorService() {
return DEFAULT_EXECUTOR_SERVICE;
}
public static Poster getBackgroundPoster() {
if (backgroundPoster == null) {
synchronized (PosterSupport.class) {
if (backgroundPoster == null) {
backgroundPoster = new BackgroundPoster();
}
}
}
return backgroundPoster;
}
public static Poster getAsyncPoster() {
if (asyncPoster == null) {
synchronized (PosterSupport.class) {
if (asyncPoster == null) {
asyncPoster = new AsyncPoster();
}
}
}
return asyncPoster;
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/utils/ClassUtils.java
================================================
package com.drouter.api.utils;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import com.drouter.api.core.DRouter;
import com.drouter.api.extra.Consts;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import dalvik.system.DexFile;
/**
* description: thanks alibaba ARouter
* author: Darren on 2018/1/23 09:24
* email: 240336124@qq.com
* version: 1.0
*/
public class ClassUtils {
private static final String EXTRACTED_NAME_EXT = ".classes";
private static final int VM_WITH_MULTIDEX_VERSION_MAJOR = 2;
private static final int VM_WITH_MULTIDEX_VERSION_MINOR = 1;
private static final String PREFS_FILE = "multidex.version";
private static final String KEY_DEX_NUMBER = "dex.number";
private static final String SECONDARY_FOLDER_NAME = "code_cache" + File.separator + "secondary-dexes";
private static final String EXTRACTED_SUFFIX = ".zip";
private static SharedPreferences getMultiDexPreferences(Context context) {
return context.getSharedPreferences(PREFS_FILE, Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? Context.MODE_PRIVATE : Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
}
/**
* 通过指定包名,扫描包下面包含的所有的ClassName
*/
public static List<String> getFileNameByPackageName(Context context, String packageName) throws PackageManager.NameNotFoundException, IOException {
List<String> classNames = new ArrayList<>();
for (String path : getSourcePaths(context)) {
DexFile dexfile;
if (path.endsWith(EXTRACTED_SUFFIX)) {
//NOT use new DexFile(path), because it will throw "permission error in /data/dalvik-cache"
dexfile = DexFile.loadDex(path, path + ".tmp", 0);
} else {
dexfile = new DexFile(path);
}
Enumeration<String> dexEntries = dexfile.entries();
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
if (className.contains(packageName)) {
classNames.add(className);
}
}
}
DRouter.logger.d(Consts.TAG, "Scan " + classNames.size() + " classes by packageName <" + packageName + ">");
return classNames;
}
/**
* get all the dex path
*
* @param context the application context
* @return all the dex path
* @throws PackageManager.NameNotFoundException
* @throws IOException
*/
public static List<String> getSourcePaths(Context context) throws PackageManager.NameNotFoundException, IOException {
ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
File sourceApk = new File(applicationInfo.sourceDir);
List<String> sourcePaths = new ArrayList<>();
sourcePaths.add(applicationInfo.sourceDir); //add the default apk path
//the prefix of extracted file, ie: test.classes
String extractedFilePrefix = sourceApk.getName() + EXTRACTED_NAME_EXT;
if (!isVMMultidexCapable()) {
//the total dex numbers
int totalDexNumber = getMultiDexPreferences(context).getInt(KEY_DEX_NUMBER, 1);
File dexDir = new File(applicationInfo.dataDir, SECONDARY_FOLDER_NAME);
for (int secondaryNumber = 2; secondaryNumber <= totalDexNumber; secondaryNumber++) {
//for each dex file, ie: test.classes2.zip, test.classes3.zip...
String fileName = extractedFilePrefix + secondaryNumber + EXTRACTED_SUFFIX;
File extractedFile = new File(dexDir, fileName);
if (extractedFile.isFile()) {
sourcePaths.add(extractedFile.getAbsolutePath());
//we ignore the verify zip part
} else {
throw new IOException("Missing extracted secondary dex file '" + extractedFile.getPath() + "'");
}
}
}
return sourcePaths;
}
/**
* Identifies if the current VM has a native support for multidex, meaning there is no need for
* additional installation by this library.
*
* @return true if the VM handles multidex
*/
private static boolean isVMMultidexCapable() {
boolean isMultidexCapable = false;
String vmName = null;
try {
if (isYunOS()) {
vmName = "'YunOS'";
isMultidexCapable = Integer.valueOf(System.getProperty("ro.build.version.sdk")) >= 21;
} else {
vmName = "'Android'";
String versionString = System.getProperty("java.vm.version");
if (versionString != null) {
Matcher matcher = Pattern.compile("(\\d+)\\.(\\d+)(\\.\\d+)?").matcher(versionString);
if (matcher.matches()) {
try {
int major = Integer.parseInt(matcher.group(1));
int minor = Integer.parseInt(matcher.group(2));
isMultidexCapable = (major > VM_WITH_MULTIDEX_VERSION_MAJOR)
|| ((major == VM_WITH_MULTIDEX_VERSION_MAJOR)
&& (minor >= VM_WITH_MULTIDEX_VERSION_MINOR));
} catch (NumberFormatException ignore) {
// let isMultidexCapable be false
}
}
}
}
} catch (Exception ignore) {
}
return isMultidexCapable;
}
/**
* 判断系统是否为YunOS系统
*/
private static boolean isYunOS() {
try {
String version = System.getProperty("ro.yunos.version");
String vmName = System.getProperty("java.vm.name");
return (vmName != null && vmName.toLowerCase().contains("lemur"))
|| (version != null && version.trim().length() > 0);
} catch (Exception ignore) {
return false;
}
}
}
================================================
FILE: drouter-api/src/main/java/com/drouter/api/utils/MapUtils.java
================================================
package com.drouter.api.utils;
import com.drouter.api.interceptor.ActionInterceptor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* description:
* author: Darren on 2018/1/24 16:57
* email: 240336124@qq.com
* version: 1.0
*/
public class MapUtils {
public static List<ActionInterceptor> getInterceptorClasses(Map<Integer, ActionInterceptor> map) {
List<ActionInterceptor> list = new ArrayList();
for (Object key : map.keySet()) {
list.add(map.get(key));
}
return list;
}
}
================================================
FILE: drouter-api/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">drouter-api</string>
</resources>
================================================
FILE: drouter-api/src/test/java/com/drouter/api/ExampleUnitTest.java
================================================
package com.drouter.api;
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: drouter-base/.gitignore
================================================
/build
================================================
FILE: drouter-base/build.gradle
================================================
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
================================================
FILE: drouter-base/src/main/java/com/drouter/base/ThreadMode.java
================================================
package com.drouter.base;
/**
* description: thanks EventBus
* author: Darren on 2018/1/23 08:57
* email: 240336124@qq.com
* version: 1.0
*/
public enum ThreadMode {
/**
* Action will be called directly in the same thread, which is posting the event. This is the default. Event delivery
* implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
* simple tasks that are known to complete in a very short time without requiring the main thread. Event handlers
* using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
*/
POSTING,
/**
* On Android, action will be called in Android's main thread (UI thread). If the posting thread is
* the main thread, action methods will be called directly, blocking the posting thread. Otherwise the event
* is queued for delivery (non-blocking). Action using this mode must return quickly to avoid blocking the main thread.
* If not on Android, behaves the same as {@link #POSTING}.
*/
MAIN,
/**
* On Android, action will be called in a background thread. If posting thread is not the main thread, action methods
* will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
* background thread, that will deliver all its events sequentially. Action using this mode should try to
* return quickly to avoid blocking the background thread. If not on Android, always uses a background thread.
*/
BACKGROUND,
/**
* Action will be called in a separate thread. This is always independent from the posting thread and the
* main thread. Posting events never wait for action methods using this mode. Action methods should
* use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
* of long running asynchronous action methods at the same time to limit the number of concurrent threads. EventBus
* uses a thread pool to efficiently reuse threads from completed asynchronous action notifications.
*/
ASYNC
}
================================================
FILE: drouter-base/src/main/java/com/drouter/base/annotation/Action.java
================================================
package com.drouter.base.annotation;
import com.drouter.base.ThreadMode;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* description: 模块注册 apt
* author: Darren on 2018/1/22 12:32
* email: 240336124@qq.com
* version: 1.0
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Action {
/**
* thread mode
*/
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* Path of route
*/
String path();
/**
* extra process
*/
boolean extraProcess() default false;
}
================================================
FILE: drouter-base/src/main/java/com/drouter/base/annotation/Interceptor.java
================================================
package com.drouter.base.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* description:
* author: Darren on 2018/1/24 16:10
* email: 240336124@qq.com
* version: 1.0
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Interceptor {
int priority();
}
================================================
FILE: drouter-compiler/.gitignore
================================================
/build
================================================
FILE: drouter-compiler/build.gradle
================================================
apply plugin: 'java-library'
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':drouter-base')
implementation 'com.google.auto.service:auto-service:1.0-rc2'
implementation 'com.squareup:javapoet:1.7.0'
}
tasks.withType(JavaCompile){
options.encoding='UTF-8'
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
================================================
FILE: drouter-compiler/src/main/java/com/drouter/compiler/Consts.java
================================================
package com.drouter.compiler;
/**
* description:
* author: Darren on 2018/1/22 10:01
* email: 240336124@qq.com
* version: 1.0
*/
public class Consts {
public static final String SDK_NAME = "DRouter";
public static final String TAG = SDK_NAME;
public static final String SUFFIX_INTERCEPTORS = "Interceptors";
public static final String ROUTER_MODULE_PACK_NAME = "com.drouter.assist.module";
public static final String ROUTER_INTERCEPTOR_PACK_NAME = "com.drouter.assist.interceptor";
public static final String ACTIONINTERCEPTOR = "com.drouter.api.interceptor.ActionInterceptor";
public static final String ROUTERACTION = "com.drouter.api.action.IRouterAction";
}
================================================
FILE: drouter-compiler/src/main/java/com/drouter/compiler/InterceptorProcessor.java
================================================
package com.drouter.compiler;
import com.drouter.base.annotation.Interceptor;
import com.drouter.compiler.util.TextUtils;
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.TypeSpec;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.LinkedHashSet;
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.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.tools.Diagnostic;
/**
* description:
* author: Darren on 2018/1/22 12:29
* email: 240336124@qq.com
* version: 1.0
*/
@AutoService(Processor.class)
public class InterceptorProcessor extends AbstractProcessor {
private Elements mElementUtils;
private Filer mFiler;
private final String KEY_MODULE_NAME = "moduleName";
private TypeMirror iInterceptor = null;
private String moduleName = null;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mFiler = processingEnvironment.getFiler();
mElementUtils = processingEnvironment.getElementUtils();
iInterceptor = mElementUtils.getTypeElement(Consts.ACTIONINTERCEPTOR).asType();
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
// 1. 有没配置 modelName 防止 class 类冲突
String moduleName = "";
Map<String, String> options = processingEnv.getOptions();
if (isNotEmpty(options)) {
moduleName = options.get(KEY_MODULE_NAME);
}
if (!TextUtils.isEmpty(moduleName)) {
moduleName = moduleName.replaceAll("[^0-9a-zA-Z_]+", "");
} else {
String errorMessage = "These no module name, at 'build.gradle', like :\n" +
"apt {\n" +
" arguments {\n" +
" moduleName project.getName();\n" +
" }\n" +
"}\n";
throw new RuntimeException("DRouter::Compiler >>> No module name, for more information, look at gradle log.\n" + errorMessage);
}
// 生成类继承和实现接口
ClassName routerAssistClassName = ClassName.get("com.drouter.api.action", "IRouterInterceptor");
ClassName mapClassName = ClassName.get("java.util", "Map");
TypeSpec.Builder classBuilder = TypeSpec.classBuilder("DRouter$$Interceptor$$" + moduleName)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC)
.addSuperinterface(routerAssistClassName)
.addField(mapClassName, "interceptors", Modifier.PRIVATE);
// 构造函数
MethodSpec.Builder constructorMethodBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
constructorMethodBuilder.addStatement("interceptors = new $T<>()", ClassName.get("java.util", "TreeMap"));
// 2. 解析到所有的 Action 信息
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Interceptor.class);
Map<Integer, String> interceptors = new HashMap<>(elements.size());
for (Element element : elements) {
// 获取注解上面的 priority
Interceptor interceptorAnnotation = element.getAnnotation(Interceptor.class);
int priority = interceptorAnnotation.priority();
// 获取 Interceptor 的 ClassName
Element enclosingElement = element.getEnclosingElement();
String packageName = mElementUtils.getPackageOf(enclosingElement).getQualifiedName().toString();
String interceptorClassName = packageName + "." + element.getSimpleName();
// 判断 Interceptor 注解类是否实现了 ActionInterceptor
if (!((TypeElement) element).getInterfaces().contains(iInterceptor)) {
error(element, "%s verify failed, @Interceptor must be implements %s", element.getSimpleName().toString(), Consts.ACTIONINTERCEPTOR);
}
if (interceptors.containsKey(priority)) {
// 输出错误,拦截器优先级 冲突重复了
error(element, "More than one interceptors use same priority <%s> , The last interceptor was <%s>", String.valueOf(priority), interceptors.get(priority));
}
// 添加到集合
interceptors.put(priority, interceptorClassName);
constructorMethodBuilder.addStatement("this.interceptors.put(" + priority + ",new $T())", ClassName.bestGuess(interceptorClassName));
}
// 实现方法
MethodSpec.Builder unbindMethodBuilder = MethodSpec.methodBuilder("getInterceptors")
.addAnnotation(Override.class)
.returns(List.class)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
unbindMethodBuilder.addStatement("return $T.getInterceptorClasses(interceptors)", ClassName.get("com.drouter.api.utils", "MapUtils"));
classBuilder.addMethod(constructorMethodBuilder.build());
classBuilder.addMethod(unbindMethodBuilder.build());
// 生成类,看下效果
try {
JavaFile.builder(Consts.ROUTER_INTERCEPTOR_PACK_NAME, classBuilder.build())
.addFileComment("DRouter 自动生成")
.build().writeTo(mFiler);
} catch (IOException e) {
e.printStackTrace();
System.out.println("翻车了!");
}
return false;
}
private boolean isNotEmpty(Map<String, String> options) {
return options != null && !options.isEmpty();
}
private void error(Element element, String message, String... args) {
printMessage(Diagnostic.Kind.ERROR, element, message, args);
}
private void printMessage(Diagnostic.Kind kind, Element element, String message, Object[] args) {
if (args.length > 0) {
message = String.format(message, args);
}
processingEnv.getMessager().printMessage(kind, message, element);
}
// 1. 指定处理的版本
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
// 2. 给到需要处理的注解
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> types = new LinkedHashSet<>();
for (Class<? extends Annotation> annotation : getSupportedAnnotations()) {
types.add(annotation.getCanonicalName());
}
return types;
}
private Set<Class<? extends Annotation>> getSupportedAnnotations() {
Set<Class<? extends Annotation>> annotations = new LinkedHashSet<>();
// 需要解析的自定义注解 BindView OnClick
annotations.add(Interceptor.class);
return annotations;
}
}
================================================
FILE: drouter-compiler/src/main/java/com/drouter/compiler/ModuleProcessor.java
================================================
package com.drouter.compiler;
import com.drouter.base.annotation.Action;
import com.drouter.compiler.util.TextUtils;
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.TypeSpec;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.LinkedHashSet;
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.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.tools.Diagnostic;
/**
* description:
* author: Darren on 2018/1/22 12:29
* email: 240336124@qq.com
* version: 1.0
*/
@AutoService(Processor.class)
public class ModuleProcessor extends AbstractProcessor {
private Elements mElementUtils;
private Filer mFiler;
private final String KEY_MODULE_NAME = "moduleName";
private TypeMirror iRouterAction = null;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mFiler = processingEnvironment.getFiler();
mElementUtils = processingEnvironment.getElementUtils();
iRouterAction = mElementUtils.getTypeElement(Consts.ROUTERACTION).asType();
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
// 1. 有没配置 modelName 防止 class 类冲突
String moduleName = "";
Map<String, String> options = processingEnv.getOptions();
if (isNotEmpty(options)) {
moduleName = options.get(KEY_MODULE_NAME);
}
System.out.println("moduleName = " + moduleName);
if (!TextUtils.isEmpty(moduleName)) {
moduleName = moduleName.replaceAll("[^0-9a-zA-Z_]+", "");
} else {
String errorMessage = "These no module name, at 'build.gradle', like :\n" +
"apt {\n" +
" arguments {\n" +
" moduleName project.getName();\n" +
" }\n" +
"}\n";
throw new RuntimeException("DRouter::Compiler >>> No module name, for more information, look at gradle log.\n" + errorMessage);
}
// 3. 生成 Java 类,效果如下
/*public class DRouter$$Assist implements IRouterAssist {
Map<String, String> modules = new HashMap<>();
public DRouter$$Assist() {
modules.put("login/module", "com.login.module.LoginModule");
}
@Override
public String findModuleClassName(String moduleName) {
return modules.get(moduleName);
}
}*/
// 生成类继承和实现接口
ClassName routerAssistClassName = ClassName.get("com.drouter.api.action", "IRouterModule");
ClassName mapClassName = ClassName.get("java.util", "Map");
TypeSpec.Builder classBuilder = TypeSpec.classBuilder("DRouter$$Module$$" + moduleName)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC)
.addSuperinterface(routerAssistClassName)
.addField(mapClassName, "actions", Modifier.PRIVATE);
// 构造函数
MethodSpec.Builder constructorMethodBuilder = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
constructorMethodBuilder.addStatement("actions = new $T<>()", ClassName.bestGuess("java.util.HashMap"));
// 2. 解析到所有的 Action 信息
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Action.class);
Map<String, String> modules = new HashMap<>(elements.size());
ClassName actionWrapperClassName = ClassName.get("com.drouter.api.extra", "ActionWrapper");
ClassName threadModeClassName = ClassName.get("com.drouter.base", "ThreadMode");
for (Element element : elements) {
// 获取注解上面的 action
Action actionAnnotation = element.getAnnotation(Action.class);
String actionName = actionAnnotation.path();
// 必须以配置的 gradle 包名开头
if (!actionName.startsWith(moduleName + "/")) {
error(element, "Path name of the action must begin with %s%s", moduleName, "/");
}
// 获取 Action 的 ClassName
Element enclosingElement = element.getEnclosingElement();
String packageName = mElementUtils.getPackageOf(enclosingElement).getQualifiedName().toString();
String actionClassName = packageName + "." + element.getSimpleName();
// 判断 Interceptor 注解类是否实现了 ActionInterceptor
if (!((TypeElement) element).getInterfaces().contains(iRouterAction)) {
error(element, "%s verify failed, @Action must be implements %s", element.getSimpleName().toString(), Consts.ROUTERACTION);
}
if (modules.containsKey(actionName)) {
// 输出错误,Action 名称冲突重复了
error(element, "%s module name already exists", actionName);
}
// 添加到集合
modules.put(actionName, actionClassName);
constructorMethodBuilder.addStatement("this.actions.put($S,$T.build($T.class, $S, "
+ actionAnnotation.extraProcess() + ", $T." + actionAnnotation.threadMode() + "))",
actionName, actionWrapperClassName, ClassName.bestGuess(actionClassName), actionName, threadModeClassName);
}
// 实现方法
MethodSpec.Builder unbindMethodBuilder = MethodSpec.methodBuilder("findAction")
.addParameter(String.class, "actionName")
.addAnnotation(Override.class)
.returns(actionWrapperClassName)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL);
unbindMethodBuilder.addStatement("return (ActionWrapper)actions.get(actionName)");
classBuilder.addMethod(constructorMethodBuilder.build());
classBuilder.addMethod(unbindMethodBuilder.build());
// 生成类,看下效果
try {
JavaFile.builder(Consts.ROUTER_MODULE_PACK_NAME, classBuilder.build())
.addFileComment("DRouter 自动生成")
.build().writeTo(mFiler);
} catch (IOException e) {
e.printStackTrace();
System.out.println("翻车了!");
}
return false;
}
private boolean isNotEmpty(Map<String, String> options) {
return options != null && !options.isEmpty();
}
private void error(Element element, String message, String... args) {
printMessage(Diagnostic.Kind.ERROR, element, message, args);
}
private void printMessage(Diagnostic.Kind kind, Element element, String message, Object[] args) {
if (args.length > 0) {
message = String.format(message, args);
}
processingEnv.getMessager().printMessage(kind, message, element);
}
// 1. 指定处理的版本
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
// 2. 给到需要处理的注解
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> types = new LinkedHashSet<>();
for (Class<? extends Annotation> annotation : getSupportedAnnotations()) {
types.add(annotation.getCanonicalName());
}
return types;
}
private Set<Class<? extends Annotation>> getSupportedAnnotations() {
Set<Class<? extends Annotation>> annotations = new LinkedHashSet<>();
// 需要解析的自定义注解 BindView OnClick
annotations.add(Action.class);
return annotations;
}
}
================================================
FILE: drouter-compiler/src/main/java/com/drouter/compiler/util/TextUtils.java
================================================
package com.drouter.compiler.util;
/**
* description:
* author: Darren on 2018/1/22 17:45
* email: 240336124@qq.com
* version: 1.0
*/
public class TextUtils {
public static boolean isEmpty(String moduleName) {
return moduleName == null || moduleName.isEmpty();
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Mon Jan 22 09:42:50 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.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: login-module/.gitignore
================================================
/build
================================================
FILE: login-module/build.gradle
================================================
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
repositories {
mavenCentral()
}
defaultConfig {
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: "login"]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
compile project(':base-core')
annotationProcessor project(':drouter-compiler')
}
================================================
FILE: login-module/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: login-module/src/androidTest/java/com/login/module/ExampleInstrumentedTest.java
================================================
package com.login.module;
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.login.module.test", appContext.getPackageName());
}
}
================================================
FILE: login-module/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.login.module" >
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity android:name=".LoginActivity"/>
</application>
</manifest>
================================================
FILE: login-module/src/main/java/com/login/module/LoginAction.java
================================================
package com.login.module;
import android.content.Context;
import android.content.Intent;
import com.drouter.api.action.IRouterAction;
import com.drouter.api.result.RouterResult;
import com.drouter.base.ThreadMode;
import com.drouter.base.annotation.Action;
import java.util.Map;
/**
* description:
* author: Darren on 2018/1/22 10:57
* email: 240336124@qq.com
* version: 1.0
*/
@Action(path = "login/action", threadMode = ThreadMode.MAIN)
public class LoginAction implements IRouterAction {
@Override
public RouterResult invokeAction(Context context, Map<String, Object> requestData) {
Intent intent = new Intent(context, LoginActivity.class);
intent.putExtra("key", (String) requestData.get("key"));
context.startActivity(intent);
return new RouterResult.Builder().success().object(100).build();
}
}
================================================
FILE: login-module/src/main/java/com/login/module/LoginActivity.java
================================================
package com.login.module;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.drouter.api.core.DRouter;
import com.drouter.api.result.ActionCallback;
import com.drouter.api.result.RouterResult;
/**
* description:
* author: Darren on 2018/1/22 15:08
* email: 240336124@qq.com
* version: 1.0
*/
public class LoginActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
String key = getIntent().getStringExtra("key");
Toast.makeText(this, key, Toast.LENGTH_LONG).show();
}
public void click(View view){
DRouter.getInstance()
.action("circlemodule/test")
.context(this)
.param("key", "value")
.invokeAction(new ActionCallback() {
@Override
public void onInterrupt() {
Log.e("TAG", "被拦截了");
}
@Override
public void onResult(RouterResult result) {
Log.e("TAG", "result = " + result.toString());
}
});
}
}
================================================
FILE: login-module/src/main/res/layout/activity_login.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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/test"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="登录模块" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:onClick="click"
android:text="点击跳转到圈子模块" />
</LinearLayout>
================================================
FILE: login-module/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">login-module</string>
</resources>
================================================
FILE: login-module/src/test/java/com/login/module/ExampleUnitTest.java
================================================
package com.login.module;
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', ':drouter-api', ':login-module', ':base-core', ':drouter-compiler', ':drouter-base', ':circle-module'
gitextract_w0jpccmc/ ├── .gitignore ├── .idea/ │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── darren/ │ │ └── drouter/ │ │ └── ExampleInstrumentedTest.kt │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── darren/ │ │ │ └── drouter/ │ │ │ ├── BaseApplication.java │ │ │ └── MainActivity.java │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_launcher_background.xml │ │ ├── drawable-v24/ │ │ │ └── ic_launcher_foreground.xml │ │ ├── layout/ │ │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26/ │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ └── values/ │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test/ │ └── java/ │ └── com/ │ └── darren/ │ └── drouter/ │ └── ExampleUnitTest.kt ├── base-core/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── base/ │ │ └── core/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ └── res/ │ │ └── values/ │ │ └── strings.xml │ └── test/ │ └── java/ │ └── com/ │ └── base/ │ └── core/ │ └── ExampleUnitTest.java ├── build.gradle ├── circle-module/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── example/ │ │ └── circle_module/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── circle_module/ │ │ │ ├── CircleAction.java │ │ │ ├── CircleActivity.java │ │ │ ├── CircleInterceptor.java │ │ │ ├── CircleInterceptor1.java │ │ │ └── CircleInterceptor2.java │ │ └── res/ │ │ ├── layout/ │ │ │ └── activity_circle.xml │ │ └── values/ │ │ └── strings.xml │ └── test/ │ └── java/ │ └── com/ │ └── example/ │ └── circle_module/ │ └── ExampleUnitTest.java ├── drouter-api/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── drouter/ │ │ └── api/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── drouter/ │ │ │ └── api/ │ │ │ ├── action/ │ │ │ │ ├── IRouterAction.java │ │ │ │ ├── IRouterInterceptor.java │ │ │ │ └── IRouterModule.java │ │ │ ├── core/ │ │ │ │ ├── DRouter.java │ │ │ │ └── RouterForward.java │ │ │ ├── exception/ │ │ │ │ ├── InitException.java │ │ │ │ ├── RouterActionException.java │ │ │ │ └── RouterModuleException.java │ │ │ ├── extra/ │ │ │ │ ├── ActionWrapper.java │ │ │ │ ├── Consts.java │ │ │ │ ├── DefaultLogger.java │ │ │ │ ├── ErrorActionWrapper.java │ │ │ │ └── ILogger.java │ │ │ ├── interceptor/ │ │ │ │ ├── ActionInterceptor.java │ │ │ │ ├── ActionInterceptorChain.java │ │ │ │ ├── CallActionInterceptor.java │ │ │ │ └── ErrorActionInterceptor.java │ │ │ ├── result/ │ │ │ │ ├── ActionCallback.java │ │ │ │ └── RouterResult.java │ │ │ ├── thread/ │ │ │ │ ├── ActionPost.java │ │ │ │ ├── ActionPostQueue.java │ │ │ │ ├── AsyncPoster.java │ │ │ │ ├── BackgroundPoster.java │ │ │ │ ├── HandlerPoster.java │ │ │ │ ├── Poster.java │ │ │ │ └── PosterSupport.java │ │ │ └── utils/ │ │ │ ├── ClassUtils.java │ │ │ └── MapUtils.java │ │ └── res/ │ │ └── values/ │ │ └── strings.xml │ └── test/ │ └── java/ │ └── com/ │ └── drouter/ │ └── api/ │ └── ExampleUnitTest.java ├── drouter-base/ │ ├── .gitignore │ ├── build.gradle │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── drouter/ │ └── base/ │ ├── ThreadMode.java │ └── annotation/ │ ├── Action.java │ └── Interceptor.java ├── drouter-compiler/ │ ├── .gitignore │ ├── build.gradle │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── drouter/ │ └── compiler/ │ ├── Consts.java │ ├── InterceptorProcessor.java │ ├── ModuleProcessor.java │ └── util/ │ └── TextUtils.java ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── login-module/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── login/ │ │ └── module/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── login/ │ │ │ └── module/ │ │ │ ├── LoginAction.java │ │ │ └── LoginActivity.java │ │ └── res/ │ │ ├── layout/ │ │ │ └── activity_login.xml │ │ └── values/ │ │ └── strings.xml │ └── test/ │ └── java/ │ └── com/ │ └── login/ │ └── module/ │ └── ExampleUnitTest.java └── settings.gradle
SYMBOL INDEX (191 symbols across 50 files)
FILE: app/src/main/java/com/darren/drouter/BaseApplication.java
class BaseApplication (line 12) | public class BaseApplication extends Application{
method onCreate (line 13) | @Override
FILE: app/src/main/java/com/darren/drouter/MainActivity.java
class MainActivity (line 19) | public class MainActivity extends AppCompatActivity {
method onCreate (line 21) | @Override
method jumpLogin (line 27) | public void jumpLogin(View view) {
method jumpCircle (line 35) | public void jumpCircle(View view) {
FILE: base-core/src/androidTest/java/com/base/core/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 19) | @Test
FILE: base-core/src/test/java/com/base/core/ExampleUnitTest.java
class ExampleUnitTest (line 12) | public class ExampleUnitTest {
method addition_isCorrect (line 13) | @Test
FILE: circle-module/src/androidTest/java/com/example/circle_module/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 19) | @Test
FILE: circle-module/src/main/java/com/example/circle_module/CircleAction.java
class CircleAction (line 19) | @Action(path = "circlemodule/test", threadMode = ThreadMode.MAIN)
method invokeAction (line 21) | @Override
FILE: circle-module/src/main/java/com/example/circle_module/CircleActivity.java
class CircleActivity (line 19) | public class CircleActivity extends AppCompatActivity {
method onCreate (line 20) | @Override
method click (line 27) | public void click(View view) {
FILE: circle-module/src/main/java/com/example/circle_module/CircleInterceptor.java
class CircleInterceptor (line 16) | @Interceptor(priority = 18)
method intercept (line 19) | @Override
FILE: circle-module/src/main/java/com/example/circle_module/CircleInterceptor1.java
class CircleInterceptor1 (line 13) | @Interceptor(priority = 6)
method intercept (line 16) | @Override
FILE: circle-module/src/main/java/com/example/circle_module/CircleInterceptor2.java
class CircleInterceptor2 (line 13) | @Interceptor(priority = 10)
method intercept (line 16) | @Override
FILE: circle-module/src/test/java/com/example/circle_module/ExampleUnitTest.java
class ExampleUnitTest (line 12) | public class ExampleUnitTest {
method addition_isCorrect (line 13) | @Test
FILE: drouter-api/src/androidTest/java/com/drouter/api/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 19) | @Test
FILE: drouter-api/src/main/java/com/drouter/api/action/IRouterAction.java
type IRouterAction (line 15) | public interface IRouterAction {
method invokeAction (line 17) | RouterResult invokeAction(Context context, Map<String, Object> request...
FILE: drouter-api/src/main/java/com/drouter/api/action/IRouterInterceptor.java
type IRouterInterceptor (line 13) | public interface IRouterInterceptor {
method getInterceptors (line 15) | List<ActionInterceptor> getInterceptors();
FILE: drouter-api/src/main/java/com/drouter/api/action/IRouterModule.java
type IRouterModule (line 11) | public interface IRouterModule {
method findAction (line 13) | ActionWrapper findAction(String actionName);
FILE: drouter-api/src/main/java/com/drouter/api/core/DRouter.java
class DRouter (line 36) | public class DRouter {
method openDebug (line 53) | public static synchronized void openDebug() {
method debuggable (line 62) | public static boolean debuggable() {
method DRouter (line 66) | private DRouter() {
method getInstance (line 74) | public static DRouter getInstance() {
method init (line 88) | public void init(Application context) {
method scanAddInterceptors (line 113) | private void scanAddInterceptors(final Context context) {
method action (line 147) | public RouterForward action(String actionName) {
method debugMessage (line 220) | private void debugMessage(String message) {
method showToast (line 232) | private void showToast(String message) {
method searchModuleClassName (line 242) | private String searchModuleClassName(String moduleName) {
FILE: drouter-api/src/main/java/com/drouter/api/core/RouterForward.java
class RouterForward (line 22) | public class RouterForward {
method threadMode (line 36) | public RouterForward threadMode(ThreadMode threadMode) {
method RouterForward (line 41) | RouterForward(ActionWrapper actionWrapper, List<ActionInterceptor> int...
method invokeAction (line 52) | public void invokeAction() {
method invokeAction (line 61) | public void invokeAction(ActionCallback actionCallback) {
method getThreadMode (line 75) | public ThreadMode getThreadMode() {
method context (line 79) | public RouterForward context(Context context) {
method param (line 84) | public RouterForward param(String key, Object value) {
method param (line 89) | public RouterForward param(Map<String, Object> params) {
FILE: drouter-api/src/main/java/com/drouter/api/exception/InitException.java
class InitException (line 9) | public class InitException extends RuntimeException {
method InitException (line 10) | public InitException(String message) {
FILE: drouter-api/src/main/java/com/drouter/api/exception/RouterActionException.java
class RouterActionException (line 9) | public class RouterActionException extends RuntimeException{
method RouterActionException (line 10) | public RouterActionException(String message) {
FILE: drouter-api/src/main/java/com/drouter/api/exception/RouterModuleException.java
class RouterModuleException (line 9) | public class RouterModuleException extends RuntimeException{
method RouterModuleException (line 10) | public RouterModuleException(String message) {
FILE: drouter-api/src/main/java/com/drouter/api/extra/ActionWrapper.java
class ActionWrapper (line 12) | public class ActionWrapper {
method ActionWrapper (line 19) | ActionWrapper() {
method setRouterAction (line 23) | public void setRouterAction(IRouterAction routerAction) {
method setThreadMode (line 27) | public void setThreadMode(ThreadMode threadMode) {
method getRouterAction (line 31) | public IRouterAction getRouterAction() {
method ActionWrapper (line 35) | private ActionWrapper(Class<? extends IRouterAction> actionClass, Stri...
method getActionClass (line 42) | public Class<? extends IRouterAction> getActionClass() {
method getThreadMode (line 46) | public ThreadMode getThreadMode() {
method getPath (line 50) | public String getPath() {
method isExtraProcess (line 54) | public boolean isExtraProcess() {
method build (line 58) | public static ActionWrapper build(Class<? extends IRouterAction> actio...
FILE: drouter-api/src/main/java/com/drouter/api/extra/Consts.java
class Consts (line 9) | public class Consts {
FILE: drouter-api/src/main/java/com/drouter/api/extra/DefaultLogger.java
class DefaultLogger (line 12) | public class DefaultLogger implements ILogger {
method showLog (line 16) | @Override
method d (line 21) | @Override
method i (line 28) | @Override
method w (line 35) | @Override
method e (line 42) | @Override
method getDefaultTag (line 50) | public String getDefaultTag() {
FILE: drouter-api/src/main/java/com/drouter/api/extra/ErrorActionWrapper.java
class ErrorActionWrapper (line 9) | public class ErrorActionWrapper extends ActionWrapper {
method ErrorActionWrapper (line 10) | public ErrorActionWrapper() {
FILE: drouter-api/src/main/java/com/drouter/api/extra/ILogger.java
type ILogger (line 9) | public interface ILogger {
method showLog (line 10) | void showLog(boolean isShowLog);
method d (line 12) | void d(String tag, String message);
method i (line 14) | void i(String tag, String message);
method w (line 16) | void w(String tag, String message);
method e (line 18) | void e(String tag, String message);
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/ActionInterceptor.java
type ActionInterceptor (line 11) | public interface ActionInterceptor {
method intercept (line 12) | void intercept(ActionChain chain);
type ActionChain (line 14) | interface ActionChain {
method onInterrupt (line 16) | void onInterrupt();
method proceed (line 19) | void proceed(ActionPost actionPost);
method action (line 22) | ActionPost action();
method actionPath (line 24) | String actionPath();
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/ActionInterceptorChain.java
class ActionInterceptorChain (line 13) | public class ActionInterceptorChain implements ActionInterceptor.ActionC...
method ActionInterceptorChain (line 20) | public ActionInterceptorChain(List<ActionInterceptor> interceptors, Ac...
method onInterrupt (line 26) | @Override
method proceed (line 32) | @Override
method action (line 44) | @Override
method actionPath (line 49) | @Override
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/CallActionInterceptor.java
class CallActionInterceptor (line 18) | public class CallActionInterceptor implements ActionInterceptor {
method intercept (line 19) | @Override
method invokeAction (line 32) | private void invokeAction(ActionPost actionPost, boolean isMainThread) {
method invokeAction (line 63) | private void invokeAction(ActionPost actionPost) {
FILE: drouter-api/src/main/java/com/drouter/api/interceptor/ErrorActionInterceptor.java
class ErrorActionInterceptor (line 13) | public class ErrorActionInterceptor implements ActionInterceptor {
method intercept (line 14) | @Override
FILE: drouter-api/src/main/java/com/drouter/api/result/ActionCallback.java
type ActionCallback (line 9) | public interface ActionCallback {
method onInterrupt (line 11) | void onInterrupt();
method onResult (line 14) | void onResult(RouterResult result);
method onInterrupt (line 19) | @Override
method onResult (line 24) | @Override
FILE: drouter-api/src/main/java/com/drouter/api/result/RouterResult.java
class RouterResult (line 9) | public class RouterResult {
method getCode (line 16) | public int getCode() {
method RouterResult (line 20) | private RouterResult(Builder builder) {
method toString (line 26) | @Override
method getMsg (line 35) | public String getMsg() {
method getObject (line 39) | public Object getObject() {
method isSucceed (line 48) | public boolean isSucceed() {
class Builder (line 53) | public static class Builder {
method error (line 58) | public Builder error() {
method success (line 63) | public Builder success() {
method msg (line 68) | public Builder msg(String msg) {
method object (line 73) | public Builder object(Object object) {
method build (line 78) | public RouterResult build() {
FILE: drouter-api/src/main/java/com/drouter/api/thread/ActionPost.java
class ActionPost (line 18) | public final class ActionPost {
method ActionPost (line 27) | private ActionPost(ActionWrapper actionWrapper, Context context, Map<S...
method obtainActionPost (line 34) | public static ActionPost obtainActionPost(ActionWrapper actionWrapper,...
method releasePendingPost (line 50) | public void releasePendingPost() {
FILE: drouter-api/src/main/java/com/drouter/api/thread/ActionPostQueue.java
class ActionPostQueue (line 9) | public class ActionPostQueue {
method enqueue (line 13) | synchronized void enqueue(ActionPost pendingPost) {
method poll (line 28) | synchronized ActionPost poll() {
method poll (line 39) | synchronized ActionPost poll(int maxMillisToWait) throws InterruptedEx...
FILE: drouter-api/src/main/java/com/drouter/api/thread/AsyncPoster.java
class AsyncPoster (line 13) | public class AsyncPoster implements Runnable, Poster {
method AsyncPoster (line 17) | AsyncPoster() {
method run (line 21) | @Override
method enqueue (line 36) | @Override
FILE: drouter-api/src/main/java/com/drouter/api/thread/BackgroundPoster.java
class BackgroundPoster (line 15) | final class BackgroundPoster implements Runnable, Poster {
method BackgroundPoster (line 21) | BackgroundPoster() {
method enqueue (line 25) | @Override
method run (line 36) | @Override
FILE: drouter-api/src/main/java/com/drouter/api/thread/HandlerPoster.java
class HandlerPoster (line 18) | public class HandlerPoster extends Handler implements Poster {
method HandlerPoster (line 23) | protected HandlerPoster(Looper looper, int maxMillisInsideHandleMessag...
method handleMessage (line 29) | @Override
method enqueue (line 68) | @Override
FILE: drouter-api/src/main/java/com/drouter/api/thread/Poster.java
type Poster (line 9) | public interface Poster {
method enqueue (line 10) | void enqueue(ActionPost actionPost);
FILE: drouter-api/src/main/java/com/drouter/api/thread/PosterSupport.java
class PosterSupport (line 14) | public class PosterSupport {
method getMainPoster (line 19) | public static Poster getMainPoster() {
method getExecutorService (line 30) | public static ExecutorService getExecutorService() {
method getBackgroundPoster (line 34) | public static Poster getBackgroundPoster() {
method getAsyncPoster (line 45) | public static Poster getAsyncPoster() {
FILE: drouter-api/src/main/java/com/drouter/api/utils/ClassUtils.java
class ClassUtils (line 28) | public class ClassUtils {
method getMultiDexPreferences (line 37) | private static SharedPreferences getMultiDexPreferences(Context contex...
method getFileNameByPackageName (line 44) | public static List<String> getFileNameByPackageName(Context context, S...
method getSourcePaths (line 75) | public static List<String> getSourcePaths(Context context) throws Pack...
method isVMMultidexCapable (line 112) | private static boolean isVMMultidexCapable() {
method isYunOS (line 147) | private static boolean isYunOS() {
FILE: drouter-api/src/main/java/com/drouter/api/utils/MapUtils.java
class MapUtils (line 15) | public class MapUtils {
method getInterceptorClasses (line 17) | public static List<ActionInterceptor> getInterceptorClasses(Map<Intege...
FILE: drouter-api/src/test/java/com/drouter/api/ExampleUnitTest.java
class ExampleUnitTest (line 12) | public class ExampleUnitTest {
method addition_isCorrect (line 13) | @Test
FILE: drouter-base/src/main/java/com/drouter/base/ThreadMode.java
type ThreadMode (line 9) | public enum ThreadMode {
FILE: drouter-compiler/src/main/java/com/drouter/compiler/Consts.java
class Consts (line 9) | public class Consts {
FILE: drouter-compiler/src/main/java/com/drouter/compiler/InterceptorProcessor.java
class InterceptorProcessor (line 38) | @AutoService(Processor.class)
method init (line 46) | @Override
method process (line 54) | @Override
method isNotEmpty (line 143) | private boolean isNotEmpty(Map<String, String> options) {
method error (line 147) | private void error(Element element, String message, String... args) {
method printMessage (line 151) | private void printMessage(Diagnostic.Kind kind, Element element, Strin...
method getSupportedSourceVersion (line 161) | @Override
method getSupportedAnnotationTypes (line 167) | @Override
method getSupportedAnnotations (line 176) | private Set<Class<? extends Annotation>> getSupportedAnnotations() {
FILE: drouter-compiler/src/main/java/com/drouter/compiler/ModuleProcessor.java
class ModuleProcessor (line 37) | @AutoService(Processor.class)
method init (line 44) | @Override
method process (line 52) | @Override
method isNotEmpty (line 167) | private boolean isNotEmpty(Map<String, String> options) {
method error (line 171) | private void error(Element element, String message, String... args) {
method printMessage (line 175) | private void printMessage(Diagnostic.Kind kind, Element element, Strin...
method getSupportedSourceVersion (line 185) | @Override
method getSupportedAnnotationTypes (line 191) | @Override
method getSupportedAnnotations (line 200) | private Set<Class<? extends Annotation>> getSupportedAnnotations() {
FILE: drouter-compiler/src/main/java/com/drouter/compiler/util/TextUtils.java
class TextUtils (line 9) | public class TextUtils {
method isEmpty (line 10) | public static boolean isEmpty(String moduleName) {
FILE: login-module/src/androidTest/java/com/login/module/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 17) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 19) | @Test
FILE: login-module/src/main/java/com/login/module/LoginAction.java
class LoginAction (line 19) | @Action(path = "login/action", threadMode = ThreadMode.MAIN)
method invokeAction (line 22) | @Override
FILE: login-module/src/main/java/com/login/module/LoginActivity.java
class LoginActivity (line 20) | public class LoginActivity extends AppCompatActivity {
method onCreate (line 21) | @Override
method click (line 30) | public void click(View view){
FILE: login-module/src/test/java/com/login/module/ExampleUnitTest.java
class ExampleUnitTest (line 12) | public class ExampleUnitTest {
method addition_isCorrect (line 13) | @Test
Condensed preview — 106 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (137K chars).
[
{
"path": ".gitignore",
"chars": 118,
"preview": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
},
{
"path": ".idea/gradle.xml",
"chars": 975,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"GradleSettings\">\n <option name=\"linke"
},
{
"path": ".idea/misc.xml",
"chars": 6238,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"MarkdownProjectSettings\">\n <PreviewSe"
},
{
"path": ".idea/modules.xml",
"chars": 1153,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": ".idea/runConfigurations.xml",
"chars": 564,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"RunConfigurationProducerService\">\n <o"
},
{
"path": ".idea/vcs.xml",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": "README.md",
"chars": 4091,
"preview": "# Android 平台多模块多组件开发的路由库\n\n\n### **一. DRouter 基本介绍**\n\n**1.** 该库所涉及到的类大概在 30 个左右,源码并不多相信我们都能读懂里面的内容,这里罗列一下源码中所涉及到的一些知识点:\n\n&"
},
{
"path": "app/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "app/build.gradle",
"chars": 1439,
"preview": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-android-extensions'\n\nandroi"
},
{
"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/darren/drouter/ExampleInstrumentedTest.kt",
"chars": 638,
"preview": "package com.darren.drouter\n\nimport android.support.test.InstrumentationRegistry\nimport android.support.test.runner.Andro"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 752,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package="
},
{
"path": "app/src/main/java/com/darren/drouter/BaseApplication.java",
"chars": 401,
"preview": "package com.darren.drouter;\n\nimport android.app.Application;\nimport com.drouter.api.core.DRouter;\n\n/**\n * description:\n "
},
{
"path": "app/src/main/java/com/darren/drouter/MainActivity.java",
"chars": 1486,
"preview": "package com.darren.drouter;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.suppor"
},
{
"path": "app/src/main/res/drawable/ic_launcher_background.xml",
"chars": 5606,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:wi"
},
{
"path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
"chars": 1880,
"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": 1166,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
"chars": 272,
"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": 272,
"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": 70,
"preview": "<resources>\n <string name=\"app_name\">DRouter</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/darren/drouter/ExampleUnitTest.kt",
"chars": 343,
"preview": "package com.darren.drouter\n\nimport org.junit.Test\n\nimport org.junit.Assert.*\n\n/**\n * Example local unit test, which will"
},
{
"path": "base-core/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "base-core/build.gradle",
"chars": 690,
"preview": "apply plugin: 'com.android.library'\n\nandroid {\n compileSdkVersion 26\n\n\n\n defaultConfig {\n minSdkVersion 15\n"
},
{
"path": "base-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": "base-core/src/androidTest/java/com/base/core/ExampleInstrumentedTest.java",
"chars": 732,
"preview": "package com.base.core;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport andr"
},
{
"path": "base-core/src/main/AndroidManifest.xml",
"chars": 100,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.base.core\" />\n"
},
{
"path": "base-core/src/main/res/values/strings.xml",
"chars": 72,
"preview": "<resources>\n <string name=\"app_name\">base-core</string>\n</resources>\n"
},
{
"path": "base-core/src/test/java/com/base/core/ExampleUnitTest.java",
"chars": 391,
"preview": "package com.base.core;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which"
},
{
"path": "build.gradle",
"chars": 643,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n e"
},
{
"path": "circle-module/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "circle-module/build.gradle",
"chars": 1102,
"preview": "apply plugin: 'com.android.library'\n\nandroid {\n compileSdkVersion 26\n\n repositories {\n mavenCentral()\n }"
},
{
"path": "circle-module/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": "circle-module/src/androidTest/java/com/example/circle_module/ExampleInstrumentedTest.java",
"chars": 756,
"preview": "package com.example.circle_module;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;"
},
{
"path": "circle-module/src/main/AndroidManifest.xml",
"chars": 323,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.example.circle_module\">\n\n <appl"
},
{
"path": "circle-module/src/main/java/com/example/circle_module/CircleAction.java",
"chars": 858,
"preview": "package com.example.circle_module;\n\nimport android.content.Context;\nimport android.content.Intent;\n\nimport com.drouter.a"
},
{
"path": "circle-module/src/main/java/com/example/circle_module/CircleActivity.java",
"chars": 1280,
"preview": "package com.example.circle_module;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android"
},
{
"path": "circle-module/src/main/java/com/example/circle_module/CircleInterceptor.java",
"chars": 1011,
"preview": "package com.example.circle_module;\n\nimport android.widget.Toast;\n\nimport com.drouter.api.core.DRouter;\nimport com.droute"
},
{
"path": "circle-module/src/main/java/com/example/circle_module/CircleInterceptor1.java",
"chars": 672,
"preview": "package com.example.circle_module;\n\nimport com.drouter.api.interceptor.ActionInterceptor;\nimport com.drouter.api.thread."
},
{
"path": "circle-module/src/main/java/com/example/circle_module/CircleInterceptor2.java",
"chars": 671,
"preview": "package com.example.circle_module;\n\nimport com.drouter.api.interceptor.ActionInterceptor;\nimport com.drouter.api.thread."
},
{
"path": "circle-module/src/main/res/layout/activity_circle.xml",
"chars": 793,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "circle-module/src/main/res/values/strings.xml",
"chars": 76,
"preview": "<resources>\n <string name=\"app_name\">circle-module</string>\n</resources>\n"
},
{
"path": "circle-module/src/test/java/com/example/circle_module/ExampleUnitTest.java",
"chars": 403,
"preview": "package com.example.circle_module;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit"
},
{
"path": "drouter-api/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "drouter-api/build.gradle",
"chars": 646,
"preview": "apply plugin: 'com.android.library'\n\nandroid {\n compileSdkVersion 26\n\n\n\n defaultConfig {\n minSdkVersion 15\n"
},
{
"path": "drouter-api/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": "drouter-api/src/androidTest/java/com/drouter/api/ExampleInstrumentedTest.java",
"chars": 736,
"preview": "package com.drouter.api;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport an"
},
{
"path": "drouter-api/src/main/AndroidManifest.xml",
"chars": 102,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.drouter.api\" />\n"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/action/IRouterAction.java",
"chars": 374,
"preview": "package com.drouter.api.action;\n\nimport android.content.Context;\n\nimport com.drouter.api.result.RouterResult;\n\nimport ja"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/action/IRouterInterceptor.java",
"chars": 333,
"preview": "package com.drouter.api.action;\n\nimport com.drouter.api.interceptor.ActionInterceptor;\n\nimport java.util.List;\n\n/**\n * d"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/action/IRouterModule.java",
"chars": 296,
"preview": "package com.drouter.api.action;\n\nimport com.drouter.api.extra.ActionWrapper;\n\n/**\n * description:\n * author: Darren on 2"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/core/DRouter.java",
"chars": 9053,
"preview": "package com.drouter.api.core;\n\nimport android.app.Application;\nimport android.content.Context;\nimport android.content.pm"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/core/RouterForward.java",
"chars": 2452,
"preview": "package com.drouter.api.core;\n\nimport android.content.Context;\n\nimport com.drouter.api.extra.ActionWrapper;\nimport com.d"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/exception/InitException.java",
"chars": 276,
"preview": "package com.drouter.api.exception;\n\n/**\n * description: 初始化异常类\n * author: Darren on 2018/1/22 10:26\n * email: 240336124@"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/exception/RouterActionException.java",
"chars": 308,
"preview": "package com.drouter.api.exception;\n\n/**\n * description: Router Action Exception\n * author: Darren on 2018/1/22 10:44\n * "
},
{
"path": "drouter-api/src/main/java/com/drouter/api/exception/RouterModuleException.java",
"chars": 308,
"preview": "package com.drouter.api.exception;\n\n/**\n * description: Router Module Exception\n * author: Darren on 2018/1/22 10:44\n * "
},
{
"path": "drouter-api/src/main/java/com/drouter/api/extra/ActionWrapper.java",
"chars": 1574,
"preview": "package com.drouter.api.extra;\n\nimport com.drouter.api.action.IRouterAction;\nimport com.drouter.base.ThreadMode;\n\n/**\n *"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/extra/Consts.java",
"chars": 602,
"preview": "package com.drouter.api.extra;\n\n/**\n * description:\n * author: Darren on 2018/1/22 10:01\n * email: 240336124@qq.com\n * v"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/extra/DefaultLogger.java",
"chars": 1210,
"preview": "package com.drouter.api.extra;\n\nimport android.text.TextUtils;\nimport android.util.Log;\n\n/**\n * description:\n * author: "
},
{
"path": "drouter-api/src/main/java/com/drouter/api/extra/ErrorActionWrapper.java",
"chars": 243,
"preview": "package com.drouter.api.extra;\n\n/**\n * description:\n * author: Darren on 2018/1/23 15:45\n * email: 240336124@qq.com\n * v"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/extra/ILogger.java",
"chars": 366,
"preview": "package com.drouter.api.extra;\n\n/**\n * description:\n * author: Darren on 2018/1/22 10:02\n * email: 240336124@qq.com\n * v"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/interceptor/ActionInterceptor.java",
"chars": 498,
"preview": "package com.drouter.api.interceptor;\n\nimport com.drouter.api.thread.ActionPost;\n\n/**\n * description: 拦截器\n * author: Darr"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/interceptor/ActionInterceptorChain.java",
"chars": 1424,
"preview": "package com.drouter.api.interceptor;\n\nimport com.drouter.api.thread.ActionPost;\n\nimport java.util.List;\n\n/**\n * descript"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/interceptor/CallActionInterceptor.java",
"chars": 2169,
"preview": "package com.drouter.api.interceptor;\n\n\nimport android.os.Looper;\n\nimport com.drouter.api.action.IRouterAction;\nimport co"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/interceptor/ErrorActionInterceptor.java",
"chars": 627,
"preview": "package com.drouter.api.interceptor;\n\n\nimport com.drouter.api.extra.ErrorActionWrapper;\nimport com.drouter.api.thread.Ac"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/result/ActionCallback.java",
"chars": 516,
"preview": "package com.drouter.api.result;\n\n/**\n * description:\n * author: Darren on 2018/1/24 09:05\n * email: 240336124@qq.com\n * "
},
{
"path": "drouter-api/src/main/java/com/drouter/api/result/RouterResult.java",
"chars": 1667,
"preview": "package com.drouter.api.result;\n\n/**\n * description: 路由的返回结果\n * author: Darren on 2018/1/22 10:35\n * email: 240336124@qq"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/thread/ActionPost.java",
"chars": 2036,
"preview": "package com.drouter.api.thread;\n\nimport android.content.Context;\n\nimport com.drouter.api.extra.ActionWrapper;\nimport com"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/thread/ActionPostQueue.java",
"chars": 1141,
"preview": "package com.drouter.api.thread;\n\n/**\n * description:\n * author: Darren on 2018/1/23 16:13\n * email: 240336124@qq.com\n * "
},
{
"path": "drouter-api/src/main/java/com/drouter/api/thread/AsyncPoster.java",
"chars": 1150,
"preview": "package com.drouter.api.thread;\n\nimport com.drouter.api.action.IRouterAction;\nimport com.drouter.api.extra.ActionWrapper"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/thread/BackgroundPoster.java",
"chars": 2152,
"preview": "package com.drouter.api.thread;\n\nimport com.drouter.api.action.IRouterAction;\nimport com.drouter.api.core.DRouter;\nimpor"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/thread/HandlerPoster.java",
"chars": 2707,
"preview": "package com.drouter.api.thread;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.os.Message;\nimport "
},
{
"path": "drouter-api/src/main/java/com/drouter/api/thread/Poster.java",
"chars": 206,
"preview": "package com.drouter.api.thread;\n\n/**\n * description:\n * author: Darren on 2018/1/23 16:05\n * email: 240336124@qq.com\n * "
},
{
"path": "drouter-api/src/main/java/com/drouter/api/thread/PosterSupport.java",
"chars": 1521,
"preview": "package com.drouter.api.thread;\n\nimport android.os.Looper;\n\nimport java.util.concurrent.ExecutorService;\nimport java.uti"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/utils/ClassUtils.java",
"chars": 6356,
"preview": "package com.drouter.api.utils;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport android"
},
{
"path": "drouter-api/src/main/java/com/drouter/api/utils/MapUtils.java",
"chars": 568,
"preview": "package com.drouter.api.utils;\n\nimport com.drouter.api.interceptor.ActionInterceptor;\n\nimport java.util.ArrayList;\nimpor"
},
{
"path": "drouter-api/src/main/res/values/strings.xml",
"chars": 74,
"preview": "<resources>\n <string name=\"app_name\">drouter-api</string>\n</resources>\n"
},
{
"path": "drouter-api/src/test/java/com/drouter/api/ExampleUnitTest.java",
"chars": 393,
"preview": "package com.drouter.api;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, whi"
},
{
"path": "drouter-base/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "drouter-base/build.gradle",
"chars": 165,
"preview": "apply plugin: 'java-library'\n\ndependencies {\n implementation fileTree(dir: 'libs', include: ['*.jar'])\n}\n\nsourceCompa"
},
{
"path": "drouter-base/src/main/java/com/drouter/base/ThreadMode.java",
"chars": 2189,
"preview": "package com.drouter.base;\n\n/**\n * description: thanks EventBus\n * author: Darren on 2018/1/23 08:57\n * email: 240336124@"
},
{
"path": "drouter-base/src/main/java/com/drouter/base/annotation/Action.java",
"chars": 669,
"preview": "package com.drouter.base.annotation;\n\nimport com.drouter.base.ThreadMode;\n\nimport java.lang.annotation.ElementType;\nimpo"
},
{
"path": "drouter-base/src/main/java/com/drouter/base/annotation/Interceptor.java",
"chars": 420,
"preview": "package com.drouter.base.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nim"
},
{
"path": "drouter-compiler/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "drouter-compiler/build.gradle",
"chars": 384,
"preview": "apply plugin: 'java-library'\n\ndependencies {\n implementation fileTree(include: ['*.jar'], dir: 'libs')\n implementa"
},
{
"path": "drouter-compiler/src/main/java/com/drouter/compiler/Consts.java",
"chars": 696,
"preview": "package com.drouter.compiler;\n\n/**\n * description:\n * author: Darren on 2018/1/22 10:01\n * email: 240336124@qq.com\n * ve"
},
{
"path": "drouter-compiler/src/main/java/com/drouter/compiler/InterceptorProcessor.java",
"chars": 7212,
"preview": "package com.drouter.compiler;\n\nimport com.drouter.base.annotation.Interceptor;\nimport com.drouter.compiler.util.TextUtil"
},
{
"path": "drouter-compiler/src/main/java/com/drouter/compiler/ModuleProcessor.java",
"chars": 8064,
"preview": "package com.drouter.compiler;\n\nimport com.drouter.base.annotation.Action;\nimport com.drouter.compiler.util.TextUtils;\nim"
},
{
"path": "drouter-compiler/src/main/java/com/drouter/compiler/util/TextUtils.java",
"chars": 287,
"preview": "package com.drouter.compiler.util;\n\n/**\n * description:\n * author: Darren on 2018/1/22 17:45\n * email: 240336124@qq.com\n"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 230,
"preview": "#Mon Jan 22 09:42:50 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": "login-module/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "login-module/build.gradle",
"chars": 929,
"preview": "apply plugin: 'com.android.library'\n\nandroid {\n compileSdkVersion 26\n\n repositories {\n mavenCentral()\n }"
},
{
"path": "login-module/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": "login-module/src/androidTest/java/com/login/module/ExampleInstrumentedTest.java",
"chars": 738,
"preview": "package com.login.module;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport a"
},
{
"path": "login-module/src/main/AndroidManifest.xml",
"chars": 312,
"preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.login.module\" >\n <application\n "
},
{
"path": "login-module/src/main/java/com/login/module/LoginAction.java",
"chars": 855,
"preview": "package com.login.module;\n\nimport android.content.Context;\nimport android.content.Intent;\n\nimport com.drouter.api.action"
},
{
"path": "login-module/src/main/java/com/login/module/LoginActivity.java",
"chars": 1404,
"preview": "package com.login.module;\n\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support."
},
{
"path": "login-module/src/main/res/layout/activity_login.xml",
"chars": 793,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmln"
},
{
"path": "login-module/src/main/res/values/strings.xml",
"chars": 75,
"preview": "<resources>\n <string name=\"app_name\">login-module</string>\n</resources>\n"
},
{
"path": "login-module/src/test/java/com/login/module/ExampleUnitTest.java",
"chars": 394,
"preview": "package com.login.module;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, wh"
},
{
"path": "settings.gradle",
"chars": 118,
"preview": "include ':app', ':drouter-api', ':login-module', ':base-core', ':drouter-compiler', ':drouter-base', ':circle-module'\n"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the HCDarren/DRouter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 106 files (117.8 KB), approximately 32.8k tokens, and a symbol index with 191 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.