[
  {
    "path": "README.md",
    "content": "#### 介绍\nXRetrofit   是一个极致模仿Retrofit 的风格代码，代码没有Retrofit 复杂，简单易懂。\n####\n 支持`get`、`post`、`put`、`delete` 请求，这些使用都一样。\n简化文件上传，跟下载 使用`@DOWNLOAD` 跟`@UPLOAD`\n简化` post` 表单请求跟JOSN请求。\n支持转换器，如果需要Gson的转换器，可以去demo那边去复制\n支持适配器，内置跟Retrofit的`Call<String>`，当然了String可以替换任意的类型，跟Retrofit一样\n没有内置`Rxjava的适配器`，如果需要，自己去demo那边复制。\n##### 区别\n`Retrofit`      属于运行时注解,通过动态代理生成一个代码\n`XRetrofit`   属于编译时注解，通过APT生成代码，如果要学习APT，可以操作这篇文章[《带你了解APT》点击传送门](https://www.jianshu.com/p/00dce41e5d00)\n\n##### 依赖,  只支持androidX,没有supper版本\n~~~\n    implementation 'com.yanxuwen.xretrofit:xretrofit:2.0.0'\n    annotationProcessor 'com.yanxuwen.xretrofit:xretrofit-compiler:2.0.0'\n~~~\n##### 依赖,  由于jcenter要跑路了，所以已迁移到jitpack  \n~~~\n    implementation 'com.github.yanxuwen:xretrofit:0.0.8'\n    annotationProcessor 'com.github.yanxuwen.xretrofit:compiler:0.0.8'\n~~~\n#### 使用方法，跟Retrofit一样，要定义接口，唯一区别在于在类上面要添加注解`@NetServiceClass`\n#### 定义接口，该例子分别写了`Rxjava`  、`Call`  、`同步请求`的使用\n~~~\n@NetServiceClass\npublic interface NetService {\n    /**\n     * Rxjava  适配器\n     */\n    @GET(\"api/manage-home/v5/home/detail-v2\")\n    Observable<HomeInfoV5> get(@Query(\"page\") int page, @Query(\"limit\") int limit);\n\n    /**\n     * 自带Call  适配器\n     */\n    @GET(\"api/manage-home/v5/home/{version}\")\n    Call<HomeInfoV5> get(@Path(\"version\") String version, @Query(\"page\") int page, @Query(\"limit\") int limit);\n\n    /**\n     * 同步请求\n     */\n    @GET(\"api/manage-home/v5/home/detail-v2\")\n    String get3(@Query(\"page\") int page, @Query(\"limit\") int limit);\n\n}\n~~~\n#### 执行请求，以Call 适配器为例子\n~~~\n   public void onGet2(View view) {\n        Call<HomeInfoV5> call = HttpRequest.getNetService().get(\"detail-v2\", 0, 10);\n        call.enqueue(new MyCallBack<HomeInfoV5>(this) {\n\n            @Override\n            public void success(HomeInfoV5 s) {\n                Log.e(\"yxw\", \"onGet:\" + s.getMsg());\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"onGet:\" + msg);\n            }\n\n            @Override\n            public void cancel() {\n                Log.e(\"yxw\", \"cancel\");\n            }\n        });\n\n    }\n~~~\n#### 执行请求，以Rxjava 适配器为例子\n~~~\n\n    /**\n     * get请求\n     */\n    public void onGet(View view) {\n        Observable<HomeInfoV5> observable = HttpRequest.getNetService().get(0, 10);\n        observable.subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .doOnDispose(new Action() {\n                    @Override\n                    public void run() throws Exception {\n                        Log.e(\"yxw\",\"取消订阅2\");\n                    }\n                })\n                .as(AutoDispose.<HomeInfoV5>autoDisposable(\n                        AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_PAUSE)))//OnDestory时自动解绑\n                .subscribe(new Observer<HomeInfoV5>() {\n                    @Override\n                    public void onSubscribe(@NonNull Disposable d) {\n                        Log.e(\"yxw\", \"onGet2 onSubscribe \");\n                    }\n\n                    @Override\n                    public void onNext(@NonNull HomeInfoV5 homeInfoV5) {\n                        Log.e(\"yxw\", \"onGet2 onNext \" + homeInfoV5.getMsg());\n                    }\n\n                    @Override\n                    public void onError(@NonNull Throwable e) {\n                        Log.e(\"yxw\", \"onGet2 fail \" + e.getMessage());\n                    }\n\n                    @Override\n                    public void onComplete() {\n                        Log.e(\"yxw\", \"onGet2 onComplete \");\n                    }\n                });\n\n    }\n\n    }\n~~~\n#### POST请求如何区分表单跟JOSN，，这里我们抛弃了Retrofit的复杂度\n例子如下：表单请求\n~~~\n    @FORM\n    @POST(\"https://bx-uat.bisinuolan.cn/api/login/mobile\")\n    Call<String> postForm(@Param(\"mobile\") String mobile, @Param(\"sms_code\") String sms_code);\n~~~\n注意2个注解 `@FORM` 跟`@Param`   我们舍弃了Retrofit的 `@Field` 跟`@FormUrlEncoded`  \n `@FORM` 替换了`@FormUrlEncoded`  来区分是否表单\n `@Param` 替换了`@Field`    ，\n `@Param` 有个好处就是：\n1、不管是表单请求还JSON请求，都是可以作为参数来传参\n2、如果用来Json请求的话，他会作为json格式的最外层数据，\n哎这个怎么解释呢。就是如果你用@Param(\"userId\")，那么最终传参是\n~~~\n{\n\t\"userId\": \"c053e1a2-7335-4451-9201-e25e805a19f5-1578390821008\"\n}\n~~~\n\n `@Body`    注解，可以这样传\n~~~\n    /**\n     * json 整串提交\n     */\n    @POST(\"api/customer/v1/open/user/level/my\")\n    Call<String> postJson2(@Body String json);\n\n    /**\n     * json 实体类提交\n     */\n    @POST(\"api/customer/v1/open/user/level/my\")\n    Call<String> postJson(@Body LoginBuild json);\n~~~\n `@Body`  注解跟Retrofit 注解一样，拥有一个功能，那是`转换器`，在添加转换器的时候，我们会通过 `@Body` 注解，判断当前是什么类型，然后通过类型，进行转换你想要的数据。。\n上面的那个实体类提交就是这个原理，判断是Object类型的话，然后将Object类型转换为JSON格式进行提交。\n那么你就可以定义你们公司需要啥类型，做啥处理。反正你们自己想。\n\n***\n\n#### 配置。这个是跟Retrofit是一样的。。\n\n        OkHttpClient client = new OkHttpClient\n                .Builder()\n                .connectTimeout(15, TimeUnit.SECONDS)//连接超时时间\n                .readTimeout(15, TimeUnit.SECONDS)//读取超时时间\n                .writeTimeout(15, TimeUnit.SECONDS)//写入超时时间\n                .retryOnConnectionFailure(false)//连接不上是否重连,false不重连\n                .hostnameVerifier(new TrustAllHostnameVerifier())//校验名称,这个对象就是信任所有的主机,也就是信任所有https的请求\n                .sslSocketFactory(SslUtils.getSslSocketFactory().sSLSocketFactory, SslUtils.getSslSocketFactory().trustManager)\n                .build();\n        HttpManager.Builder()\n                .baseUrl(\"https://bxapi.bisinuolan.cn/\")\n                .addConverterFactory(GsonConverterFactories.create())//FastJson转换器、可以替换成Gson\n                .addCallAdapterFactory(Rxjava2CallAdapterFactories.create())//Rxjava2适配器，不配置有自带Call适配器\n                .client(client)\n                .build();\n\n#### 出如何初始呢，NetService （类名是随便定义的）接口呢，那就是下面那个\n~~~\npublic class HttpRequest {\n\n    private static NetService netService;\n\n    public static NetService getNetService() {\n        try {\n            if (netService == null) {\n                synchronized (HttpRequest.class) {\n                    if (netService == null) {\n                        netService = (NetService) Class.forName(HttpManager.getImplName(NetService.class))\n                                .getConstructor().newInstance();\n                    }\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return netService;\n    }\n}\n\n~~~\n\n然后使用的时候就是直接\nHttpRequest.getNetService().get(0, 10);\n***\n### github  [点击跳转](https://github.com/yanxuwen/XRetrofit)\n### 如果你喜欢就去 github 帮我star下,非常感谢o(∩_∩)o~~~\n\n\n\n\n\n\n"
  },
  {
    "path": "XRetrofit/.gitignore",
    "content": "# Built application files\n*.apk\n*.ap_\n\n# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\nout/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Log Files\n*.log\n\n# Android Studio Navigation editor temp files\n.navigation/\n\n# Android Studio captures folder\ncaptures/\n\n# Intellij\n*.iml\n.idea/\n\n# Keystore files\n*.jks\n\n# External native build folder generated in Android Studio 2.2 and later\n.externalNativeBuild"
  },
  {
    "path": "XRetrofit/Could",
    "content": ""
  },
  {
    "path": "XRetrofit/annotations/.gitignore",
    "content": "/build"
  },
  {
    "path": "XRetrofit/annotations/build.gradle",
    "content": "apply plugin: 'java'\n\next {\n    bintrayName = 'annotations'\n    artifact = bintrayName\n    libraryName = 'xretrofit-annotations'\n    libraryDescription = 'this is a  xretrofit-annotations'\n    libraryVersion = main_version\n}\ncompileJava {\n    sourceCompatibility = '1.8'\n    targetCompatibility = '1.8'\n}\n\ndependencies {\n}\n\n//apply from: '../install.gradle'\n//apply from: '../bintray.gradle'\napply from: '../jitpack.gradle'\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/DELETE.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface DELETE {\n    String value() default \"\";\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/DOWNLOAD.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface DOWNLOAD {\n    String value() default \"\";\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/FORM.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n *  标记是否是表单提交\n */\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface FORM {\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/GET.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface GET {\n    String value() default \"\";\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/Headers.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface Headers {\n    String[] value();\n    boolean encoded() default false;\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/POST.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface POST {\n    String value() default \"\";\n\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/PUT.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface PUT {\n    String value() default \"\";\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/method/UPLOAD.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.method;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.METHOD})\n@Retention(RetentionPolicy.CLASS)\npublic @interface UPLOAD {\n    String value() default \"\";\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/param/Body.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.param;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.PARAMETER})\n@Retention(RetentionPolicy.CLASS)\npublic @interface Body {\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/param/FilePath.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.param;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n//用于文件上传用的路径\n//支持 File String List<File> List<String>\n@Documented\n@Target({ElementType.PARAMETER})\n@Retention(RetentionPolicy.CLASS)\npublic @interface FilePath {\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/param/Header.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.param;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Retention(RetentionPolicy.CLASS)\n@Target({ElementType.PARAMETER})\npublic @interface Header {\n    String value();\n    boolean encoded() default false;\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/param/Param.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.param;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.PARAMETER})\n@Retention(RetentionPolicy.CLASS)\npublic @interface Param {\n    String value();\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/param/Path.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.param;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Retention(RetentionPolicy.CLASS)\n@Target({ElementType.PARAMETER})\npublic @interface Path {\n    String value();\n\n    boolean encoded() default false;\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/param/Query.java",
    "content": "//\n// Source code recreated from a .class file by IntelliJ IDEA\n// (powered by Fernflower decompiler)\n//\n\npackage com.yanxuwen.xretrofit_annotations.annotation.param;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Documented\n@Target({ElementType.PARAMETER})\n@Retention(RetentionPolicy.CLASS)\npublic @interface Query {\n    String value();\n}\n"
  },
  {
    "path": "XRetrofit/annotations/src/main/java/com/yanxuwen/xretrofit_annotations/annotation/service/NetServiceClass.java",
    "content": "package com.yanxuwen.xretrofit_annotations.annotation.service;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target({ElementType.TYPE})\n@Retention(RetentionPolicy.CLASS)\npublic @interface NetServiceClass {\n    String value() default \"\";\n}\n"
  },
  {
    "path": "XRetrofit/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "XRetrofit/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion build_versions.target_sdk\n    buildToolsVersion build_versions.build_tools\n    defaultConfig {\n        applicationId \"com.yanxuwen.myhttpservice\"\n        minSdkVersion build_versions.min_sdk\n        targetSdkVersion build_versions.target_sdk\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n        multiDexEnabled true\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    repositories {\n        flatDir { dirs 'libs' }\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n}\n//自动导入libs目录下的aar文件\nfileTree(dir: 'libs', include: '**/*.aar').each { File file ->\n    dependencies.add(\"implementation\", [name: file.name.lastIndexOf('.').with {\n        it != -1 ? file.name[0..<it] : file.name\n    }, ext                                  : 'aar'])\n}\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    api support.app_compat\n    // RxJava\n    api other.rxandroid\n    api other.rxjava\n    //自动解绑取代RxLifecycle\n    api other.autoDispose\n    //权限\n    api other.rxpermissions\n\n    api other.fastjson\n\n    implementation project(path: ':xretrofit')\n    annotationProcessor project(':compiler')\n}\n"
  },
  {
    "path": "XRetrofit/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "XRetrofit/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.yanxuwen.xretrofit\">\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n    <application\n        android:networkSecurityConfig=\"@xml/network_security_config\"\n        android:name=\".MyApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/MainActivity.java",
    "content": "package com.yanxuwen.xretrofit;\n\nimport android.Manifest;\nimport android.os.Bundle;\nimport android.os.Environment;\nimport android.os.Looper;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.Toast;\n\nimport androidx.appcompat.app.AppCompatActivity;\nimport androidx.lifecycle.Lifecycle;\n\nimport com.tbruyelle.rxpermissions2.Permission;\nimport com.tbruyelle.rxpermissions2.RxPermissions;\nimport com.uber.autodispose.AutoDispose;\nimport com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider;\nimport com.xretrofit.call.Call;\nimport com.xretrofit.call.ProgressCall;\nimport com.yanxuwen.xretrofit.bean.HomeInfoV5;\nimport com.yanxuwen.xretrofit.bean.LoginBuild;\nimport com.yanxuwen.xretrofit.callback.MyCallBack;\nimport com.yanxuwen.xretrofit.callback.MyProgressCallBack;\nimport com.yanxuwen.xretrofit.http.HttpRequest;\n\nimport io.reactivex.Observable;\nimport io.reactivex.Observer;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.annotations.NonNull;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Action;\nimport io.reactivex.functions.Consumer;\nimport io.reactivex.schedulers.Schedulers;\n\npublic class MainActivity extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n    }\n\n    public boolean isMainThread() {\n        return Looper.getMainLooper().getThread() == Thread.currentThread();\n    }\n\n    /**\n     * get请求\n     */\n    public void onGet(View view) {\n        Observable<HomeInfoV5> observable = HttpRequest.getNetService().get(0, 10);\n        observable\n                .as(RxSchedulers.applySchedulers(this))\n                .subscribe(new Observer<HomeInfoV5>() {\n                    @Override\n                    public void onSubscribe(@NonNull Disposable d) {\n                        Log.e(\"yxw\", isMainThread() +\" onGet2 onSubscribe \");\n                    }\n\n                    @Override\n                    public void onNext(@NonNull HomeInfoV5 homeInfoV5) {\n                        Log.e(\"yxw\", isMainThread() + \" onGet2 onNext \" + homeInfoV5.getMsg());\n                    }\n\n                    @Override\n                    public void onError(@NonNull Throwable e) {\n                        Log.e(\"yxw\", \"onGet2 fail \" + e.getMessage());\n                    }\n\n                    @Override\n                    public void onComplete() {\n                        Log.e(\"yxw\", isMainThread() + \" onGet2 onComplete \");\n                    }\n                });\n\n    }\n\n    /**\n     * get请求(URL中带有参数,也支持post)\n     */\n    public void onGet2(View view) {\n        Call<HomeInfoV5> call = HttpRequest.getNetService().get(\"detail-v2\", 0, 10);\n        call.enqueue(new MyCallBack<HomeInfoV5>(this) {\n\n            @Override\n            public void success(HomeInfoV5 s) {\n                Log.e(\"yxw\", \"onGet:\" + s.getMsg());\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"onGet:\" + msg);\n            }\n\n            @Override\n            public void cancel() {\n                Log.e(\"yxw\", \"cancel\");\n            }\n        });\n\n    }\n\n    /**\n     * 表单提交\n     */\n    public void postForm(View view) {\n        Call<String> call = HttpRequest.getNetService().postForm(\"19906058322\", \"10960\");\n        call.enqueue(new MyCallBack<String>() {\n            @Override\n            public void success(String s) {\n                Log.e(\"yxw\", \"postForm:\" + s);\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"postForm:\" + msg);\n            }\n        });\n    }\n\n    /**\n     * json提交\n     */\n    public void postJson(View view) {\n        String userId = \"c053e1a2-7335-4451-9201-e25e805a19f5-1578390821008\";\n        Call<String> call = HttpRequest.getNetService().postJson(userId);\n        call.enqueue(new MyCallBack<String>() {\n            @Override\n            public void success(String s) {\n                Log.e(\"yxw\", \"postJson:\" + s);\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"postJson:\" + msg);\n            }\n        });\n    }\n\n    /**\n     * json 整串提交\n     */\n    public void postJson2(View view) {\n        String json = \"{\\n\" +\n                \"\\t\\\"userId\\\": \\\"c053e1a2-7335-4451-9201-e25e805a19f5-1578390821008\\\"\\n\" +\n                \"}\";\n        Call<String> call = HttpRequest.getNetService().postJson2(json);\n        call.enqueue(new MyCallBack<String>() {\n            @Override\n            public void success(String s) {\n                Log.e(\"yxw\", \"postJson2:\" + s);\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"postJson2:\" + msg);\n            }\n        });\n    }\n\n    /**\n     * json 整串提交\n     */\n    public void postJson3(View view) {\n        LoginBuild mLoginBuild = new LoginBuild();\n        mLoginBuild.setUserId(\"c053e1a2-7335-4451-9201-e25e805a19f5-1578390821008\");\n        Call<String> call = HttpRequest.getNetService().postJson(mLoginBuild);\n        call.enqueue(new MyCallBack<String>() {\n            @Override\n            public void success(String s) {\n                Log.e(\"yxw\", \"postJson2:\" + s);\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"postJson2:\" + msg);\n            }\n        });\n    }\n\n    /**\n     * put 提交\n     */\n    public void onPut(View view) {\n        Call<String> call = HttpRequest.getNetService().put(\"header\", \"测试\", \"signature\", \"area\");\n        call.enqueue(new MyCallBack<String>() {\n            @Override\n            public void success(String s) {\n                Log.e(\"yxw\", \"onPut :\" + s);\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"onPut fail :\" + msg);\n            }\n        });\n    }\n\n    /**\n     * delete 提交\n     */\n    public void onDelete(View view) {\n        Call<String> call = HttpRequest.getNetService().delete(\"header\", \"123231\");\n        call.enqueue(new MyCallBack<String>() {\n            @Override\n            public void success(String s) {\n                Log.e(\"yxw\", \"onDelete :\" + s);\n            }\n\n            @Override\n            public void fail(String msg) {\n                Log.e(\"yxw\", \"onDelete fail :\" + msg);\n            }\n        });\n    }\n\n    public void onDownload(View v) {\n        //先权限申请，在请求\n        RxPermissions rxPermissions = new RxPermissions(this);\n        rxPermissions.requestEach(\n                Manifest.permission.WRITE_EXTERNAL_STORAGE)\n                .subscribe(new Consumer<Permission>() {\n                    @Override\n                    public void accept(Permission permission) throws Exception {\n                        if (permission.granted) {\n                            String path = Environment.getExternalStorageDirectory().toString() + \"/测试/text2.apk\";//获取目录\n                            ProgressCall<String> call = HttpRequest.getNetService().download(path);\n                            call.enqueue(new MyProgressCallBack<String>() {\n                                @Override\n                                public void onProgress(float progress) {\n                                    Log.e(\"yxw\", \"onDownload progress :\" + progress);\n                                }\n\n                                @Override\n                                public void success(String s) {\n                                    Log.e(\"yxw\", \"onDownload  :\" + s);\n                                }\n\n                                @Override\n                                public void fail(String msg) {\n                                    Log.e(\"yxw\", \"onDownload fail :\" + msg);\n                                }\n                            });\n                        } else {\n                            Toast.makeText(MainActivity.this, \"请打开存储权限\", Toast.LENGTH_SHORT).show();\n                        }\n                    }\n                });\n    }\n\n    public void onUpload(View v) {\n//        //先权限申请，在请求\n        RxPermissions rxPermissions = new RxPermissions(this);\n        rxPermissions.requestEach(\n                Manifest.permission.WRITE_EXTERNAL_STORAGE)\n                .subscribe(new Consumer<Permission>() {\n                    @Override\n                    public void accept(Permission permission) throws Exception {\n                        if (permission.granted) {\n                            //允许权限\n                            String path = Environment.getExternalStorageDirectory().toString() + \"/测试/测试.mp4\";//获取跟目录\n                            ProgressCall<String> call = HttpRequest.getNetService().upload(path, true);\n                            call.enqueue(new MyProgressCallBack<String>() {\n                                @Override\n                                public void success(String s) {\n                                    Log.e(\"yxw\", \"onUpload :\" + s);\n                                }\n\n                                @Override\n                                public void fail(String msg) {\n                                    Log.e(\"yxw\", \"onUpload2 fail:\" + msg);\n                                }\n\n                                @Override\n                                public void onProgress(float progress) {\n                                    Log.e(\"yxw\", \"onUpload2 progress:\" + progress);\n                                }\n                            });\n                        } else {\n                            Toast.makeText(MainActivity.this, \"请打开存储权限\", Toast.LENGTH_SHORT).show();\n                        }\n                    }\n                });\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/MyApplication.java",
    "content": "package com.yanxuwen.xretrofit;\n\nimport android.app.Application;\n\nimport com.xretrofit.HttpManager;\nimport com.xretrofit.okhttp.SslUtils;\nimport com.yanxuwen.xretrofit.converter.GsonConverterFactories;\nimport com.yanxuwen.xretrofit.converter.Rxjava2CallAdapterFactories;\n\nimport java.util.concurrent.TimeUnit;\n\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.SSLSession;\n\nimport okhttp3.OkHttpClient;\n\npublic class MyApplication extends Application {\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        init();\n    }\n\n    public void init() {\n\n        OkHttpClient client = new OkHttpClient\n                .Builder()\n                .connectTimeout(15, TimeUnit.SECONDS)//连接超时时间\n                .readTimeout(15, TimeUnit.SECONDS)//读取超时时间\n                .writeTimeout(15, TimeUnit.SECONDS)//写入超时时间\n                .retryOnConnectionFailure(false)//连接不上是否重连,false不重连\n                .hostnameVerifier(new TrustAllHostnameVerifier())//校验名称,这个对象就是信任所有的主机,也就是信任所有https的请求\n                .sslSocketFactory(SslUtils.getSslSocketFactory().sSLSocketFactory, SslUtils.getSslSocketFactory().trustManager)\n                .build();\n        HttpManager.Builder()\n                .baseUrl(\"https://bxapi.bisinuolan.cn/\")\n                .addConverterFactory(GsonConverterFactories.create())//FastJson转换器、可以替换成Gson\n                .addCallAdapterFactory(Rxjava2CallAdapterFactories.create())//Rxjava2适配器，不配置有自带Call适配器\n                .client(client)\n                .build();\n    }\n\n    /**\n     * 信任所有的服务器,返回true\n     */\n    private static class TrustAllHostnameVerifier implements HostnameVerifier {\n        @Override\n        public boolean verify(String hostname, SSLSession session) {\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/RxSchedulers.java",
    "content": "package com.yanxuwen.xretrofit;\n\nimport androidx.lifecycle.Lifecycle;\nimport androidx.lifecycle.LifecycleOwner;\n\nimport com.uber.autodispose.AutoDispose;\nimport com.uber.autodispose.ObservableSubscribeProxy;\nimport com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider;\n\nimport io.reactivex.Observable;\nimport io.reactivex.ObservableConverter;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.annotations.NonNull;\nimport io.reactivex.schedulers.Schedulers;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/3/19 10:52\n * Description :\n */\npublic class RxSchedulers {\n    public static <T> ObservableConverter<T, ObservableSubscribeProxy> applySchedulers(LifecycleOwner owner) {\n        return new ObservableConverter<T, ObservableSubscribeProxy>() {\n            @NonNull\n            @Override\n            public ObservableSubscribeProxy apply(@NonNull Observable<T> upstream) {\n                return upstream\n                        .subscribeOn(Schedulers.io())\n                        .observeOn(AndroidSchedulers.mainThread())\n                        .as(AutoDispose.autoDisposable(\n                                AndroidLifecycleScopeProvider.from(owner, Lifecycle.Event.ON_DESTROY)));\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/bean/HomeInfoV5.java",
    "content": "package com.yanxuwen.xretrofit.bean;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/19 9:21\n * Description :\n */\npublic class HomeInfoV5 {\n\n    private String msg;\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/bean/LoginBuild.java",
    "content": "package com.yanxuwen.xretrofit.bean;\n\npublic class LoginBuild {\n\n    /**\n     * password : “123456”\n     * mobile : “15060568265”\n     */\n\n    private String userId;\n    private String msg;\n\n    public String getUserId() {\n        return userId;\n    }\n\n    public void setUserId(String userId) {\n        this.userId = userId;\n    }\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/callback/MyCallBack.java",
    "content": "package com.yanxuwen.xretrofit.callback;\n\nimport android.util.Log;\n\nimport androidx.fragment.app.FragmentActivity;\nimport androidx.lifecycle.Lifecycle;\nimport androidx.lifecycle.LifecycleObserver;\nimport androidx.lifecycle.OnLifecycleEvent;\n\nimport com.xretrofit.Response;\nimport com.xretrofit.call.Call;\nimport com.xretrofit.callback.CallBack;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/5 11:19\n * Description :\n */\npublic abstract class MyCallBack<T> implements CallBack<T> {\n\n    private FragmentActivity activity;\n\n    public MyCallBack() {\n    }\n\n    public MyCallBack(FragmentActivity activity) {\n        this.activity = activity;\n    }\n\n    @Override\n    public void onStart(Call<T> call) {\n        if (activity != null) {\n            activity.getLifecycle().addObserver(new LifecycleObserver() {\n                @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)\n                public void onDestroy() {\n                    Log.e(\"yxw\", \"????取消请求\");\n                    call.cancel();\n                }\n\n            });\n        }\n    }\n\n    @Override\n    public final void onSuccess(Call<T> call, Response<T> response) {\n        if (response.errorBody() != null) {\n            fail(\"网络异常\");\n            return;\n        }\n        success(response.body());\n\n    }\n\n    @Override\n    public final void onFail(Call<T> call, Throwable e) {\n        if (call.isCanceled()){\n            cancel();\n        } else {\n            fail(ServerException.handleException(e));\n        }\n    }\n\n\n    public abstract void success(T t);\n\n    public abstract void fail(String msg);\n\n    public void cancel(){\n\n    }\n\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/callback/MyProgressCallBack.java",
    "content": "package com.yanxuwen.xretrofit.callback;\n\nimport com.xretrofit.Response;\nimport com.xretrofit.call.Call;\nimport com.xretrofit.callback.ProgressCallBack;\n\npublic abstract class MyProgressCallBack<T> extends ProgressCallBack<T> {\n\n    @Override\n    public void onStart(Call<T> call) {\n\n    }\n\n    @Override\n    public final void onSuccess(Call<T> call, Response<T> response) {\n        if (response.errorBody() != null) {\n            fail(\"网络异常\");\n            return;\n        }\n        success(response.body());\n\n    }\n\n    @Override\n    public final void onFail(Call<T> call, Throwable e) {\n        fail(ServerException.handleException(e));\n    }\n\n\n    public abstract void success(T t);\n\n    public abstract void fail(String msg);\n\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/callback/ServerException.java",
    "content": "package com.yanxuwen.xretrofit.callback;\n\nimport org.apache.http.conn.ConnectTimeoutException;\nimport org.json.JSONException;\n\nimport java.io.NotSerializableException;\nimport java.net.ConnectException;\nimport java.net.SocketTimeoutException;\nimport java.net.UnknownHostException;\nimport java.text.ParseException;\n\npublic class ServerException {\n\n    public static  String handleException(Throwable e) {\n        String msg = e.getMessage();\n        if (e instanceof SocketTimeoutException) {\n            msg = \"网络连接超时，请检查网络\";\n        } else if (e instanceof ConnectException) {\n            msg = \"网络异常，请检查网络\";\n        } else if (e instanceof ConnectTimeoutException) {\n            msg = \"网络连接超时，请检查网络\";\n        } else if (e instanceof UnknownHostException) {\n            msg = \"网络异常，请检查网络\";\n        } else if (e instanceof NullPointerException) {\n            msg = \"空指针异常\";\n        } else if (e instanceof javax.net.ssl.SSLHandshakeException) {\n            msg = \"证书验证失败\";\n        } else if (e instanceof ClassCastException) {\n            msg = \"类型转换错误\";\n        } else if (/*e instanceof JsonParseException ||*/\n            e instanceof JSONException ||\n                e instanceof com.alibaba.fastjson.JSONException ||\n                /*e instanceof JsonSerializer ||*/\n                e instanceof NotSerializableException ||\n                e instanceof ParseException) {\n            msg = \"解析错误\";\n        }\n        return msg;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/converter/GsonConverterFactories.java",
    "content": "package com.yanxuwen.xretrofit.converter;\n\nimport com.xretrofit.converter.Converter;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\nimport okhttp3.RequestBody;\nimport okhttp3.ResponseBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 15:46\n * Description :\n * 接口数据转换器\n * fastjson转换器\n */\npublic class GsonConverterFactories extends Converter.Factory {\n\n    public static GsonConverterFactories create() {\n        return new GsonConverterFactories();\n    }\n\n    @Nullable\n    @Override\n    public Converter<?, RequestBody> requestBodyConverter(Type request, Type requestParamType) {\n        if (requestParamType instanceof Object) {\n            return new GsonRequestConverter();\n        }\n        return null;\n    }\n\n    @Nullable\n    @Override\n    public Converter<ResponseBody, ?> responseBodyConverter(Type request, Type responseType) {\n        Class<?> rawType = getRawType(responseType);\n        if (rawType instanceof Object) {\n            return new GsonResponseConverter(responseType);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/converter/GsonRequestConverter.java",
    "content": "package com.yanxuwen.xretrofit.converter;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.xretrofit.converter.Converter;\n\nimport okhttp3.MediaType;\nimport okhttp3.RequestBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/5 16:00\n * Description :\n * 请求参数数据转换\n */\nclass GsonRequestConverter<T> implements Converter<T, RequestBody> {\n    private static final MediaType JSON = MediaType.parse(\"application/json;charset=utf-8\");\n\n\n    @Override\n    public RequestBody convert(T value) throws Exception {\n        RequestBody requestBody = RequestBody.create(JSON, JSONObject.toJSONString(value));\n        return requestBody;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/converter/GsonResponseConverter.java",
    "content": "package com.yanxuwen.xretrofit.converter;\n\nimport com.alibaba.fastjson.JSONObject;\nimport com.xretrofit.converter.Converter;\n\nimport java.lang.reflect.Type;\n\nimport okhttp3.ResponseBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 17:09\n * Description :\n * 请求结果数据转换\n * Gson操作\n */\npublic class GsonResponseConverter<T> implements Converter<ResponseBody, T> {\n\n    private Type responseType;\n\n    protected GsonResponseConverter(Type responseType){\n        this.responseType = responseType;\n    }\n\n\n    @Override\n    public T convert(ResponseBody value) throws Exception {\n        String responseStr = value.string();\n        return (T) JSONObject.parseObject(responseStr,responseType);\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/converter/Rxjava2CallAdapter.java",
    "content": "package com.yanxuwen.xretrofit.converter;\n\nimport com.xretrofit.CallAdapter.CallAdapter;\nimport com.xretrofit.HttpException;\nimport com.xretrofit.Response;\nimport com.xretrofit.call.Call;\n\nimport java.lang.ref.WeakReference;\nimport java.lang.reflect.Type;\n\nimport io.reactivex.Observable;\nimport io.reactivex.Observer;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.exceptions.CompositeException;\nimport io.reactivex.exceptions.Exceptions;\nimport io.reactivex.plugins.RxJavaPlugins;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/8 10:19\n * Description :\n * rxjava 适配器\n */\nclass Rxjava2CallAdapter<T> implements CallAdapter<Observable, T> {\n\n    private Type responseType;\n\n    protected Rxjava2CallAdapter(Type responseType) {\n        this.responseType = responseType;\n    }\n\n\n    @Override\n    public Type responseType() {\n        return responseType;\n    }\n\n\n    @Override\n    public Observable adapt(Call<T> call) {\n        Observable observable = new CallExecuteObservable(call);\n        return observable;\n    }\n\n    final class CallExecuteObservable<T> extends Observable<T> {\n        private final Call<T> call;\n\n\n        CallExecuteObservable(Call<T> call) {\n            this.call = call;\n\n        }\n\n        @Override\n        protected void subscribeActual(Observer<? super T> observer) {\n            CallDisposable disposable = new CallDisposable(call);\n            observer.onSubscribe(disposable);\n            Response<T> response = null;\n            try {\n                response = call.execute();\n                if (response.isSuccessful()) {\n                    observer.onNext((T) response.body());\n                } else {\n                    Throwable t = new HttpException(response);\n                    try {\n                        observer.onError(t);\n                    } catch (Throwable inner) {\n                        Exceptions.throwIfFatal(inner);\n                        RxJavaPlugins.onError(new CompositeException(t, inner));\n                    }\n                }\n            } catch (Throwable t) {\n                Exceptions.throwIfFatal(t);\n                if (!disposable.isDisposed()) {\n                    try {\n                        observer.onError(t);\n                    } catch (Throwable inner) {\n                        Exceptions.throwIfFatal(inner);\n                        RxJavaPlugins.onError(new CompositeException(t, inner));\n                    }\n                }\n            }\n            observer.onComplete();\n        }\n\n    }\n\n\n    private static final class CallDisposable implements Disposable {\n        private volatile boolean disposed;\n        private WeakReference<Call> weakCall;\n\n        CallDisposable(Call<?> call) {\n            weakCall = new WeakReference<>(call);\n\n        }\n\n        @Override\n        public void dispose() {\n            disposed = true;\n            if (weakCall != null) {\n                weakCall.get().cancel();\n            }\n        }\n\n        @Override\n        public boolean isDisposed() {\n            return disposed;\n        }\n    }\n}"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/converter/Rxjava2CallAdapterFactories.java",
    "content": "package com.yanxuwen.xretrofit.converter;\n\nimport com.xretrofit.CallAdapter.CallAdapter;\nimport com.xretrofit.utils.Utils;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\nimport io.reactivex.Observable;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 15:46\n * Description :\n * rxjava2 适配器\n */\npublic class Rxjava2CallAdapterFactories<T> extends CallAdapter.Factory {\n\n    public static Rxjava2CallAdapterFactories create() {\n        return new Rxjava2CallAdapterFactories();\n    }\n\n\n    @Nullable\n    @Override\n    public CallAdapter<Observable, T> get(Type returnType) {\n        Class<?> rawType = getRawType(returnType);\n        final Type responseType = Utils.getCallResponseType(returnType);\n        if (rawType == Observable.class) {\n            return new Rxjava2CallAdapter<T>(responseType);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/http/HttpRequest.java",
    "content": "package com.yanxuwen.xretrofit.http;\n\nimport com.xretrofit.HttpManager;\n\npublic class HttpRequest {\n\n    private static NetService netService;\n\n    public static NetService getNetService() {\n        try {\n            if (netService == null) {\n                synchronized (HttpRequest.class) {\n                    if (netService == null) {\n                        netService = (NetService) Class.forName(HttpManager.getImplName(NetService.class))\n                                .getConstructor().newInstance();\n                    }\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return netService;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/app/src/main/java/com/yanxuwen/xretrofit/http/NetService.java",
    "content": "package com.yanxuwen.xretrofit.http;\n\nimport com.xretrofit.call.Call;\nimport com.xretrofit.call.ProgressCall;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.DELETE;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.DOWNLOAD;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.FORM;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.GET;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.POST;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.PUT;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.UPLOAD;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Body;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.FilePath;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Header;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Param;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Path;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Query;\nimport com.yanxuwen.xretrofit_annotations.annotation.service.NetServiceClass;\nimport com.yanxuwen.xretrofit.bean.HomeInfoV5;\nimport com.yanxuwen.xretrofit.bean.LoginBuild;\n\nimport io.reactivex.Observable;\n\n@NetServiceClass\npublic interface NetService {\n    /**\n     * get\n     */\n    @GET(\"api/manage-home/v5/home/detail-v2\")\n    Observable<HomeInfoV5> get(@Query(\"page\") int page, @Query(\"limit\") int limit);\n\n    /**\n     * get请求(URL中带有参数)\n     */\n    @GET(\"api/manage-home/v5/home/{version}\")\n    Call<HomeInfoV5> get(@Path(\"version\") String version, @Query(\"page\") int page, @Query(\"limit\") int limit);\n\n    /**\n     * 表单提交\n     */\n    @FORM\n    @POST(\"https://bx-uat.bisinuolan.cn/api/login/mobile\")\n    Call<String> postForm(@Param(\"mobile\") String mobile, @Param(\"sms_code\") String sms_code);\n\n    /**\n     * json提交\n     */\n    @POST(\"https://bx-co-uat-appgateway.bsnlco.com/api/customer/v1/open/user/level/my\")\n    Call<String> postJson(@Param(\"userId\") String userId);\n\n    /**\n     * json 整串提交\n     */\n    @POST(\"https://bx-co-uat-appgateway.bsnlco.com/api/customer/v1/open/user/level/my\")\n    Call<String> postJson2(@Body String json);\n\n    /**\n     * json 实体类提交\n     */\n    @POST(\"https://bx-co-uat-appgateway.bsnlco.com/api/customer/v1/open/user/level/my\")\n    Call<String> postJson(@Body LoginBuild json);\n\n    /**\n     * put 提交\n     */\n    @PUT(\"http://api.sdwhcn.com:5056/v1/member\")\n    Call<String> put(@Header(\"Authorization\") String header, @Query(\"nickname\") String nickname, @Query(\"signature\") String signature, @Query(\"area\") String area);\n\n    /**\n     * delete 提交\n     */\n    @DELETE(\"http://api.sdwhcn.com:5056/v1/member_collect_article/{id}\")\n    Call<String> delete(@Header(\"Authorization\") String header, @Path(\"id\") String id);\n\n    /**\n     *\n     */\n    @DOWNLOAD(\"https://ztjyupdate.ztjy61.com/333897c77ec9a86605006679c7a4b418-ZTJY\")\n    ProgressCall<String> download(@FilePath String file);\n\n    /**\n     * 多图上传\n     */\n    @UPLOAD(\"https://bxuatapi.bisinuolan.cn/api/bsnl-oss/appUploadShot\")\n    ProgressCall<String> upload(@FilePath String file, @Param(\"shot\") boolean shot);\n\n}"
  },
  {
    "path": "XRetrofit/app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillColor=\"#008577\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeWidth=\"0.8\"\n        android:strokeColor=\"#33FFFFFF\" />\n</vector>\n"
  },
  {
    "path": "XRetrofit/app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportWidth=\"108\"\n    android:viewportHeight=\"108\">\n    <path\n        android:fillType=\"evenOdd\"\n        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\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"78.5885\"\n                android:endY=\"90.9159\"\n                android:startX=\"48.7653\"\n                android:startY=\"61.0927\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        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\"\n        android:strokeWidth=\"1\"\n        android:strokeColor=\"#00000000\" />\n</vector>\n"
  },
  {
    "path": "XRetrofit/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/activity_main\"\n    android:orientation=\"vertical\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n    <Button\n        android:id=\"@+id/tv_get\"\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"get请求\"\n        android:onClick=\"onGet\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"get请求(URL中带有参数)\"\n        android:onClick=\"onGet2\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"post表单提交\"\n        android:onClick=\"postForm\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"json提交\"\n        android:onClick=\"postJson\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"json 整串提交\"\n        android:onClick=\"postJson2\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"json 实体类提交\"\n        android:onClick=\"postJson3\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"put 提交\"\n        android:onClick=\"onPut\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"delete 提交\"\n        android:onClick=\"onDelete\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"文件下载\"\n        android:onClick=\"onDownload\"\n        />\n    <Button\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"文件上传\"\n        android:onClick=\"onUpload\"\n        />\n</LinearLayout>\n"
  },
  {
    "path": "XRetrofit/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "XRetrofit/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "XRetrofit/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#008577</color>\n    <color name=\"colorPrimaryDark\">#00574B</color>\n    <color name=\"colorAccent\">#D81B60</color>\n</resources>\n"
  },
  {
    "path": "XRetrofit/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">XRetrofit</string>\n</resources>\n"
  },
  {
    "path": "XRetrofit/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "XRetrofit/app/src/main/res/xml/network_security_config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--解决安卓P 没有使用https的话会报 CLEARTEXT communication to api.sdwhcn.com not permitted by network security policy-->\n<network-security-config>\n    <base-config cleartextTrafficPermitted=\"true\" />\n</network-security-config>"
  },
  {
    "path": "XRetrofit/bintray.gradle",
    "content": "// backup of [https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle]\n\napply plugin: 'com.jfrog.bintray'\n\nversion = libraryVersion\n\nif (project.hasProperty(\"android\")) { // Android libraries\n    task sourcesJar(type: Jar) {\n        classifier = 'sources'\n        from android.sourceSets.main.java.srcDirs\n    }\n\n    task javadoc(type: Javadoc) {\n        source = android.sourceSets.main.java.srcDirs\n        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))\n    }\n} else { // Java libraries\n    task sourcesJar(type: Jar, dependsOn: classes) {\n        classifier = 'sources'\n        from sourceSets.main.allSource\n    }\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from javadoc.destinationDir\n}\n\nartifacts {\n    archives javadocJar\n    archives sourcesJar\n}\n\njavadoc {\n    failOnError false\n    options {\n        encoding \"UTF-8\"\n        charSet 'UTF-8'\n        author true\n        version true\n        links \"http://docs.oracle.com/javase/7/docs/api\"\n    }\n}\n\n// Bintray\nProperties properties = new Properties()\nproperties.load(project.rootProject.file('local.properties').newDataInputStream())\n\nbintray {\n    user = properties.getProperty(\"bintray.user\")\n    key = properties.getProperty(\"bintray.apikey\")\n\n    configurations = ['archives']\n    pkg {\n        repo = \"maven\"\n        name = bintrayName\n        desc = libraryDescription\n        websiteUrl = siteUrl\n        vcsUrl = gitUrl\n        licenses = [\"Apache-2.0\"]\n        publish = true\n        publicDownloadNumbers = true\n        version {\n            desc = libraryDescription\n            gpg {\n                sign = true //Determines whether to GPG sign the files. The default is false\n                passphrase = properties.getProperty(\"bintray.gpg.password\")\n                //Optional. The passphrase for GPG signing'\n            }\n        }\n    }\n}"
  },
  {
    "path": "XRetrofit/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    apply from: 'versions.gradle'\n    repositories {\n        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }\n        jcenter()\n        google()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.6.0'\n        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'\n        classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'\n    }\n\n}\n\nallprojects {\n    repositories {\n        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }\n        maven { url 'https://jitpack.io' }\n        jcenter()\n        google()\n    }\n}\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}"
  },
  {
    "path": "XRetrofit/compiler/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "XRetrofit/compiler/build.gradle",
    "content": "apply plugin: 'java'\next {\n    bintrayName = 'compiler'\n    artifact = bintrayName\n    libraryName = 'xretrofit compiler'\n    libraryDescription = 'this is a  xretrofit-compiler'\n    libraryVersion = main_version\n}\ncompileJava {\n    sourceCompatibility = '1.8'\n    targetCompatibility = '1.8'\n}\n\ndependencies {\n    implementation 'com.google.auto.service:auto-service:1.0-rc6'\n    annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'\n\n    implementation 'com.squareup:javapoet:1.10.0'\n\n    implementation project(path: ':annotations')\n}\n\n//apply from: '../install.gradle'\n//apply from: '../bintray.gradle'\napply from: '../jitpack.gradle'\n"
  },
  {
    "path": "XRetrofit/compiler/src/main/java/com/xretrofit/compiler/ElementUtils.java",
    "content": "package com.xretrofit.compiler;\n\n/**\n * 这个类改版的话，HttpManager里面的getImplName 也需要改变\n */\n@SuppressWarnings(\"unchecked\")\npublic class ElementUtils {\n    public static String packageName = \"com.http\";\n\n    public static String getImplName(Class<?> clazz) {\n        return packageName + \".\" + clazz.getSimpleName() + \"$Impl\";\n    }\n}\n"
  },
  {
    "path": "XRetrofit/compiler/src/main/java/com/xretrofit/compiler/HttpServiceProcessor2.java",
    "content": "package com.xretrofit.compiler;\n\nimport com.google.auto.service.AutoService;\nimport com.xretrofit.compiler.create.CreateClassUtils;\nimport com.squareup.javapoet.JavaFile;\nimport com.yanxuwen.xretrofit_annotations.annotation.service.NetServiceClass;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.Set;\n\nimport javax.annotation.processing.AbstractProcessor;\nimport javax.annotation.processing.Filer;\nimport javax.annotation.processing.Messager;\nimport javax.annotation.processing.ProcessingEnvironment;\nimport javax.annotation.processing.Processor;\nimport javax.annotation.processing.RoundEnvironment;\nimport javax.lang.model.SourceVersion;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.ElementKind;\nimport javax.lang.model.element.PackageElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.util.Elements;\nimport javax.tools.Diagnostic;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/1/28 15:49\n * Description :\n */\n@AutoService(Processor.class)\npublic class HttpServiceProcessor2 extends AbstractProcessor {\n\n    private Messager mMessager;//可以用来打印一些信息\n    private Elements mElementUtils;\n    private Filer mFiler;//生成java源码\n    private Map<String, CreateClassUtils> mapClass = new HashMap<>();\n\n    @Override\n    public synchronized void init(ProcessingEnvironment processingEnv) {\n        super.init(processingEnv);\n        mMessager = processingEnv.getMessager();\n        mElementUtils = processingEnv.getElementUtils();\n        mFiler = processingEnv.getFiler();\n    }\n\n    /**\n     * 指定注解\n     */\n    @Override\n    public Set<String> getSupportedAnnotationTypes() {\n        HashSet<String> supportTypes = new LinkedHashSet<>();\n        supportTypes.add(NetServiceClass.class.getCanonicalName());\n        return supportTypes;\n    }\n\n    /**\n     * 用来指定你使用的Java版本\n     */\n    @Override\n    public SourceVersion getSupportedSourceVersion() {\n        return SourceVersion.latestSupported();\n    }\n\n\n\n    @Override\n    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {\n        mMessager.printMessage(Diagnostic.Kind.NOTE, \"processing...\");\n\n        //step1:得到所有的注解\n        Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(NetServiceClass.class);\n        if (elements == null || elements.isEmpty()) {\n            mMessager.printMessage(Diagnostic.Kind.NOTE, \"elements is null\");\n            return true;\n        }\n        for (Element element : elements) {\n            if (element.getKind() != ElementKind.INTERFACE) {\n                continue;\n            }\n            TypeElement classElement = (TypeElement) element;\n\n            CreateClassUtils creatorUtils = mapClass.get(getKey(classElement));\n            if (creatorUtils == null) {\n                creatorUtils = new CreateClassUtils(mElementUtils, classElement);\n            }\n            mapClass.put(getKey(classElement), creatorUtils);\n        }\n\n//        //step3:创建DataCallBack\n//        ClassCallBackUtils backUtils = new ClassCallBackUtils(mElementUtils);\n//        //创建文件\n//        try {\n//            JavaFile javaFile = JavaFile.builder(ElementUtils.packageName, backUtils.generateJavaCode()).build();\n//            javaFile.writeTo(processingEnv.getFiler());\n//        } catch (IOException e) {\n//            e.printStackTrace();\n//        }\n\n        //step3:遍历存储的类信息，创建java文件\n        for (String key : mapClass.keySet()) {\n            CreateClassUtils creatorUtils = mapClass.get(key);\n            try {\n                //创建文件\n                JavaFile javaFile = JavaFile.builder(ElementUtils.packageName, creatorUtils.generateJavaCode()).build();\n                javaFile.writeTo(processingEnv.getFiler());\n\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n\n        }\n        return true;\n    }\n\n    /**\n     * 根据类元素获取 key\n     * 包名 + 类名\n     */\n    public String getKey(TypeElement classElement) {\n        if (mElementUtils == null) {\n            return \"\";\n        }\n        PackageElement packageElement = mElementUtils.getPackageOf(classElement);\n        String packageName = packageElement.getQualifiedName().toString();\n        String className = classElement.getSimpleName().toString();\n        return packageName + \".\" + className;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/compiler/src/main/java/com/xretrofit/compiler/create/CreateClassUtils.java",
    "content": "package com.xretrofit.compiler.create;\n\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.FieldSpec;\nimport com.squareup.javapoet.MethodSpec;\nimport com.squareup.javapoet.ParameterSpec;\nimport com.squareup.javapoet.TypeName;\nimport com.squareup.javapoet.TypeSpec;\nimport com.yanxuwen.xretrofit_annotations.annotation.service.NetServiceClass;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\nimport javax.lang.model.element.AnnotationMirror;\nimport javax.lang.model.element.AnnotationValue;\nimport javax.lang.model.element.Element;\nimport javax.lang.model.element.ElementKind;\nimport javax.lang.model.element.ExecutableElement;\nimport javax.lang.model.element.Modifier;\nimport javax.lang.model.element.PackageElement;\nimport javax.lang.model.element.TypeElement;\nimport javax.lang.model.element.VariableElement;\nimport javax.lang.model.type.TypeKind;\nimport javax.lang.model.util.Elements;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/1/28 15:51\n * Description :\n */\npublic class CreateClassUtils {\n    private String mBindingClassName;\n    private String mClassName;\n    private String mPackageName;\n    private TypeElement mTypeElement;\n    private final String packagename_api = \"com.xretrofit.api\";\n    private final String packagename_bean = \"com.xretrofit.bean\";\n    private final String packagename_utils = \"com.xretrofit.utils\";\n    private final String packagename_method = \"com.xretrofit.method\";\n    private Elements elementUtils;\n\n    public CreateClassUtils(Elements elementUtils, TypeElement classElement) {\n        this.mTypeElement = classElement;\n        this.elementUtils = elementUtils;\n        PackageElement packageElement = elementUtils.getPackageOf(mTypeElement);\n        String packageName = packageElement.getQualifiedName().toString();\n        String className = mTypeElement.getSimpleName().toString();\n        this.mPackageName = packageName;\n        this.mClassName = className;\n        this.mBindingClassName = className + \"$Impl\";\n    }\n\n\n    /**\n     * 创建Java代码\n     *\n     * @return\n     */\n    public TypeSpec generateJavaCode() {\n\n        ClassName className = ClassName.get(mPackageName, mClassName);\n\n        NetServiceClass service = (NetServiceClass) mTypeElement.getAnnotation(NetServiceClass.class);\n        FieldSpec baseUrl = FieldSpec.builder(String.class, \"baseUrl\", Modifier.PRIVATE)\n                .initializer(service != null ? \"\\\"\" + service.value() + \"\\\"\" : \" null \").build();\n\n        TypeSpec bindingClass = TypeSpec.classBuilder(mBindingClassName)\n                .addModifiers(Modifier.PUBLIC)\n                .addSuperinterface(className)\n                .addField(baseUrl)//添加baseUrl变量\n                .addMethods(addMethod())//添加方法\n                .build();\n        return bindingClass;\n\n    }\n\n\n    /**\n     * 循环添加方法\n     */\n    private List<MethodSpec> addMethod() {\n        List<MethodSpec> list = new ArrayList<>();\n        //获取元素集合\n        List<? extends Element> listType = mTypeElement.getEnclosedElements();\n        if (listType == null || listType.isEmpty()) {\n            return list;\n        }\n        for (Element element : listType) {\n            if (element.getKind() != ElementKind.METHOD) {\n                continue;\n            }\n            ExecutableElement executableElement = (ExecutableElement) element;\n            String methodName = element.getSimpleName().toString();\n\n\n            MethodSpec.Builder methodSpec = MethodSpec.methodBuilder(methodName)\n                    .addModifiers(Modifier.PUBLIC)\n                    .returns(TypeName.get(executableElement.getReturnType()))\n                    .addParameters(addParameters(executableElement));\n            addStatement(methodSpec, executableElement);//判断是否含有Query的注解，则添加\n            list.add(methodSpec.build());\n        }\n        return list;\n    }\n\n    /**\n     * 循环添加参数\n     */\n    private List<ParameterSpec> addParameters(ExecutableElement executableElement) {\n        List<ParameterSpec> list = new ArrayList<>();\n\n        //获取元素集合\n        List<? extends VariableElement> listType = executableElement.getParameters();\n        if (listType == null || listType.isEmpty()) {\n            return list;\n        }\n\n        for (VariableElement variableElement : listType) {\n            String name = variableElement.getSimpleName().toString();\n            TypeName typeName = TypeName.get(variableElement.asType());\n            ParameterSpec parameterSpec = ParameterSpec.builder(typeName, name)\n//                .addAnnotation(nullable)//注解参数\n                    .build();\n            list.add(parameterSpec);\n        }\n        return list;\n    }\n\n\n    /**\n     * 添加代码\n     */\n    private void addStatement(MethodSpec.Builder builder, ExecutableElement executableElement) {\n\n        ClassName ServiceMethod = ClassName.get(packagename_method, \"ServiceMethod\");\n        ClassName MethodAnnotation = ClassName.get(packagename_method, \"MethodAnnotation\");\n        ClassName ParamAnnotation = ClassName.get(packagename_method, \"ParamAnnotation\");\n        ClassName HashMap = ClassName.get(\"java.util\", \"HashMap\");\n\n        ClassName List = ClassName.get(\"java.util\", \"List\");\n        ClassName ArrayList = ClassName.get(\"java.util\", \"ArrayList\");\n        ClassName Object = ClassName.get(\"java.lang\", \"Object\");\n        builder.addStatement(\"$T<Class, $T> mapMa= new $T<>()\", HashMap, MethodAnnotation, HashMap);\n        //获取方法注解\n        int numM = 0;\n        for (AnnotationMirror annotationMirror : executableElement.getAnnotationMirrors()) {\n            Class annotationClass = null;\n            try {\n                annotationClass = Class.forName(annotationMirror.getAnnotationType().toString());\n            } catch (ClassNotFoundException e) {\n                e.printStackTrace();\n            }\n            boolean isValue = false;\n            builder.addStatement(\"$T<$T> list_ma_$N = new $T<>()\", List, Object, String.valueOf(numM), ArrayList);\n            for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {\n                isValue = true;\n                //如果注解里面是数组，如@Headers\n                if (entry.getValue().getValue() instanceof List) {\n                    for (int i = 0; i < ((List) entry.getValue().getValue()).size(); i++) {\n                        builder.addStatement(\"list_ma_$N.add($N)\", String.valueOf(numM), String.valueOf(((List) entry.getValue().getValue()).get(i)));\n                    }\n                } else {\n                    builder.addStatement(\"list_ma_$N.add($N)\", String.valueOf(numM), String.valueOf(entry.getValue()));\n                }\n            }\n            builder.addStatement(\"mapMa.put($N.class,new $T($N.class,$N))\", annotationClass.getName(), MethodAnnotation, annotationClass.getName(), isValue ? \"list_ma_\" + numM : \"null\");\n            numM++;\n        }\n        builder.addCode(\"\\n\");\n\n        //参数添加\n        builder.addStatement(\"List<$T> listPA = new $N<>()\", ParamAnnotation, String.valueOf(ArrayList));\n        int numP = 0;\n        //获取参数注解\n        List<? extends VariableElement> list = executableElement.getParameters();\n        if (list != null) {\n            for (VariableElement variableElement : list) {\n                for (AnnotationMirror annotationMirror : variableElement.getAnnotationMirrors()) {\n                    Class annotationClass = null;\n                    try {\n                        annotationClass = Class.forName(annotationMirror.getAnnotationType().toString());\n                    } catch (ClassNotFoundException e) {\n                        e.printStackTrace();\n                    }\n                    boolean isValue = false;\n                    builder.addStatement(\"List<$T> list_pa_$N = new $N<>()\", Object, String.valueOf(numP), String.valueOf(ArrayList));\n                    for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {\n                        isValue = true;\n                        builder.addStatement(\"list_pa_$N.add($N)\", String.valueOf(numP), String.valueOf(entry.getValue()));\n                    }\n                    builder.addStatement(\"listPA.add(new $T($N.class,$N,$N))\", ParamAnnotation, annotationClass.getName(),\n                            isValue ? \"list_pa_\" + numP : \"null\",\n                            variableElement.getSimpleName());\n                }\n                numP++;\n            }\n        }\n\n        builder.addStatement(\"$T serviceMethod = new $T()\", ServiceMethod, ServiceMethod);\n\n        if (executableElement.getReturnType().getKind() != TypeKind.VOID) {\n            ClassName TypeToken = ClassName.get(\"com.google.common.reflect\", \"TypeToken\");\n            builder.addStatement(\"return serviceMethod.request(mapMa,listPA,new $T<$N>(){}.getType())\", TypeToken, String.valueOf(executableElement.getReturnType()));\n        } else {\n            builder.addStatement(\"serviceMethod.request(mapMa,listPA,Void.class)\");\n        }\n    }\n}\n"
  },
  {
    "path": "XRetrofit/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Tue Apr 16 17:53:26 CST 2019\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-5.6.4-all.zip\n"
  },
  {
    "path": "XRetrofit/gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\norg.gradle.daemon=true\n\nbintrayRepo=maven\nmain_version=0.0.8\npublishedGroupId=com.github.yanxuwen\nsiteUrl=https://github.com/yanxuwen/xretrofit\ngitUrl=https://github.com/yanxuwen/xretrofit.git\ndeveloperId=yxe\ndeveloperName=yanxuwen\ndeveloperEmail=420255048@qq.com\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n\n\norg.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8\n\n#org.gradle.jvmargs= -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005,\n#Dorg.gradle.debug=true\n\n\n\n\n\n"
  },
  {
    "path": "XRetrofit/gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "XRetrofit/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windows variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "XRetrofit/install.gradle",
    "content": "// backup of [https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle]\n\napply plugin: 'com.github.dcendents.android-maven'\n\ngroup = publishedGroupId                               // Maven Group ID for the artifact\n\ninstall {\n    repositories.mavenInstaller {\n        // This generates POM.xml with proper parameters\n        pom {\n            project {\n                packaging 'aar'\n                groupId publishedGroupId\n                artifactId artifact\n\n                // Add your description here\n                name libraryName\n                description libraryDescription\n                url siteUrl\n\n                // Set your license\n                licenses {\n                    license {\n                        name 'The Apache Software License, Version 2.0'\n                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'\n                    }\n                }\n                developers {\n                    developer {\n                        id developerId\n                        name developerName\n                        email developerEmail\n                    }\n                }\n                scm {\n                    connection gitUrl\n                    developerConnection gitUrl\n                    url siteUrl\n\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "XRetrofit/jitpack.gradle",
    "content": "apply plugin: 'com.github.dcendents.android-maven'\n\ngroup = 'com.github.yanxuwen'\n"
  },
  {
    "path": "XRetrofit/settings.gradle",
    "content": "include ':annotations'\ninclude ':app', ':xretrofit', ':compiler'\n"
  },
  {
    "path": "XRetrofit/versions.gradle",
    "content": "/**\n * Shared file between builds so that they can all use the same dependencies and\n * maven repositories.\n **/\next.deps = [:]\next.support_version = '23.1.1'\next.kotlin_version = '1.3.0'\next.anko_version = '0.8.2'\next.butterknife_version = '8.8.1'\n\ndef build_versions = [:]\nbuild_versions.min_sdk = 16\nbuild_versions.target_sdk = 28\nbuild_versions.build_tools = \"28.0.3\"\next.build_versions = build_versions\n\ndef versions = [:]\nversions.support = \"28.0.0\"\n\ndef support = [:]\nsupport.app_compat = \"androidx.appcompat:appcompat:1.0.0\"\nsupport.design = \"com.google.android.material:material:1.0.0\"\nsupport.recyclerview = \"androidx.recyclerview:recyclerview:1.0.0\"\nsupport.constraintlayout = 'androidx.constraintlayout:constraintlayout:1.1.3'\next.support = support\n\ndef other = [:]\nother.okhttp = 'com.squareup.okhttp3:okhttp:4.1.0'\nother.fastjson = 'com.alibaba:fastjson:1.2.57'\nother.rxpermissions = 'com.github.tbruyelle:rxpermissions:0.10.2'\nother.rxandroid = 'io.reactivex.rxjava2:rxandroid:2.1.1'\nother.rxjava = 'io.reactivex.rxjava2:rxjava:2.2.19'\nother.autoDispose = 'com.uber.autodispose:autodispose-android-archcomponents:1.0.0-RC2'\nother.guava = 'com.google.guava:guava:27.0.1-jre'\n\next.other = other\n\n\n"
  },
  {
    "path": "XRetrofit/xretrofit/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "XRetrofit/xretrofit/build.gradle",
    "content": "apply plugin: 'com.android.library'\next {\n    bintrayName = 'xretrofit'\n    artifact = bintrayName\n    libraryName = 'xretrofit api'\n    libraryDescription = 'xretrofit'\n    libraryVersion = main_version\n}\n\nandroid {\n    compileSdkVersion 28\n    buildToolsVersion \"28.0.3\"\n    defaultConfig {\n        minSdkVersion 15\n        targetSdkVersion 28\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n        javaCompileOptions {\n            annotationProcessorOptions {\n                includeCompileClasspath true\n            }\n        }\n        buildTypes {\n            release {\n                minifyEnabled false\n                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n            }\n        }\n    }\n}\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    api other.okhttp\n    api other.guava\n    api project(path: ':annotations')\n}\n\n//apply from: '../install.gradle'\n//apply from: '../bintray.gradle'\napply from: '../jitpack.gradle'\n"
  },
  {
    "path": "XRetrofit/xretrofit/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.xretrofit\" >\n\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n</manifest>\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/CallAdapter/CallAdapter.java",
    "content": "package com.xretrofit.CallAdapter;\n\nimport com.xretrofit.call.Call;\nimport com.xretrofit.utils.Utils;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 16:02\n * Description :\n * 适配器\n *\n * R  为  封装后的类型。\n * T  为接口返回类型\n */\npublic interface CallAdapter<R, T>{\n    R adapt(Call<T> call);\n\n    /**\n     * 接口数据 类型\n     */\n    Type responseType();\n\n    abstract class Factory {\n        /**\n         * 封装转换器，如封装Observable\n         */\n        public abstract @Nullable CallAdapter<?, ?> get(Type returnType);\n\n        protected static Class<?> getRawType(Type type) {\n            return Utils.getRawType(type);\n        }\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/CallAdapter/MCallAdapter.java",
    "content": "package com.xretrofit.CallAdapter;\n\nimport com.xretrofit.call.Call;\n\nimport java.lang.reflect.Type;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 17:49\n * Description :\n * 返回类型为Call<> 的适配器\n */\npublic class MCallAdapter<T> implements CallAdapter<Call,T> {\n\n    private Type responseType;\n\n    protected MCallAdapter(Type responseType){\n        this.responseType = responseType;\n    }\n\n\n    @Override\n    public Type responseType() {\n        return responseType;\n    }\n\n\n    @Override\n    public Call adapt(Call<T> call) {\n        return call;\n    }\n\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/CallAdapter/ObjectCallAdapter.java",
    "content": "package com.xretrofit.CallAdapter;\n\nimport com.xretrofit.call.Call;\n\nimport java.lang.reflect.Type;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 17:49\n * Description :\n * 同步\n * Object 适配器,\n */\npublic class ObjectCallAdapter<T> implements CallAdapter<Object,T> {\n\n    private Type responseType;\n\n    protected ObjectCallAdapter(Type responseType){\n        this.responseType = responseType;\n    }\n\n    @Override\n    public Type responseType() {\n        return responseType;\n    }\n\n    @Override\n    public Object adapt(Call call) {\n        try {\n            return call.execute().body();\n        } catch (Exception e) {\n            return null;\n        }\n    }\n\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/CallAdapter/ObjectCallAdapterFactory.java",
    "content": "package com.xretrofit.CallAdapter;\n\nimport com.xretrofit.call.Call;\nimport com.xretrofit.call.ProgressCall;\nimport com.xretrofit.utils.Utils;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 17:47\n * Description :\n * 适配器Factory\n */\npublic class ObjectCallAdapterFactory extends CallAdapter.Factory {\n\n    public static ObjectCallAdapterFactory create() {\n        return new ObjectCallAdapterFactory();\n    }\n\n\n    @Nullable\n    @Override\n    public CallAdapter<?, ?> get(Type returnType) {\n        Class<?> rawType = getRawType(returnType);\n        final Type responseType = Utils.getCallResponseType(returnType);\n        if (rawType == ProgressCall.class) {\n            return new ProgressCallAdapter(responseType);\n        } else if (rawType == Call.class) {\n            return new MCallAdapter<>(responseType);\n        }\n        return new ObjectCallAdapter(responseType);\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/CallAdapter/ProgressCallAdapter.java",
    "content": "package com.xretrofit.CallAdapter;\n\nimport com.xretrofit.call.Call;\nimport com.xretrofit.call.ProgressCall;\n\nimport java.lang.reflect.Type;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 17:49\n * Description :\n * 返回类型为{@link ProgressCall<> 的适配器  带进度的\n */\npublic class ProgressCallAdapter<T> implements CallAdapter<ProgressCall,T> {\n\n    private Type responseType;\n\n    protected ProgressCallAdapter(Type responseType){\n        this.responseType = responseType;\n    }\n\n    @Override\n    public ProgressCall adapt(Call<T> call) {\n        if (call != null){\n            return (ProgressCall) call;\n        }\n        return null;\n    }\n\n    @Override\n    public Type responseType() {\n        return responseType;\n    }\n\n\n\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/HttpException.java",
    "content": "/*\n * Copyright (C) 2016 Square, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.xretrofit;\n\n\nimport static com.xretrofit.utils.Utils.checkNotNull;\n\n/** Exception for an unexpected, non-2xx HTTP response. */\npublic class HttpException extends RuntimeException {\n    private static String getMessage(Response<?> response) {\n        checkNotNull(response, \"response == null\");\n        return \"HTTP \" + response.code() + \" \" + response.message();\n    }\n\n    private final int code;\n    private final String message;\n    private final transient Response<?> response;\n\n    public HttpException(Response<?> response) {\n        super(getMessage(response));\n        this.code = response.code();\n        this.message = response.message();\n        this.response = response;\n    }\n\n    /** HTTP status code. */\n    public int code() {\n        return code;\n    }\n\n    /** HTTP status message. */\n    public String message() {\n        return message;\n    }\n\n    /**\n     * The full HTTP response. This may be null if the exception was serialized.\n     */\n    public Response<?> response() {\n        return response;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/HttpManager.java",
    "content": "package com.xretrofit;\n\nimport com.xretrofit.CallAdapter.CallAdapter;\nimport com.xretrofit.CallAdapter.ObjectCallAdapterFactory;\nimport com.xretrofit.converter.Converter;\nimport com.xretrofit.converter.DownloadConverterFactories;\nimport com.xretrofit.converter.StringConverterFactories;\nimport com.xretrofit.okhttp.SslUtils;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport okhttp3.Call;\nimport okhttp3.Interceptor;\nimport okhttp3.OkHttpClient;\n\nimport static com.xretrofit.utils.Utils.checkNotNull;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 14:00\n * Description :\n * 配置\n */\npublic final class HttpManager {\n    private static volatile HttpManager instance;\n    public List<Converter.Factory> converterFactories = new ArrayList<>();\n    public List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();\n    public String baseUrl;\n    okhttp3.Call.Factory callFactory;\n\n    public static HttpManager getInstance() {\n        if (instance == null) {\n            synchronized (HttpManager.class) {\n                if (instance == null) {\n                    instance = new HttpManager();\n                }\n            }\n        }\n\n        return instance;\n    }\n\n    HttpManager() {\n\n    }\n\n    public okhttp3.Call.Factory callFactory() {\n        if (callFactory == null) {\n            return callFactory = getOkHttpClient();\n        }\n        return callFactory;\n\n    }\n\n    /**\n     * 文件下载用的，不能跟其他共享，避免其他错误。\n     */\n    public OkHttpClient getOkHttpDownloadClient(Interceptor interceptor) {\n        OkHttpClient client = new OkHttpClient\n                .Builder()\n                .connectTimeout(15, TimeUnit.SECONDS)//连接超时时间\n                .readTimeout(15, TimeUnit.SECONDS)//读取超时时间\n                .writeTimeout(15, TimeUnit.SECONDS)//写入超时时间\n                .retryOnConnectionFailure(false)//连接不上是否重连,false不重连\n                .sslSocketFactory(SslUtils.getSslSocketFactory().sSLSocketFactory, SslUtils.getSslSocketFactory().trustManager)\n                .addNetworkInterceptor(interceptor)\n                .build();\n        return client;\n    }\n\n    /**\n     * 默认OkHttpClient\n     */\n    public OkHttpClient getOkHttpClient() {\n        OkHttpClient client = new OkHttpClient\n                .Builder()\n                .connectTimeout(15, TimeUnit.SECONDS)//连接超时时间\n                .readTimeout(15, TimeUnit.SECONDS)//读取超时时间\n                .writeTimeout(15, TimeUnit.SECONDS)//写入超时时间\n                .retryOnConnectionFailure(false)//连接不上是否重连,false不重连\n                .sslSocketFactory(SslUtils.getSslSocketFactory().sSLSocketFactory, SslUtils.getSslSocketFactory().trustManager)\n                .build();\n        return client;\n    }\n\n    void setData(@Nullable Call.Factory callFactory, String baseUrl,\n                 List<Converter.Factory> converterFactories,\n                 List<CallAdapter.Factory> callAdapterFactories) {\n\n        //默认添加一个字符串转换器、下载转换器\n        converterFactories.add(0, DownloadConverterFactories.create());\n        converterFactories.add(StringConverterFactories.create());\n\n        //添加适配器\n        callAdapterFactories.add(ObjectCallAdapterFactory.create());\n\n        this.baseUrl = baseUrl;\n        this.converterFactories = converterFactories;\n        this.callAdapterFactories = callAdapterFactories;\n        this.callFactory = callFactory;\n\n    }\n\n    public static Builder Builder() {\n        return new Builder();\n    }\n\n    public static final class Builder {\n        private List<Converter.Factory> converterFactories = new ArrayList<>();\n        private List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();\n        private String baseUrl;\n        private @Nullable\n        okhttp3.Call.Factory callFactory;\n\n        public Builder() {\n        }\n\n        public Builder baseUrl(String baseUrl) {\n            this.baseUrl = checkNotNull(baseUrl, \"baseUrl == null\");\n            return this;\n        }\n\n        public Builder addConverterFactory(Converter.Factory factory) {\n            converterFactories.add(checkNotNull(factory, \"factory == null\"));\n            return this;\n        }\n\n        public Builder addCallAdapterFactory(CallAdapter.Factory factory) {\n            callAdapterFactories.add(checkNotNull(factory, \"factory == null\"));\n            return this;\n        }\n\n        public Builder client(OkHttpClient client) {\n            return callFactory(checkNotNull(client, \"client == null\"));\n        }\n\n        public Builder callFactory(okhttp3.Call.Factory factory) {\n            this.callFactory = checkNotNull(factory, \"factory == null\");\n            return this;\n        }\n\n        public void build() {\n            HttpManager.getInstance().setData(callFactory, baseUrl, converterFactories, callAdapterFactories);\n        }\n    }\n\n\n    public static String packageName = \"com.http\";\n\n    /**\n     * 照抄ElementUtils\n     */\n    public static String getImplName(Class<?> clazz) {\n        return packageName + \".\" + clazz.getSimpleName() + \"$Impl\";\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/Interceptor/DownloadResponseBody.java",
    "content": "package com.xretrofit.Interceptor;\n\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.text.DecimalFormat;\n\nimport okhttp3.MediaType;\nimport okhttp3.Response;\nimport okhttp3.ResponseBody;\nimport okio.Buffer;\nimport okio.BufferedSource;\nimport okio.ForwardingSource;\nimport okio.Okio;\n\n/**\n * 下载\n */\npublic class DownloadResponseBody extends ResponseBody {\n\n    private Response originalResponse;\n    private long startsPoint = 0;\n    private long maxProgress = 0;\n    private File file;\n    DecimalFormat df = new DecimalFormat(\"#.00\");\n\n    private ProgressListener progressListener;\n\n    public void setProgressListener(ProgressListener progressListener) {\n        this.progressListener = progressListener;\n    }\n\n    public DownloadResponseBody(Response originalResponse, long startsPoint, File file) {\n        this.originalResponse = originalResponse;\n        this.startsPoint = startsPoint;\n        this.file = file;\n    }\n\n    @Override\n    public MediaType contentType() {\n        return originalResponse.body().contentType();\n    }\n\n    @Override\n    public long contentLength() {\n        return originalResponse.body().contentLength();\n    }\n\n    public void setMaxProgress(long maxProgress) {\n        this.maxProgress = maxProgress;\n    }\n\n    @Override\n    public BufferedSource source() {\n        return Okio.buffer(new ForwardingSource(originalResponse.body().source()) {\n            private long bytesReaded = 0;\n\n            @Override\n            public long read(Buffer sink, long byteCount) throws IOException {\n                long bytesRead = super.read(sink, byteCount);\n                bytesReaded += bytesRead == -1 ? 0 : bytesRead;\n                if (progressListener != null) {\n                    progressListener.setProgress(Float.valueOf(df.format((Float.valueOf(bytesReaded+startsPoint) / maxProgress) * 100)));\n                }\n                return bytesRead;\n            }\n        });\n    }\n\n    public File getFile() {\n        return file;\n    }\n\n    public void setFile(File file) {\n        this.file = file;\n    }\n\n    public long getStartsPoint() {\n        return startsPoint;\n    }\n}"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/Interceptor/ProgressListener.java",
    "content": "package com.xretrofit.Interceptor;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/8 9:45\n * Description :\n */\npublic class ProgressListener {\n    public void setProgress(float progress) {\n        if (listener != null) {\n            listener.progress(progress);\n        }\n    }\n\n    public interface Listener {\n        public void progress(float progress);\n    }\n\n    private Listener listener;\n\n    public void setProgressListener(Listener listener) {\n        this.listener = listener;\n    }\n\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/Interceptor/UploadRequestBodyBody.java",
    "content": "package com.xretrofit.Interceptor;\n\nimport java.io.IOException;\nimport java.text.DecimalFormat;\n\nimport okhttp3.MediaType;\nimport okhttp3.RequestBody;\nimport okio.Buffer;\nimport okio.BufferedSink;\nimport okio.ForwardingSink;\nimport okio.Okio;\nimport okio.Sink;\n\n/**\n * 上传\n */\npublic class UploadRequestBodyBody extends RequestBody {\n    private RequestBody mRequestBody;\n    private long mContentLength;\n    final DecimalFormat df = new DecimalFormat(\"#.00\");\n\n    private ProgressListener progressListener;\n\n    public void setProgressListener(ProgressListener progressListener) {\n        this.progressListener = progressListener;\n    }\n\n    public UploadRequestBodyBody(RequestBody requestBody) {\n        mRequestBody = requestBody;\n    }\n\n    //文件的总长度\n    @Override\n    public long contentLength() {\n        try {\n            if (mContentLength == 0)\n                mContentLength = mRequestBody.contentLength();\n            return mContentLength;\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        return -1;\n    }\n\n    @Override\n    public MediaType contentType() {\n        return mRequestBody.contentType();\n    }\n\n    @Override\n    public void writeTo(BufferedSink sink) throws IOException {\n        ByteSink byteSink = new ByteSink(sink);\n        BufferedSink mBufferedSink = Okio.buffer(byteSink);\n        mRequestBody.writeTo(mBufferedSink);\n        mBufferedSink.flush();\n    }\n\n\n    private final class ByteSink extends ForwardingSink {\n        //已经上传的长度\n        private long mByteLength = 0L;\n\n        ByteSink(Sink delegate) {\n            super(delegate);\n        }\n\n        @Override\n        public void write(Buffer source, long byteCount) throws IOException {\n            super.write(source, byteCount);\n            mByteLength += byteCount;\n            if (progressListener != null){\n                progressListener.setProgress(Float.valueOf(df.format((Float.valueOf(mByteLength) /  contentLength()) * 100)));\n            }\n        }\n    }\n}"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/Response.java",
    "content": "package com.xretrofit;\n\n\nimport org.jetbrains.annotations.Nullable;\n\nimport okhttp3.Headers;\nimport okhttp3.ResponseBody;\n\nimport static com.xretrofit.utils.Utils.checkNotNull;\n\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 11:11\n * Description :\n * 自己定义的Response，里面嵌套 okhttp的Response，可供后续替换\n */\npublic final class Response<T> {\n    private okhttp3.Response rawResponse;\n    private @Nullable\n    T body;\n    private @Nullable\n    ResponseBody errorBody;\n\n    private Response(okhttp3.Response rawResponse, @Nullable T body,\n                     @Nullable ResponseBody errorBody) {\n        this.rawResponse = rawResponse;\n        this.body = body;\n        this.errorBody = errorBody;\n    }\n\n\n    public static <T> Response<T> success(@Nullable T body, okhttp3.Response rawResponse) {\n        checkNotNull(rawResponse, \"rawResponse == null\");\n        if (!rawResponse.isSuccessful()) {\n            throw new IllegalArgumentException(\"rawResponse must be successful response\");\n        }\n        return new Response<>(rawResponse, body, null);\n    }\n\n\n    /**\n     * Create an error response from {@code rawResponse} with {@code body} as the error body.\n     */\n    public static <T> Response<T> error(ResponseBody body, okhttp3.Response rawResponse) {\n        checkNotNull(body, \"body == null\");\n        checkNotNull(rawResponse, \"rawResponse == null\");\n        if (rawResponse.isSuccessful()) {\n            throw new IllegalArgumentException(\"rawResponse should not be successful response\");\n        }\n        return new Response<>(rawResponse, null, body);\n    }\n\n    /** The raw response from the HTTP client. */\n    public okhttp3.Response raw() {\n        return rawResponse;\n    }\n\n    /** HTTP status code. */\n    public int code() {\n        return rawResponse.code();\n    }\n\n    /** HTTP status message or null if unknown. */\n    public String message() {\n        return rawResponse.message();\n    }\n\n    /** HTTP headers. */\n    public Headers headers() {\n        return rawResponse.headers();\n    }\n\n    /** Returns true if {@link #code()} is in the range [200..300). */\n    public boolean isSuccessful() {\n        return rawResponse.isSuccessful();\n    }\n\n    /** The deserialized response body of a {@linkplain #isSuccessful() successful} response. */\n    public @Nullable T body() {\n        return body;\n    }\n\n    /** The raw response body of an {@linkplain #isSuccessful() unsuccessful} response. */\n    public @Nullable ResponseBody errorBody() {\n        return errorBody;\n    }\n\n    @Override public String toString() {\n        return rawResponse.toString();\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/bean/RequestParams.java",
    "content": "package com.xretrofit.bean;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * 自动生成用的请求参数\n */\npublic class RequestParams {\n    private String url;\n    private boolean isForm;//是否是表单提交\n    private Map<String, Object> params;\n    private Map<String, String> headers;\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n\n    public Map<String, Object> getParams() {\n        if (params == null){\n            return new HashMap<>();\n        }\n        return params;\n    }\n\n    public void setParams(Map<String, Object> params) {\n        this.params = params;\n    }\n\n\n    public Map<String, String> getHeaders() {\n        if (headers == null){\n            return new HashMap<>();\n        }\n        return headers;\n    }\n\n\n    public void setHeaders(Map<String, String> headers) {\n        this.headers = headers;\n    }\n\n    public void addParams(String key, String value) {\n        getParams().put(key, value);\n    }\n\n    public void addHeader(String key, String value) {\n        getHeaders().put(key, value);\n    }\n\n    public boolean isForm() {\n        return isForm;\n    }\n\n    public void setForm(boolean form) {\n        isForm = form;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/call/Call.java",
    "content": "package com.xretrofit.call;\n\nimport com.xretrofit.Response;\nimport com.xretrofit.callback.CallBack;\nimport com.xretrofit.converter.Converter;\n\nimport okhttp3.ResponseBody;\n\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 11:02\n * Description :\n *\n */\npublic interface Call<T> {\n\n    /**\n     * 初始化接口返回类型\n     */\n    void init(Converter<ResponseBody, T> responseConverter);\n\n    /**\n     * 执行请求，异步\n     */\n    void enqueue(CallBack<T> callback);\n\n\n    /**\n     * 执行请求同步\n     */\n    Response<T> execute() throws Exception;\n\n\n    void cancel();\n\n    boolean isCanceled();\n\n    Call<T> clone();\n\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/call/OkHttpCall.java",
    "content": "package com.xretrofit.call;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\nimport com.xretrofit.Response;\nimport com.xretrofit.callback.CallBack;\nimport com.xretrofit.converter.Converter;\nimport com.xretrofit.utils.Utils;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.io.IOException;\n\nimport okhttp3.Callback;\nimport okhttp3.MediaType;\nimport okhttp3.ResponseBody;\nimport okio.BufferedSource;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 11:17\n * Description :\n */\npublic class OkHttpCall<T> implements Call<T> {\n    protected Converter<ResponseBody, T> responseConverter;//结果转换器\n    protected okhttp3.Call call;\n    private volatile boolean canceled;\n    final Handler mHandler = new Handler(Looper.getMainLooper());\n\n    public OkHttpCall(okhttp3.Call call) {\n        this.call = call;\n    }\n\n    @Override\n    public void init(Converter<ResponseBody, T> responseConverter) {\n        this.responseConverter = responseConverter;\n    }\n\n    /**\n     * 执行请求，异步\n     */\n    @Override\n    public void enqueue(final CallBack<T> callback) {\n        call.enqueue(new Callback() {\n            @Override\n            public void onFailure(@NotNull okhttp3.Call call, @NotNull final IOException e) {\n                if (callback == null) {\n                    return;\n                }\n                mHandler.post(new Runnable() {\n                    @Override\n                    public void run() {\n                        callback.onFail(OkHttpCall.this, e);\n                    }\n                });\n            }\n\n            @Override\n            public void onResponse(@NotNull okhttp3.Call call, @NotNull final okhttp3.Response response) throws IOException {\n                if (callback == null) {\n                    return;\n                }\n                final Response<T> tResponse;\n                try {\n                    if (canceled) {\n                        return;\n                    }\n                    tResponse = parseResponse(response);\n                } catch (final Exception e) {\n                    mHandler.post(new Runnable() {\n                        @Override\n                        public void run() {\n                            callback.onFail(OkHttpCall.this, e);\n                        }\n                    });\n                    return;\n                }\n                mHandler.post(new Runnable() {\n                    @Override\n                    public void run() {\n                        callback.onSuccess(OkHttpCall.this, tResponse);\n                    }\n                });\n            }\n        });\n        mHandler.post(new Runnable() {\n            @Override\n            public void run() {\n                callback.onStart(OkHttpCall.this);\n            }\n        });\n    }\n\n    /**\n     * 执行请求，同步\n     */\n    @Override\n    public Response<T> execute() throws Exception {\n        okhttp3.Response rawResponse = call.execute();\n        if (canceled) {\n            return null;\n        }\n        return parseResponse(rawResponse);\n    }\n\n    @Override\n    public void cancel() {\n        canceled = true;\n        if (call != null) {\n            call.cancel();\n        }\n    }\n\n    @Override public boolean isCanceled() {\n        if (canceled) {\n            return true;\n        }\n        synchronized (this) {\n            return call != null && call.isCanceled();\n        }\n    }\n\n    @Override\n    public Call<T> clone() {\n        OkHttpCall okHttpCall = new OkHttpCall(call);\n        okHttpCall.init(responseConverter);\n        return okHttpCall;\n    }\n\n    /**\n     * 结果请求，数据处理\n     */\n    protected Response<T> parseResponse(okhttp3.Response rawResponse) throws Exception {\n        ResponseBody rawBody = rawResponse.body();\n        // Remove the body's source (the only stateful object) so we can pass the response along.\n        //删除主体的源（唯一有状态的对象），这样我们就可以传递响应。\n        //抄袭 retrofit的\n        rawResponse = rawResponse.newBuilder()\n                .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))\n                .build();\n\n        //不是200的则错误信息\n        int code = rawResponse.code();\n        if (code < 200 || code >= 300) {\n            try {\n                // Buffer the entire body to avoid future I/O.\n                // 缓冲整个主体以避免将来的I/O。\n                ResponseBody bufferedBody = Utils.buffer(rawBody);\n                return Response.error(bufferedBody, rawResponse);\n            } finally {\n                rawBody.close();\n            }\n        }\n        //HTTP 204(no content)表示响应执行成功，但没有数据返回，浏览器不用刷新，不用导向新页面。\n        //HTTP 205(reset content) 表示响应执行成功，重置页面（Form表单），方便用户下次输入。\n        if (code == 204 || code == 205) {\n            rawBody.close();\n            return Response.success(null, rawResponse);\n        }\n        //使用转换器转换\n        T body = null;\n        if (responseConverter != null) {\n            body = responseConverter.convert(rawBody);\n        }\n        rawBody.close();\n        return Response.success(body, rawResponse);\n    }\n\n\n    static final class NoContentResponseBody extends ResponseBody {\n        private final MediaType contentType;\n        private final long contentLength;\n\n        NoContentResponseBody(MediaType contentType, long contentLength) {\n            this.contentType = contentType;\n            this.contentLength = contentLength;\n        }\n\n        @Override\n        public MediaType contentType() {\n            return contentType;\n        }\n\n        @Override\n        public long contentLength() {\n            return contentLength;\n        }\n\n        @Override\n        public BufferedSource source() {\n            throw new IllegalStateException(\"Cannot read raw response body of a converted body.\");\n        }\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/call/ProgressCall.java",
    "content": "package com.xretrofit.call;\n\nimport com.xretrofit.Interceptor.ProgressListener;\nimport com.xretrofit.callback.CallBack;\nimport com.xretrofit.callback.ProgressCallBack;\n\nimport java.text.DecimalFormat;\n\nimport okhttp3.Call;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/7 17:05\n * Description :\n * 下载\n */\npublic class ProgressCall<T> extends OkHttpCall<T> {\n\n    final DecimalFormat df = new DecimalFormat(\"#.00\");\n\n    private ProgressListener[] listeners;\n\n    /**\n     * @param listeners 用于监听上传跟下载的时候用的\n     */\n    public ProgressCall(Call call, ProgressListener... listeners) {\n        super(call);\n        this.listeners = listeners;\n    }\n\n    @Override\n    public void enqueue(final CallBack<T> callback) {\n        super.enqueue(callback);\n        if (callback instanceof ProgressCallBack) {\n            final ProgressCallBack progressCallBack = (ProgressCallBack) callback;\n            if (listeners != null) {\n                final float[] totalProgress = new float[listeners.length];\n                for (int i = 0; i < listeners.length; i++) {\n                    final int finalI = i;\n                    listeners[i].setProgressListener(new ProgressListener.Listener() {\n                        @Override\n                        public void progress(float progress) {\n                            totalProgress[finalI] = progress;\n                            double total = 0;\n                            for (double mProcess : totalProgress) {\n                                total += mProcess;\n                            }\n                            progressCallBack.onProgress(Float.valueOf(df.format(total / listeners.length)));\n                        }\n                    });\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/callback/CallBack.java",
    "content": "package com.xretrofit.callback;\n\nimport com.xretrofit.call.Call;\nimport com.xretrofit.Response;\n\n\npublic interface CallBack<T> {\n\n    void onStart(Call<T> call);\n\n    void onSuccess(Call<T> call, Response<T> response);\n\n    void onFail(Call<T> call, final Throwable e);\n}"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/callback/ProgressCallBack.java",
    "content": "package com.xretrofit.callback;\n\npublic abstract class ProgressCallBack<T> implements CallBack<T> {\n\n    /**\n     * 进度\n     */\n    public abstract void onProgress(float progress);\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/converter/Converter.java",
    "content": "package com.xretrofit.converter;\n\nimport com.xretrofit.utils.Utils;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Body;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.FilePath;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Header;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Param;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Path;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Query;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\nimport okhttp3.RequestBody;\nimport okhttp3.ResponseBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 14:07\n * Description :\n * 如果是请求\n */\npublic interface Converter<F, T> {\n    T convert(F value) throws Exception;\n\n    abstract class Factory {\n\n        /**\n         * 请求转换器,目前只支持{@link Body @Body} 注解\n         * @param request get post\n         * @param requestParamType  请求的参数类型\n         * @return\n         */\n        public @Nullable Converter<?, RequestBody> requestBodyConverter(Type request, Type requestParamType) {\n            return null;\n        }\n\n        /**\n         * 请求转换器 ,支持\n         * {@link Header @Header}\n         * {@link Query @Query}\n         * {@link Path @Path}\n         * {@link FilePath @FilePath}\n         * {@link Param @FilePath}\n         * @param request  get post\n         * @param requestParamType 请求的参数类型\n         * @return\n         */\n        public @Nullable Converter<?, String> stringConverter(Type request,Type requestParamType) {\n            return null;\n        }\n\n        /**\n         * 结果转换器\n         * @param request    get post\n         * @param responseType 结果返回的参数类型\n         * @return\n         */\n        public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type request,Type responseType) {\n            return null;\n        }\n\n        protected static Class<?> getRawType(Type type) {\n            return Utils.getRawType(type);\n        }\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/converter/DownloadConverterFactories.java",
    "content": "package com.xretrofit.converter;\n\nimport com.yanxuwen.xretrofit_annotations.annotation.method.DOWNLOAD;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\nimport okhttp3.ResponseBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/7 16:32\n * 接口数据转换器\n * 下载转换器\n */\npublic class DownloadConverterFactories extends Converter.Factory {\n\n    public static DownloadConverterFactories create() {\n        return new DownloadConverterFactories();\n    }\n\n\n    @Nullable\n    @Override\n    public Converter<ResponseBody, ?> responseBodyConverter(Type request, Type responseType) {\n        if (request == DOWNLOAD.class) {\n            return new DownloadResponseConverter();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/converter/DownloadResponseConverter.java",
    "content": "package com.xretrofit.converter;\n\nimport com.xretrofit.Interceptor.DownloadResponseBody;\n\nimport java.io.BufferedInputStream;\nimport java.io.InputStream;\nimport java.io.RandomAccessFile;\n\nimport okhttp3.ResponseBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 17:09\n * Description :\n * 接口数据转换\n * 返回接口的   下载操作\n */\npublic class DownloadResponseConverter<T> implements Converter<ResponseBody, T> {\n\n    @Override\n    public T convert(ResponseBody value) throws Exception {\n\n        DownloadResponseBody responseBody = null;\n        if (value instanceof DownloadResponseBody) {\n            responseBody = (DownloadResponseBody) value;\n        }\n        if (responseBody == null) {\n            return null;\n        }\n        long length = responseBody.contentLength();\n        if (length == 0 || length == 1) {\n            // 说明文件已经下载完，直接跳转安装就好\n            return (T) String.valueOf(responseBody.getFile().getAbsoluteFile());\n        }\n        if (responseBody instanceof DownloadResponseBody) {\n            responseBody.setMaxProgress(length + responseBody.getStartsPoint());\n        }\n        // 保存文件到本地\n        InputStream is = null;\n        RandomAccessFile randomAccessFile = null;\n        BufferedInputStream bis = null;\n\n        byte[] buff = new byte[2048];\n        int len = 0;\n        try {\n            is = responseBody.byteStream();\n            bis = new BufferedInputStream(is);\n\n            // 随机访问文件，可以指定断点续传的起始位置\n            randomAccessFile = new RandomAccessFile(responseBody.getFile(), \"rwd\");\n            randomAccessFile.seek( responseBody.getStartsPoint());\n            while ((len = bis.read(buff)) != -1) {\n                randomAccessFile.write(buff, 0, len);\n            }\n\n            // 下载完成\n            return (T) String.valueOf(responseBody.getFile().getAbsoluteFile());\n        } catch (Exception e) {\n//                    postUIFail(e, requestParams);\n        } finally {\n            try {\n                if (is != null) {\n                    is.close();\n                }\n                if (bis != null) {\n                    bis.close();\n                }\n                if (randomAccessFile != null) {\n                    randomAccessFile.close();\n                }\n            } catch (Exception e) {\n\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/converter/StringConverterFactories.java",
    "content": "package com.xretrofit.converter;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\nimport okhttp3.ResponseBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 15:46\n * Description :\n * 接口数据转换器\n * 字符串转换器\n */\npublic class StringConverterFactories extends Converter.Factory {\n\n    public static StringConverterFactories create() {\n        return new StringConverterFactories();\n    }\n\n\n    @Nullable\n    @Override\n    public Converter<ResponseBody, ?> responseBodyConverter(Type request,Type responseType) {\n        Class<?> rawType = getRawType(responseType);\n        if (rawType == String.class) {\n            return new StringResponseConverter();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/converter/StringResponseConverter.java",
    "content": "package com.xretrofit.converter;\n\nimport okhttp3.ResponseBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 17:09\n * Description :\n * 接口数据转换\n * 返回接口的   字符串操作\n */\npublic class StringResponseConverter<T> implements Converter<ResponseBody, T> {\n\n\n    @Override\n    public T convert(ResponseBody value) throws Exception {\n        String responseStr = value.string();\n        return (T) responseStr;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/converter/UploadConverterFactories.java",
    "content": "package com.xretrofit.converter;\n\nimport com.yanxuwen.xretrofit_annotations.annotation.method.UPLOAD;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Type;\n\nimport okhttp3.RequestBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/7 16:32\n * 接口数据转换器\n * 转换器\n */\npublic class UploadConverterFactories extends Converter.Factory {\n\n    public static UploadConverterFactories create() {\n        return new UploadConverterFactories();\n    }\n\n    @Nullable\n    @Override\n    public Converter<?, RequestBody> requestBodyConverter(Type request, Type requestParamType) {\n        if (request == UPLOAD.class) {\n            return new UploadRequestConverter<>();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/converter/UploadRequestConverter.java",
    "content": "package com.xretrofit.converter;\n\nimport okhttp3.RequestBody;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/8 9:25\n * Description :\n * * 接口数据转换\n * * 返回接口的   上次操作\n */\npublic class UploadRequestConverter<T> implements Converter<T, RequestBody> {\n\n    @Override\n    public RequestBody convert(T value) throws Exception {\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/method/MethodAnnotation.java",
    "content": "package com.xretrofit.method;\n\nimport java.util.List;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 14:00\n * Description :\n * 方法注解，就是那些get post\n */\npublic class MethodAnnotation {\n    private Class annotation;//注解类型\n    private List<Object> key;//注解key\n\n    public MethodAnnotation(Class annotation , List<Object> key){\n        this.annotation = annotation;\n        this.key = key;\n\n    }\n\n    public Class getAnnotation() {\n        return annotation;\n    }\n\n    /**\n     * key虽然可以多个，但是这个基本都显示1个，并且为String\n     */\n    public String getKey() {\n        if (key == null || key.isEmpty()){\n            return null;\n        }\n        if (key.get(0) instanceof String){\n            return (String) key.get(0);\n        }\n        return null;\n    }\n\n    /**\n     * @Headers 使用\n     */\n    public List<Object> getKeys() {\n        return key;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/method/ParamAnnotation.java",
    "content": "package com.xretrofit.method;\n\nimport java.util.List;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 14:00\n * Description :\n * 参数注解, Queue,Path\n */\npublic class ParamAnnotation {\n    private Class annotation;//注解类型\n    private List<Object> key;//注解key ,会存在第一个key\n    private Object value;//注解字段，会存在为空问题\n\n    public ParamAnnotation(Class annotation, List<Object> key, Object value) {\n        this.annotation = annotation;\n        this.key = key;\n        this.value = value;\n    }\n\n    public Class getAnnotation() {\n        return annotation;\n    }\n\n    /**\n     * key虽然可以多个，但是这个基本都显示1个，并且为String\n     */\n    public String getKey() {\n        if (key == null || key.isEmpty()){\n            return null;\n        }\n        if (key.get(0) instanceof String){\n            return (String) key.get(0);\n        }\n        return null;\n    }\n\n    public Object getValue() {\n        return value;\n    }\n\n    public void setValue(Object value) {\n        this.value = value;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/method/ServiceMethod.java",
    "content": "package com.xretrofit.method;\n\nimport android.util.Log;\nimport android.util.Patterns;\n\nimport com.xretrofit.CallAdapter.CallAdapter;\nimport com.xretrofit.HttpManager;\nimport com.xretrofit.Interceptor.DownloadResponseBody;\nimport com.xretrofit.Interceptor.ProgressListener;\nimport com.xretrofit.Interceptor.UploadRequestBodyBody;\nimport com.xretrofit.bean.RequestParams;\nimport com.xretrofit.call.Call;\nimport com.xretrofit.call.OkHttpCall;\nimport com.xretrofit.call.ProgressCall;\nimport com.xretrofit.converter.Converter;\nimport com.xretrofit.utils.UrlUtils;\nimport com.xretrofit.utils.Utils;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.DELETE;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.DOWNLOAD;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.FORM;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.GET;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.Headers;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.POST;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.PUT;\nimport com.yanxuwen.xretrofit_annotations.annotation.method.UPLOAD;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Body;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.FilePath;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Header;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Param;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Path;\nimport com.yanxuwen.xretrofit_annotations.annotation.param.Query;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.lang.reflect.Type;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport okhttp3.FormBody;\nimport okhttp3.Interceptor;\nimport okhttp3.MediaType;\nimport okhttp3.MultipartBody;\nimport okhttp3.Request;\nimport okhttp3.RequestBody;\nimport okhttp3.Response;\nimport okhttp3.ResponseBody;\n\npublic class ServiceMethod {\n\n    //提交json数据\n    private static final MediaType JSON = MediaType.parse(\"application/json;charset=utf-8\");\n    //提交字符串数据\n    private static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse(\"text/x-markdown;charset=utf-8\");\n\n    private RequestParams requestParams = new RequestParams();\n\n    /**\n     * 头部暂时未处理\n     */\n    public <R> R request(Map<Class, MethodAnnotation> mapMa, List<ParamAnnotation> listPA, Type returnType) {\n        if (listPA == null) {\n            return null;\n        }\n        buildHeaders(mapMa,listPA);\n        Call<Object> myCall = null;\n        Type requestType = null;\n        if (mapMa.containsKey(GET.class)) {\n            Class annotation = GET.class;\n            requestType = annotation;\n            buildUrl(mapMa.get(annotation).getKey(), listPA);\n            final Request request = buildRequest(annotation, null);\n            okhttp3.Call call = HttpManager.getInstance().callFactory().newCall(request);\n            myCall = new OkHttpCall<>(call);\n        } else if ((mapMa.containsKey(POST.class) || mapMa.containsKey(PUT.class) || mapMa.containsKey(DELETE.class)) && mapMa.containsKey(FORM.class)) {\n            Class annotation = POST.class;\n            if (mapMa.containsKey(POST.class)) {\n                annotation = mapMa.get(POST.class).getAnnotation();\n            } else if (mapMa.containsKey(PUT.class)) {\n                annotation = mapMa.get(PUT.class).getAnnotation();\n            }\n            if (mapMa.containsKey(DELETE.class)) {\n                annotation = mapMa.get(DELETE.class).getAnnotation();\n            }\n            requestType = annotation;\n            //表单提交\n            buildUrl(mapMa.get(annotation).getKey(), listPA);\n            Map<String, Object> params = new HashMap<>();\n            for (ParamAnnotation paramAnnotation : listPA) {\n                if (Param.class == paramAnnotation.getAnnotation()) {\n                    params.put(paramAnnotation.getKey(), paramAnnotation.getValue());\n                }\n            }\n            FormBody.Builder builder = new FormBody.Builder();\n            addMapParmsToFromBody(params, builder);\n            Request request = buildRequest(annotation, builder.build());\n            okhttp3.Call call = HttpManager.getInstance().callFactory().newCall(request);\n            myCall = new OkHttpCall<>(call);\n        } else if (mapMa.containsKey(POST.class) || mapMa.containsKey(PUT.class) || mapMa.containsKey(DELETE.class)) {\n            Class annotation = POST.class;\n            if (mapMa.containsKey(POST.class)) {\n                annotation = mapMa.get(POST.class).getAnnotation();\n            } else if (mapMa.containsKey(PUT.class)) {\n                annotation = mapMa.get(PUT.class).getAnnotation();\n            }\n            if (mapMa.containsKey(DELETE.class)) {\n                annotation = mapMa.get(DELETE.class).getAnnotation();\n            }\n            requestType = annotation;\n            //json提交\n            buildUrl(mapMa.get(annotation).getKey(), listPA);\n            String json;\n            JSONObject jb = new JSONObject();\n            RequestBody requestBody = null;\n            for (ParamAnnotation paramAnnotation : listPA) {\n                if (Param.class == paramAnnotation.getAnnotation()) {\n                    try {\n                        jb.put(paramAnnotation.getKey(), paramAnnotation.getValue());\n                    } catch (JSONException e) {\n                        e.printStackTrace();\n                    }\n                    json = jb.toString();\n                    requestBody = RequestBody.create(JSON, json);\n                } else if (Body.class == paramAnnotation.getAnnotation() && paramAnnotation.getValue() instanceof String) {\n                    requestBody = RequestBody.create(JSON, (String) paramAnnotation.getValue());\n                } else {\n                    Converter<Object, RequestBody> converter = createRequestConverter(annotation, paramAnnotation.getValue().getClass());\n                    try {\n                        requestBody = converter.convert(paramAnnotation.getValue());\n                    } catch (Exception e) {\n                        //实体转换，使用转换器\n                        throw new IllegalStateException(\"@Body 没有定义该\" + paramAnnotation.getValue().getClass().getSimpleName() + \"的转换器，请使用addConverterFactory添加转换器\");\n                    }\n                }\n            }\n            if (requestBody == null) {\n                throw new NullPointerException(\"requestBody 为空\");\n            }\n            Request request = buildRequest(annotation, requestBody);\n            okhttp3.Call call = HttpManager.getInstance().callFactory().newCall(request);\n            myCall = new OkHttpCall<>(call);\n        } else if (mapMa.containsKey(DOWNLOAD.class)) {\n            Class annotation = DOWNLOAD.class;\n            requestType = annotation;\n            buildUrl(mapMa.get(annotation).getKey(), listPA);\n            String filePath = null;\n            for (ParamAnnotation paramAnnotation : listPA) {\n                //下载只支持String,File类型，因为他还支持List,后续看下是不是支持跟@body一样可以自定义\n                if (FilePath.class == paramAnnotation.getAnnotation()) {\n                    if (paramAnnotation.getValue() instanceof String) {\n                        filePath = (String) paramAnnotation.getValue();\n                    } else if (paramAnnotation.getValue() instanceof File) {\n                        filePath = ((File) paramAnnotation.getValue()).getAbsolutePath();\n                    }\n                }\n            }\n            if (filePath == null || filePath.equals(\"\")) {\n                throw new IllegalStateException(\"文件路径不存在\");\n            }\n            final File file = new File(filePath);\n            File folder = file.getParentFile();\n            if (!folder.exists()) {\n                try {\n                    boolean isMkdirs = folder.mkdirs();\n                    if (!isMkdirs) {\n                        throw new FileNotFoundException(\"java.io.FileNotFoundException: \" + folder + \": open failed: ENOENT (No such file or directory)\");\n                    }\n                } catch (Exception e) {\n                    throw new IllegalStateException(\"文件创建失败\");\n                }\n            }\n            final long startsPoint = file.length() > 0 ? file.length() - 1 : file.length();\n            requestParams.addHeader(\"RANGE\", \"bytes=\" + startsPoint + \"-\");//断点续传\n            Request request = buildRequest(annotation, null);\n            final ProgressListener listener = new ProgressListener();\n\n            // 重写ResponseBody监听请求\n            Interceptor interceptor = new Interceptor() {\n                @Override\n                public Response intercept(Chain chain) throws IOException {\n                    Response originalResponse = chain.proceed(chain.request());\n                    DownloadResponseBody responseBody = new DownloadResponseBody(originalResponse, startsPoint, file);\n                    responseBody.setProgressListener(listener);\n                    return originalResponse.newBuilder()\n                            .body(responseBody)\n                            .build();\n                }\n            };\n            okhttp3.Call call = HttpManager.getInstance().getOkHttpDownloadClient(interceptor).newCall(request);\n            myCall = new ProgressCall<>(call, listener);\n        } else if (mapMa.containsKey(UPLOAD.class)) {\n            Class annotation = UPLOAD.class;\n            requestType = annotation;\n            buildUrl(mapMa.get(annotation).getKey(), listPA);\n            List<File> listPath = new ArrayList<>();\n            for (ParamAnnotation paramAnnotation : listPA) {\n                if (FilePath.class == paramAnnotation.getAnnotation()) {\n                    if (paramAnnotation.getValue() instanceof String) {\n                        listPath.add(new File((String) paramAnnotation.getValue()));\n                    } else if (paramAnnotation.getValue() instanceof File) {\n                        listPath.add(((File) paramAnnotation.getValue()));\n                    } else if (paramAnnotation.getValue() instanceof List) {\n                        for (Object o : (List) paramAnnotation.getValue()) {\n                            if (o instanceof String) {\n                                listPath.add(new File((String) o));\n                            } else if (o instanceof File) {\n                                listPath.add(((File) o));\n                            }\n                        }\n                    }\n                }\n            }\n            //1.构建MultipartBody\n            MultipartBody.Builder multipartBody = new MultipartBody.Builder();\n            multipartBody.setType(MultipartBody.FORM);\n            //添加额外参数\n            for (ParamAnnotation paramAnnotation : listPA) {\n                if (Param.class == paramAnnotation.getAnnotation()) {\n                    try {\n                        multipartBody.addFormDataPart(paramAnnotation.getKey(), String.valueOf(paramAnnotation.getValue()));//后台接收文件流的参数名\n                    } catch (Exception e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n            //2.循环创建多个RequestBody\n            RequestBody fileBody = null;\n            ProgressListener[] listeners = new ProgressListener[listPath.size()];\n            for (int i = 0; i < listPath.size(); i++) {\n                File file = listPath.get(i);\n                String fileName = file.getName();\n\n                fileBody = RequestBody.create(MediaType.parse(Utils.guessMimeType(fileName)), file);\n                UploadRequestBodyBody requestBody = new UploadRequestBodyBody(fileBody);\n                listeners[i] = new ProgressListener();\n                requestBody.setProgressListener(listeners[i]);\n                //3.MultipartBody 添加Part 值\n                multipartBody.addFormDataPart(\"file\", fileName, requestBody);//后台接收文件流的参数名\n            }\n            final Request request = buildRequest(annotation, multipartBody.build());\n            okhttp3.Call call = HttpManager.getInstance().callFactory().newCall(request);\n            myCall = new ProgressCall<>(call, listeners);\n        }\n\n\n        return adapt(requestType, myCall, returnType);\n    }\n\n    private void buildHeaders(Map<Class, MethodAnnotation> mapMa, List<ParamAnnotation> listPA){\n        Map<String,String> mapHeader = new HashMap<>();\n         if (mapMa.containsKey(Headers.class)){\n             List<Object> list = mapMa.get(Headers.class).getKeys();\n             if (list != null) {\n                 for (Object o: list){\n                     String[] header = String.valueOf(o).split(\":\");\n                     if (header == null || header.length<2){\n                         continue;\n                     }\n                     mapHeader.put(header[0],header[1]);\n                 }\n             }\n         }\n         for (ParamAnnotation paramAnnotation : listPA){\n             if (Header.class == paramAnnotation.getAnnotation()){\n                 mapHeader.put(paramAnnotation.getKey(),String.valueOf(paramAnnotation.getValue()));\n             }\n         }\n         requestParams.setHeaders(mapHeader);\n    }\n\n    /**\n     * 编辑参数\n     */\n    private void buildUrl(String url, List<ParamAnnotation> listPA) {\n        if (listPA == null) {\n            return;\n        }\n        Map<String, Object> urlJoint = new HashMap<>();\n\n        for (ParamAnnotation paramAnnotation : listPA) {\n            if (Query.class == paramAnnotation.getAnnotation()) {\n                urlJoint.put(paramAnnotation.getKey(), paramAnnotation.getValue());\n            } else if (Path.class == paramAnnotation.getAnnotation() && paramAnnotation.getValue() instanceof String) {\n                url = url.replace(\"{\" + paramAnnotation.getKey() + \"}\", (String) paramAnnotation.getValue());\n            }\n        }\n\n        url = UrlUtils.urlJoint(url, urlJoint);\n        if (!Patterns.WEB_URL.matcher(url).matches() && HttpManager.getInstance().baseUrl != null) {\n          url = HttpManager.getInstance().baseUrl + url;\n        }\n        requestParams.setUrl(url);\n    }\n\n    private void addMapParmsToFromBody(Map<String, Object> params, FormBody.Builder builder) {\n        for (Map.Entry<String, Object> map : params.entrySet()) {\n            String key = map.getKey();\n            String value = \"\";\n            /**\n             * 判断值是否是空的\n             */\n            if (map.getValue() == null) {\n                value = \"\";\n            } else if (map.getValue() instanceof String) {\n                value = (String) map.getValue();\n            }\n            /**\n             * 把key和value添加到formbody中\n             */\n            builder.add(key, value);\n        }\n    }\n\n    private Request buildRequest(Class annotation, RequestBody body) {\n        Request.Builder builder = new Request.Builder();\n        builder.url(requestParams.getUrl());\n        if (body != null) {\n            if (POST.class == annotation || UPLOAD.class == annotation) {\n                builder.post(body);\n            } else if (PUT.class == annotation) {\n                builder.put(body);\n            } else if (DELETE.class == annotation) {\n                builder.delete(body);\n            }\n        } else if (GET.class == annotation) {\n            builder.get();\n        }\n        if (requestParams.getHeaders() != null) {\n            for (Map.Entry<String, String> entry : requestParams.getHeaders().entrySet()) {\n                builder.addHeader(entry.getKey(), entry.getValue());\n            }\n        }\n        return builder.build();\n    }\n\n\n    /**\n     * 获取请求参数数据转换器\n     */\n    private <T> Converter<T, RequestBody> createRequestConverter(Type request, Type requestParamType) {\n        for (int i = 0; i < HttpManager.getInstance().converterFactories.size(); i++) {\n            Converter<T, RequestBody> converter = (Converter<T, RequestBody>) HttpManager.getInstance().converterFactories.get(i).requestBodyConverter(request, requestParamType);\n            if (converter != null) {\n                return converter;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 获取结果数据转换器\n     */\n    public <T> Converter<ResponseBody, T> createResponseConverter(Type request, Type responseType) {\n        for (int i = 0; i < HttpManager.getInstance().converterFactories.size(); i++) {\n            Converter<ResponseBody, T> converter = (Converter<ResponseBody, T>) HttpManager.getInstance().converterFactories.get(i).responseBodyConverter(request, responseType);\n            if (converter != null) {\n                return converter;\n            }\n        }\n        return null;\n    }\n\n\n    /**\n     * 获取适配器\n     */\n    private CallAdapter<?, ?> createCallAdapter(Type type) {\n        for (int i = 0; i < HttpManager.getInstance().callAdapterFactories.size(); i++) {\n            CallAdapter<?, ?> converter = HttpManager.getInstance().callAdapterFactories.get(i).get(type);\n            if (converter != null) {\n                return converter;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 执行转化\n     */\n    private <R> R adapt(Type request, Call call, Type returnType) {\n        CallAdapter<?, ?> callAdapter = createCallAdapter(returnType);\n        call.init(createResponseConverter(request, callAdapter.responseType()));\n        if (callAdapter != null) {\n            return (R) callAdapter.adapt(call);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/okhttp/SslUtils.java",
    "content": "\npackage com.xretrofit.okhttp;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.security.KeyManagementException;\nimport java.security.KeyStore;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.X509Certificate;\n\nimport javax.net.ssl.KeyManager;\nimport javax.net.ssl.KeyManagerFactory;\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLSocketFactory;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.TrustManagerFactory;\nimport javax.net.ssl.X509TrustManager;\n\npublic class SslUtils {\n\n    public static class SSLParams {\n        public SSLSocketFactory sSLSocketFactory;\n        public X509TrustManager trustManager;\n    }\n\n    /**\n     * 信任所有\n     */\n    public static SSLParams getSslSocketFactory() {\n        return getSslSocketFactoryBase(null, null, null);\n    }\n\n    /**\n     * https单向认证\n     * 可以额外配置信任服务端的证书策略，否则默认是按CA证书去验证的，若不是CA可信任的证书，则无法通过验证\n     */\n    public static SSLParams getSslSocketFactory(X509TrustManager trustManager) {\n        return getSslSocketFactoryBase(trustManager, null, null);\n    }\n\n    /**\n     * https单向认证\n     * 用含有服务端公钥的证书校验服务端证书\n     */\n    public static SSLParams getSslSocketFactory(InputStream... certificates) {\n        return getSslSocketFactoryBase(null, null, null, certificates);\n    }\n\n    /**\n     * https双向认证\n     * bksFile 和 password -> 客户端使用bks证书校验服务端证书\n     * certificates -> 用含有服务端公钥的证书校验服务端证书\n     */\n    public static SSLParams getSslSocketFactory(InputStream bksFile, String password, InputStream... certificates) {\n        return getSslSocketFactoryBase(null, bksFile, password, certificates);\n    }\n\n    /**\n     * https双向认证\n     * bksFile 和 password -> 客户端使用bks证书校验服务端证书\n     * X509TrustManager -> 如果需要自己校验，那么可以自己实现相关校验，如果不需要自己校验，那么传null即可\n     */\n    public static SSLParams getSslSocketFactory(InputStream bksFile, String password, X509TrustManager trustManager) {\n        return getSslSocketFactoryBase(trustManager, bksFile, password);\n    }\n\n    private static SSLParams getSslSocketFactoryBase(X509TrustManager trustManager, InputStream bksFile, String password, InputStream... certificates) {\n        SSLParams sslParams = new SSLParams();\n        try {\n            KeyManager[] keyManagers = prepareKeyManager(bksFile, password);\n            TrustManager[] trustManagers = prepareTrustManager(certificates);\n            X509TrustManager manager;\n            if (trustManager != null) {\n                //优先使用用户自定义的TrustManager\n                manager = trustManager;\n            } else if (trustManagers != null) {\n                //然后使用默认的TrustManager\n                manager = chooseTrustManager(trustManagers);\n            } else {\n                //否则使用不安全的TrustManager\n                manager = UnSafeTrustManager;\n            }\n            // 创建TLS类型的SSLContext对象， that uses our TrustManager\n            SSLContext sslContext = SSLContext.getInstance(\"TLS\");\n            // 用上面得到的trustManagers初始化SSLContext，这样sslContext就会信任keyStore中的证书\n            // 第一个参数是授权的密钥管理器，用来授权验证，比如授权自签名的证书验证。第二个是被授权的证书管理器，用来验证服务器端的证书\n            sslContext.init(keyManagers, new TrustManager[]{manager}, null);\n            // 通过sslContext获取SSLSocketFactory对象\n            sslParams.sSLSocketFactory = sslContext.getSocketFactory();\n            sslParams.trustManager = manager;\n            return sslParams;\n        } catch (NoSuchAlgorithmException e) {\n            throw new AssertionError(e);\n        } catch (KeyManagementException e) {\n            throw new AssertionError(e);\n        }\n    }\n\n    private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {\n        try {\n            if (bksFile == null || password == null) return null;\n            KeyStore clientKeyStore = KeyStore.getInstance(\"BKS\");\n            clientKeyStore.load(bksFile, password.toCharArray());\n            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());\n            kmf.init(clientKeyStore, password.toCharArray());\n            return kmf.getKeyManagers();\n        } catch (Exception e) {\n        }\n        return null;\n    }\n\n    private static TrustManager[] prepareTrustManager(InputStream... certificates) {\n        if (certificates == null || certificates.length <= 0) return null;\n        try {\n            CertificateFactory certificateFactory = CertificateFactory.getInstance(\"X.509\");\n            // 创建一个默认类型的KeyStore，存储我们信任的证书\n            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());\n            keyStore.load(null);\n            int index = 0;\n            for (InputStream certStream : certificates) {\n                String certificateAlias = Integer.toString(index++);\n                // 证书工厂根据证书文件的流生成证书 cert\n                Certificate cert = certificateFactory.generateCertificate(certStream);\n                // 将 cert 作为可信证书放入到keyStore中\n                keyStore.setCertificateEntry(certificateAlias, cert);\n                try {\n                    if (certStream != null) certStream.close();\n                } catch (IOException e) {\n                }\n            }\n            //我们创建一个默认类型的TrustManagerFactory\n            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());\n            //用我们之前的keyStore实例初始化TrustManagerFactory，这样tmf就会信任keyStore中的证书\n            tmf.init(keyStore);\n            //通过tmf获取TrustManager数组，TrustManager也会信任keyStore中的证书\n            return tmf.getTrustManagers();\n        } catch (Exception e) {\n        }\n        return null;\n    }\n\n    private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {\n        for (TrustManager trustManager : trustManagers) {\n            if (trustManager instanceof X509TrustManager) {\n                return (X509TrustManager) trustManager;\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 为了解决客户端不信任服务器数字证书的问题，网络上大部分的解决方案都是让客户端不对证书做任何检查，\n     * 这是一种有很大安全漏洞的办法\n     */\n    public static X509TrustManager UnSafeTrustManager = new X509TrustManager() {\n        @Override\n        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {\n        }\n\n        @Override\n        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {\n        }\n\n        @Override\n        public X509Certificate[] getAcceptedIssuers() {\n            return new X509Certificate[]{};\n        }\n    };\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/utils/UrlUtils.java",
    "content": "package com.xretrofit.utils;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class UrlUtils {\n    /**\n     * @param url    实际URL的path\n     * @param params\n     * @return\n     */\n    public static String urlJoint(String url, Map<String, Object> params) {\n        StringBuilder realURL = new StringBuilder();\n        realURL = realURL.append(url);\n        boolean isFirst = true;\n        if (params == null) {\n            params = new HashMap<>();\n        } else {\n            Set<Map.Entry<String, Object>> entrySet = params.entrySet();\n            for (Map.Entry<String, Object> entry : entrySet) {\n                if (isFirst && !url.contains(\"?\")) {\n                    isFirst = false;\n                    realURL.append(\"?\");\n                } else {\n                    realURL.append(\"&\");\n                }\n                realURL.append(entry.getKey());\n                realURL.append(\"=\");\n                if (entry.getValue() == null) {\n                    realURL.append(\" \");\n                } else {\n                    realURL.append(entry.getValue());\n                }\n\n            }\n        }\n\n        return realURL.toString();\n    }\n}\n"
  },
  {
    "path": "XRetrofit/xretrofit/src/main/java/com/xretrofit/utils/Utils.java",
    "content": "package com.xretrofit.utils;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport java.io.IOException;\nimport java.lang.reflect.Array;\nimport java.lang.reflect.GenericArrayType;\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\nimport java.lang.reflect.TypeVariable;\nimport java.lang.reflect.WildcardType;\nimport java.net.FileNameMap;\nimport java.net.URLConnection;\n\nimport okhttp3.ResponseBody;\nimport okio.Buffer;\n\n/**\n * @author bsnl_yanxuwen\n * @date 2021/2/4 11:14\n * Description :\n */\npublic final class Utils {\n    public static <T> T checkNotNull(@Nullable T object, String message) {\n        if (object == null) {\n            throw new NullPointerException(message);\n        }\n        return object;\n    }\n\n    public static ResponseBody buffer(final ResponseBody body) throws IOException {\n        Buffer buffer = new Buffer();\n        body.source().readAll(buffer);\n        return ResponseBody.create(body.contentType(), body.contentLength(), buffer);\n    }\n\n    /**\n     * 获取接口返回的类型\n     */\n    public static Type getCallResponseType(Type returnType) {\n        if (!(returnType instanceof ParameterizedType)) {\n            return returnType;\n//            throw new IllegalArgumentException(\n//                    \"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>\");\n        }\n        return getParameterUpperBound(0, (ParameterizedType) returnType);\n    }\n\n\n    /**\n     * 应该是获取下一层的 泛型类型\n     */\n    public static Type getParameterUpperBound(int index, ParameterizedType type) {\n        Type[] types = type.getActualTypeArguments();\n        if (index < 0 || index >= types.length) {\n            throw new IllegalArgumentException(\n                    \"Index \" + index + \" not in range [0,\" + types.length + \") for \" + type);\n        }\n        Type paramType = types[index];\n        if (paramType instanceof WildcardType) {\n            return ((WildcardType) paramType).getUpperBounds()[0];\n        }\n        return paramType;\n    }\n\n    public static Class<?> getRawType(Type type) {\n        checkNotNull(type, \"type == null\");\n\n        if (type instanceof Class<?>) {\n            // Type is a normal class.\n            return (Class<?>) type;\n        }\n        if (type instanceof ParameterizedType) {\n            ParameterizedType parameterizedType = (ParameterizedType) type;\n\n            // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but\n            // suspects some pathological case related to nested classes exists.\n            Type rawType = parameterizedType.getRawType();\n            if (!(rawType instanceof Class)) throw new IllegalArgumentException();\n            return (Class<?>) rawType;\n        }\n        if (type instanceof GenericArrayType) {\n            Type componentType = ((GenericArrayType) type).getGenericComponentType();\n            return Array.newInstance(getRawType(componentType), 0).getClass();\n        }\n        if (type instanceof TypeVariable) {\n            // We could use the variable's bounds, but that won't work if there are multiple. Having a raw\n            // type that's more general than necessary is okay.\n            return Object.class;\n        }\n        if (type instanceof WildcardType) {\n            return getRawType(((WildcardType) type).getUpperBounds()[0]);\n        }\n\n        throw new IllegalArgumentException(\"Expected a Class, ParameterizedType, or \"\n                + \"GenericArrayType, but <\" + type + \"> is of type \" + type.getClass().getName());\n    }\n\n    /**\n     * 猜测MimeType，上传使用\n     */\n    public static String guessMimeType(String fileName) {\n        FileNameMap fileNameMap = URLConnection.getFileNameMap();\n        String contentTypeFor = fileNameMap.getContentTypeFor(fileName);\n        if (contentTypeFor == null) {\n            contentTypeFor = \"application/octet-stream\";\n        }\n        return contentTypeFor;\n    }\n}\n"
  }
]