ソースを参照

网络封装 rxjava版本

wangmeng 2 週間 前
コミット
f9ed90cd23
16 ファイル変更1707 行追加0 行削除
  1. 5 0
      base-common/build.gradle
  2. 54 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/ApiDisposableObserver.kt
  3. 171 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/NetworkManager.kt
  4. 112 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/NetworkUtil.kt
  5. 330 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/README.md
  6. 81 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/ResponseThrowable.kt
  7. 113 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/RxApiResponse.kt
  8. 113 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/RxApiResponseTransformer.kt
  9. 190 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/RxExceptionHandler.kt
  10. 23 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/CookieJarImpl.kt
  11. 42 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/CookieStore.kt
  12. 45 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/MemoryCookieStore.kt
  13. 99 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/SPCookieStore.kt
  14. 127 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/download/DownloadManager.kt
  15. 76 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/interceptor/HeaderInterceptor.kt
  16. 126 0
      base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/interceptor/TokenRefreshInterceptor.kt

+ 5 - 0
base-common/build.gradle

@@ -48,6 +48,11 @@ dependencies {
     implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
     implementation("androidx.lifecycle:lifecycle-process:2.7.0")
     
+    // RxJava 2
+    api("io.reactivex.rxjava2:rxjava:2.2.21")
+    api("io.reactivex.rxjava2:rxandroid:2.1.1")
+    api("com.squareup.retrofit2:adapter-rxjava2:2.9.0")
+    
     // 注意:SocketIO 已移动到 capability-socketio 模块,不再在此处依赖
     
     // 注意:Gson、Retrofit、OkHttp、Glide、Coroutines 已通过 base-core 传递,无需重复依赖

+ 54 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/ApiDisposableObserver.kt

@@ -0,0 +1,54 @@
+package com.narutohuo.xindazhou.common.networkrx
+
+import io.reactivex.disposables.Disposable
+
+/**
+ * API 观察者
+ * 
+ * 提供基础的 API 响应观察功能
+ */
+abstract class ApiDisposableObserver<T> {
+    
+    /**
+     * 成功回调
+     */
+    protected abstract fun onSuccess(data: T)
+    
+    /**
+     * 错误回调
+     */
+    protected open fun onError(code: Int, message: String) {
+        // 默认实现
+    }
+    
+    /**
+     * 订阅回调
+     */
+    protected open fun onSubscribe(d: Disposable) {
+        // 默认实现
+    }
+    
+    /**
+     * 完成回调
+     */
+    protected open fun onComplete() {
+        // 默认实现
+    }
+}
+
+/**
+ * 简化的 API 观察者
+ */
+class SimpleApiDisposableObserver<T>(
+    private val onSuccess: (T) -> Unit,
+    private val onError: ((Int, String) -> Unit)? = null
+) : ApiDisposableObserver<T>() {
+    
+    override fun onSuccess(data: T) {
+        onSuccess(data)
+    }
+    
+    override fun onError(code: Int, message: String) {
+        onError?.invoke(code, message)
+    }
+}

+ 171 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/NetworkManager.kt

@@ -0,0 +1,171 @@
+package com.narutohuo.xindazhou.common.networkrx
+
+import android.content.Context
+import com.narutohuo.xindazhou.common.networkrx.cookie.CookieJarImpl
+import com.narutohuo.xindazhou.common.networkrx.cookie.CookieStore
+import com.narutohuo.xindazhou.common.networkrx.cookie.MemoryCookieStore
+import com.narutohuo.xindazhou.common.networkrx.cookie.SPCookieStore
+import com.narutohuo.xindazhou.common.networkrx.interceptor.HeaderInterceptor
+import com.narutohuo.xindazhou.common.networkrx.interceptor.TokenRefreshInterceptor
+import okhttp3.OkHttpClient
+import retrofit2.Retrofit
+import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
+import retrofit2.converter.gson.GsonConverterFactory
+import java.util.concurrent.TimeUnit
+
+/**
+ * 网络管理器(基于RxJava)
+ * 
+ * 参考MVVMHabit框架设计,提供网络请求的核心配置
+ * 
+ * 功能:
+ * - OkHttpClient配置
+ * - Retrofit实例创建
+ * - 超时设置
+ * - 拦截器管理
+ * - Cookie管理
+ * - 网络状态检测
+ * 
+ * 使用方式:
+ * ```kotlin
+ * val apiService = NetworkManager.createApi(ApiService::class.java)
+ * apiService.login(request)
+ *     .subscribeOn(Schedulers.io())
+ *     .observeOn(AndroidSchedulers.mainThread())
+ *     .subscribe({
+ *         // 处理成功
+ *     }, {
+ *         // 处理错误
+ *     })
+ * ```
+ */
+object NetworkManager {
+    
+    private const val DEFAULT_TIMEOUT = 30L
+    private const val BASE_URL = "https://api.example.com/"
+    
+    private val cookieStore: CookieStore = MemoryCookieStore()
+    
+    /**
+     * 获取Cookie存储
+     * 
+     * @return CookieStore
+     */
+    fun getCookieStore(): CookieStore {
+        return cookieStore
+    }
+    
+    /**
+     * 创建OkHttpClient实例
+     * 
+     * @param interceptors 拦截器列表
+     * @param useCookie 是否使用Cookie管理
+     * @return OkHttpClient
+     */
+    fun createOkHttpClient(
+        vararg interceptors: okhttp3.Interceptor,
+        useCookie: Boolean = true
+    ): OkHttpClient {
+        val builder = OkHttpClient.Builder()
+            .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
+            .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
+            .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
+            .retryOnConnectionFailure(true)
+        
+        // 添加Cookie管理
+        if (useCookie) {
+            builder.cookieJar(CookieJarImpl(getCookieStore()))
+        }
+        
+        // 添加拦截器
+        interceptors.forEach {
+            builder.addInterceptor(it)
+        }
+        
+        return builder.build()
+    }
+    
+    /**
+     * 创建Retrofit实例
+     * 
+     * @param baseUrl 基础URL
+     * @param client OkHttpClient
+     * @return Retrofit
+     */
+    fun createRetrofit(baseUrl: String = BASE_URL, client: OkHttpClient): Retrofit {
+        return Retrofit.Builder()
+            .baseUrl(baseUrl)
+            .client(client)
+            .addConverterFactory(GsonConverterFactory.create())
+            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
+            .build()
+    }
+    
+    /**
+     * 创建API服务
+     * 
+     * @param clazz API接口类
+     * @param baseUrl 基础URL
+     * @param client OkHttpClient
+     * @return API服务实例
+     */
+    fun <T> createApi(
+        clazz: Class<T>,
+        baseUrl: String = BASE_URL,
+        client: OkHttpClient = createOkHttpClient()
+    ): T {
+        val retrofit = createRetrofit(baseUrl, client)
+        return retrofit.create(clazz)
+    }
+    
+    /**
+     * 创建默认的OkHttpClient
+     * 
+     * @param useCookie 是否使用Cookie管理
+     * @return OkHttpClient
+     */
+    fun getDefaultOkHttpClient(useCookie: Boolean = true): OkHttpClient {
+        return createOkHttpClient(
+            HeaderInterceptor(),
+            TokenRefreshInterceptor(),
+            useCookie = useCookie
+        )
+    }
+    
+    /**
+     * 获取默认的Retrofit实例
+     * 
+     * @param useCookie 是否使用Cookie管理
+     * @return Retrofit
+     */
+    fun getDefaultRetrofit(useCookie: Boolean = true): Retrofit {
+        return createRetrofit(client = getDefaultOkHttpClient(useCookie))
+    }
+    
+    /**
+     * 清除Cookie
+     */
+    fun clearCookie() {
+        cookieStore?.clearCookie()
+    }
+    
+    /**
+     * 检查网络是否连接
+     * 
+     * @param context 上下文
+     * @return 是否连接网络
+     */
+    fun isNetworkConnected(context: Context): Boolean {
+        return NetworkUtil.isNetworkConnected(context)
+    }
+    
+    /**
+     * 获取网络类型
+     * 
+     * @param context 上下文
+     * @return 网络类型
+     */
+    fun getNetworkType(context: Context): NetworkUtil.NetworkType {
+        return NetworkUtil.getNetworkType(context)
+    }
+}

+ 112 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/NetworkUtil.kt

@@ -0,0 +1,112 @@
+package com.narutohuo.xindazhou.common.networkrx
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.os.Build
+
+/**
+ * 网络工具类
+ * 
+ * 提供网络状态检测等功能
+ * 
+ * 对应 MVVMHabit 的 NetworkUtil
+ */
+object NetworkUtil {
+    
+    /**
+     * 检查网络是否连接
+     * 
+     * @param context 上下文
+     * @return 是否连接网络
+     */
+    fun isNetworkConnected(context: Context): Boolean {
+        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+        
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            val network = connectivityManager.activeNetwork ?: return false
+            val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
+            return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+        } else {
+            // 旧版本 API
+            val networkInfo = connectivityManager.activeNetworkInfo ?: return false
+            return networkInfo.isConnected
+        }
+    }
+    
+    /**
+     * 检查是否是 WiFi 连接
+     * 
+     * @param context 上下文
+     * @return 是否是 WiFi 连接
+     */
+    fun isWifiConnected(context: Context): Boolean {
+        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+        
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            val network = connectivityManager.activeNetwork ?: return false
+            val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
+            return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
+        } else {
+            // 旧版本 API
+            val networkInfo = connectivityManager.activeNetworkInfo ?: return false
+            return networkInfo.type == ConnectivityManager.TYPE_WIFI && networkInfo.isConnected
+        }
+    }
+    
+    /**
+     * 检查是否是移动网络连接
+     * 
+     * @param context 上下文
+     * @return 是否是移动网络连接
+     */
+    fun isMobileConnected(context: Context): Boolean {
+        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+        
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            val network = connectivityManager.activeNetwork ?: return false
+            val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
+            return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+        } else {
+            // 旧版本 API
+            val networkInfo = connectivityManager.activeNetworkInfo ?: return false
+            return networkInfo.type == ConnectivityManager.TYPE_MOBILE && networkInfo.isConnected
+        }
+    }
+    
+    /**
+     * 获取网络类型
+     * 
+     * @param context 上下文
+     * @return 网络类型
+     */
+    fun getNetworkType(context: Context): NetworkType {
+        if (!isNetworkConnected(context)) {
+            return NetworkType.NONE
+        }
+        
+        if (isWifiConnected(context)) {
+            return NetworkType.WIFI
+        }
+        
+        if (isMobileConnected(context)) {
+            return NetworkType.MOBILE
+        }
+        
+        return NetworkType.OTHER
+    }
+    
+    /**
+     * 网络类型
+     */
+    enum class NetworkType {
+        /** 无网络 */
+        NONE,
+        /** WiFi */
+        WIFI,
+        /** 移动网络 */
+        MOBILE,
+        /** 其他网络 */
+        OTHER
+    }
+}

+ 330 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/README.md

@@ -0,0 +1,330 @@
+# NetworkRx 模块
+
+基于 RxJava 的网络模块封装,参考 MVVMHabit 框架设计,提供完整的网络请求解决方案。
+
+## 功能特点
+
+### 核心功能
+- **网络管理器**:统一的 OkHttpClient 和 Retrofit 配置
+- **拦截器**:请求头拦截器和 Token 自动刷新拦截器
+- **响应封装**:统一的 API 响应格式处理
+- **线程调度**:自动的线程切换(IO 线程执行,主线程回调)
+- **错误处理**:统一的异常处理机制
+- **重试机制**:支持网络请求重试
+- **Token 管理**:自动处理 Token 过期刷新
+- **Cookie 管理**:支持内存和持久化 Cookie 存储
+- **下载管理**:支持文件下载和进度监听
+- **网络状态检测**:支持网络连接状态和类型检测
+
+### 技术栈
+- Kotlin
+- RxJava 2
+- Retrofit 2
+- OkHttp 3
+- Gson
+
+## 目录结构
+
+```
+networkrx/
+├── cookie/                    # Cookie 管理
+│   ├── CookieJarImpl.kt       # CookieJar 实现
+│   ├── CookieStore.kt         # Cookie 存储接口
+│   ├── MemoryCookieStore.kt   # 内存 Cookie 存储
+│   └── SPCookieStore.kt       # SharedPreferences Cookie 存储
+├── download/                  # 下载管理
+│   └── DownloadManager.kt     # 下载管理器
+├── interceptor/               # 拦截器
+│   ├── HeaderInterceptor.kt   # 请求头拦截器
+│   └── TokenRefreshInterceptor.kt # Token 刷新拦截器
+├── NetworkManager.kt          # 网络管理器(核心)
+├── NetworkUtil.kt             # 网络工具类
+├── ResponseThrowable.kt       # 响应异常类
+├── RxApiResponse.kt           # API 响应封装
+├── RxApiResponseTransformer.kt # 响应转换器
+├── RxExceptionHandler.kt      # 异常处理器
+├── ApiDisposableObserver.kt   # API 可disposable 观察者
+├── README.md                  # 说明文档
+├── MVVMHABIT对比分析.md        # 对比分析文档
+└── MVVMHABIT完整功能实现.md      # 完整功能实现说明
+```
+
+## 使用方式
+
+### 1. 基本使用
+
+```kotlin
+// 1. 定义API接口
+interface ApiService {
+    @POST("/api/login")
+    fun login(@Body request: LoginRequest): Observable<LoginResponse>
+    
+    @GET("/api/user/profile")
+    fun getUserProfile(): Observable<RxCommonResponse<UserProfile>>
+}
+
+// 2. 创建API服务实例
+val apiService = NetworkManager.createApi(ApiService::class.java)
+
+// 3. 发起网络请求
+apiService.login(LoginRequest("username", "password"))
+    .compose(RxApiResponseTransformer.transform())
+    .subscribe(object : ApiDisposableObserver<LoginResponse>() {
+        override fun onSuccess(data: LoginResponse) {
+            // 处理成功
+            Log.d("Login", "Success: $data")
+        }
+        
+        override fun onError(code: Int, message: String) {
+            // 处理错误
+            Log.e("Login", "Error: $code - $message")
+        }
+    })
+```
+
+### 2. 使用通用响应格式
+
+```kotlin
+apiService.getUserProfile()
+    .compose(RxApiResponseTransformer.transformCommonResponse())
+    .subscribe(object : ApiDisposableObserver<UserProfile>() {
+        override fun onSuccess(data: UserProfile) {
+            // 处理成功
+        }
+        
+        override fun onError(code: Int, message: String) {
+            // 处理错误
+        }
+    })
+```
+
+### 3. 带重试的请求
+
+```kotlin
+apiService.login(LoginRequest("username", "password"))
+    .compose(RxApiResponseTransformer.transformWithRetry(
+        maxRetries = 3, // 最大重试3次
+        retryDelayMillis = 1000 // 重试延迟1秒
+    ))
+    .subscribe(object : ApiDisposableObserver<LoginResponse>() {
+        override fun onSuccess(data: LoginResponse) {
+            // 处理成功
+        }
+        
+        override fun onError(code: Int, message: String) {
+            // 处理错误
+        }
+    })
+```
+
+### 4. 自定义网络配置
+
+```kotlin
+// 自定义OkHttpClient
+val customClient = NetworkManager.createOkHttpClient(
+    HeaderInterceptor(),
+    TokenRefreshInterceptor(),
+    // 可以添加其他自定义拦截器
+    HttpLoggingInterceptor().apply {
+        level = HttpLoggingInterceptor.Level.BODY
+    }
+)
+
+// 创建API服务
+val apiService = NetworkManager.createApi(
+    ApiService::class.java,
+    baseUrl = "https://api.example.com/",
+    client = customClient
+)
+```
+
+### 5. 简单回调方式
+
+```kotlin
+apiService.login(LoginRequest("username", "password"))
+    .compose(RxApiResponseTransformer.transform())
+    .subscribe(SimpleApiDisposableObserver(
+        onSuccess = { data ->
+            // 处理成功
+        },
+        onError = { code, message ->
+            // 处理错误
+        }
+    ))
+```
+
+## 配置说明
+
+### 基础配置
+- **默认超时时间**:30秒
+- **默认BaseUrl**:https://api.example.com/
+- **默认线程调度**:IO线程执行,主线程回调
+
+### 拦截器配置
+
+#### HeaderInterceptor
+自动添加以下请求头:
+- Content-Type: application/json; charset=utf-8
+- Accept: application/json
+- X-App-Version: App版本号
+- X-Device-Type: Android
+- X-Platform: Android
+- X-Request-Id: 唯一请求ID
+- Authorization: Bearer Token(如果存在)
+
+#### TokenRefreshInterceptor
+- 检测401错误(Token过期)
+- 自动刷新Token
+- 线程安全处理(避免并发刷新)
+- 重试失败的请求
+
+## 响应格式
+
+### RxApiResponse
+
+```kotlin
+sealed class RxApiResponse<out T> {
+    data class Success<T>(val data: T) : RxApiResponse<T>()
+    data class Error<T>(
+        val code: Int,
+        val message: String,
+        val error: Throwable? = null
+    ) : RxApiResponse<T>()
+}
+```
+
+### 通用响应格式
+
+```kotlin
+data class RxCommonResponse<T>(
+    val code: Int,         // 业务状态码,0表示成功
+    val message: String,   // 响应消息
+    val data: T?           // 响应数据
+)
+```
+
+## 异常处理
+
+### 网络异常类型
+
+```kotlin
+enum class NetworkErrorType {
+    NETWORK_ERROR,     // 网络错误(超时、连接失败等)
+    SERVER_ERROR,      // 服务器错误(500系列)
+    TOKEN_EXPIRED,     // Token过期(401)
+    BUSINESS_ERROR,    // 业务错误(其他HTTP错误)
+    UNKNOWN_ERROR      // 未知错误
+}
+```
+
+### 异常处理器
+
+```kotlin
+// 处理异常
+val (code, message) = RxExceptionHandler.handleException(throwable)
+
+// 获取错误类型
+val errorType = RxExceptionHandler.getErrorType(throwable)
+```
+
+## 依赖说明
+
+需要在项目的 build.gradle 中添加以下依赖:
+
+```groovy
+dependencies {
+    // RxJava
+    implementation "io.reactivex.rxjava2:rxjava:2.2.21"
+    implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
+    
+    // Retrofit
+    implementation "com.squareup.retrofit2:retrofit:2.9.0"
+    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
+    implementation "com.squareup.retrofit2:adapter-rxjava2:2.9.0"
+    
+    // OkHttp
+    implementation "com.squareup.okhttp3:okhttp:4.9.3"
+    implementation "com.squareup.okhttp3:logging-interceptor:4.9.3"
+    
+    // Gson
+    implementation "com.google.code.gson:gson:2.8.9"
+}
+```
+
+## 注意事项
+
+1. **Token管理**:需要实现 `TokenRefreshInterceptor` 中的 `refreshToken()` 和 `saveToken()` 方法
+2. **BaseUrl配置**:需要根据实际项目修改 `NetworkManager` 中的 `BASE_URL`
+3. **错误码处理**:需要根据后端返回的错误码格式调整错误处理逻辑
+4. **线程安全**:`TokenRefreshInterceptor` 已做线程安全处理,但在多线程环境下仍需注意
+5. **内存泄漏**:使用 `ApiDisposableObserver` 时,需要注意在适当的时机取消订阅
+6. **Cookie管理**:默认使用内存 Cookie 存储(应用重启后丢失)
+7. **权限**:下载功能需要存储权限,网络状态检测需要网络权限
+
+## 示例代码
+
+### 完整的登录请求示例
+
+```kotlin
+// 1. 定义API接口
+interface AuthApi {
+    @POST("/api/auth/login")
+    fun login(@Body request: LoginRequest): Observable<RxCommonResponse<LoginResponse>>
+}
+
+// 2. 创建API服务
+val authApi = NetworkManager.createApi(AuthApi::class.java)
+
+// 3. 发起登录请求
+val loginDisposable = authApi.login(LoginRequest("user@example.com", "password123"))
+    .compose(RxApiResponseTransformer.transformCommonResponse())
+    .subscribe(object : ApiDisposableObserver<LoginResponse>() {
+        override fun onSuccess(data: LoginResponse) {
+            // 登录成功,保存Token
+            saveToken(data.token)
+            
+            // 跳转到主页面
+            navigateToMainActivity()
+        }
+        
+        override fun onError(code: Int, message: String) {
+            // 登录失败,显示错误信息
+            showToast(message)
+        }
+    })
+
+// 4. 在适当的时机取消订阅
+fun onDestroy() {
+    loginDisposable.dispose()
+}
+```
+
+## 与 Network 模块对比
+
+| 特性 | NetworkRx | Network(协程) |
+|------|-----------|----------------|
+| 响应式编程 | RxJava 2 | 协程 + Flow |
+| 线程调度 | Schedulers | 协程上下文 |
+| 错误处理 | onError回调 | try-catch |
+| 操作符 | 丰富的Rx操作符 | 协程挂起函数 |
+| 学习成本 | 较高 | 较低 |
+| 代码复杂度 | 中等 | 低 |
+| 生态成熟度 | 成熟稳定 | 现代推荐 |
+
+## 适用场景
+
+- 项目已经使用 RxJava
+- 需要丰富的响应式操作符
+- 习惯使用 Observer 模式
+- 从 MVVMHabit 框架迁移
+
+## 总结
+
+NetworkRx 模块提供了完整的基于 RxJava 的网络请求解决方案,参考 MVVMHabit 框架设计,具有以下优势:
+
+- **功能完整**:涵盖了网络请求的各个方面
+- **使用简单**:链式调用,API 简洁明了
+- **扩展性强**:模块化设计,易于定制
+- **稳定性高**:基于成熟的 RxJava 生态
+
+可以根据项目需求选择使用 NetworkRx(RxJava)或 Network(协程)模块。

+ 81 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/ResponseThrowable.kt

@@ -0,0 +1,81 @@
+package com.narutohuo.xindazhou.common.networkrx
+
+/**
+ * 响应异常
+ * 
+ * 封装 API 响应中的错误信息
+ * 
+ * 对应 MVVMHabit 的 ResponseThrowable
+ */
+open class ResponseThrowable(
+    val code: Int,
+    message: String,
+    val error: Throwable? = null
+) : Exception(message, error) {
+    
+    /**
+     * 错误类型
+     */
+    val errorType: ErrorType
+        get() = when (code) {
+            in 400..499 -> ErrorType.CLIENT_ERROR
+            in 500..599 -> ErrorType.SERVER_ERROR
+            401 -> ErrorType.UNAUTHORIZED
+            403 -> ErrorType.FORBIDDEN
+            404 -> ErrorType.NOT_FOUND
+            else -> ErrorType.OTHER
+        }
+    
+    /**
+     * 错误类型枚举
+     */
+    enum class ErrorType {
+        /** 客户端错误 */
+        CLIENT_ERROR,
+        /** 服务器错误 */
+        SERVER_ERROR,
+        /** 未授权 */
+        UNAUTHORIZED,
+        /** 禁止访问 */
+        FORBIDDEN,
+        /** 资源不存在 */
+        NOT_FOUND,
+        /** 其他错误 */
+        OTHER
+    }
+    
+    override fun toString(): String {
+        return "ResponseThrowable(code=$code, message='$message', errorType=$errorType)"
+    }
+}
+
+/**
+ * 业务错误
+ * 
+ * 用于封装业务逻辑错误
+ */
+class BusinessException(
+    code: Int,
+    message: String,
+    error: Throwable? = null
+) : ResponseThrowable(code, message, error)
+
+/**
+ * 网络错误
+ * 
+ * 用于封装网络相关错误
+ */
+class NetworkException(
+    message: String,
+    error: Throwable? = null
+) : ResponseThrowable(-1, message, error)
+
+/**
+ * Token 过期错误
+ * 
+ * 用于封装 Token 过期错误
+ */
+class TokenExpiredException(
+    message: String = "Token 已过期",
+    error: Throwable? = null
+) : ResponseThrowable(401, message, error)

+ 113 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/RxApiResponse.kt

@@ -0,0 +1,113 @@
+package com.narutohuo.xindazhou.common.networkrx
+
+/**
+ * RxJava API响应封装
+ * 
+ * 统一封装网络响应,支持RxJava链式调用
+ * 
+ * 功能:
+ * - 统一的响应格式
+ * - 支持成功和失败状态
+ * - 与RxJava无缝集成
+ * 
+ * 使用方式:
+ * ```kotlin
+ * apiService.login(request)
+ *     .compose(RxApiResponseTransformer())
+ *     .subscribe({
+ *         // 处理成功
+ *     }, {
+ *         // 处理错误
+ *     })
+ * ```
+ */
+
+/**
+ * API响应基类
+ */
+sealed class RxApiResponse<out T> {
+    
+    /**
+     * 成功响应
+     * 
+     * @param data 响应数据
+     */
+    data class Success<T>(val data: T) : RxApiResponse<T>()
+    
+    /**
+     * 错误响应
+     * 
+     * @param code 错误码
+     * @param message 错误消息
+     * @param error 原始错误
+     */
+    data class Error<T>(
+        val code: Int,
+        val message: String,
+        val error: Throwable? = null
+    ) : RxApiResponse<T>()
+}
+
+/**
+ * 通用响应数据结构
+ * 
+ * 适用于大多数API响应格式
+ */
+data class RxCommonResponse<T>(
+    val code: Int,
+    val message: String,
+    val data: T?
+) {
+    /**
+     * 是否成功
+     */
+    val isSuccess: Boolean
+        get() = code == 0
+}
+
+/**
+ * API响应转换器
+ * 
+ * 将通用响应转换为RxApiResponse
+ */
+object RxApiResponseConverter {
+    
+    /**
+     * 转换通用响应
+     * 
+     * @param response 通用响应
+     * @return RxApiResponse
+     */
+    fun <T> convert(response: RxCommonResponse<T>): RxApiResponse<T> {
+        return if (response.isSuccess) {
+            if (response.data != null) {
+                RxApiResponse.Success(response.data)
+            } else {
+                RxApiResponse.Error(
+                    code = -1,
+                    message = "数据为空",
+                    error = NullPointerException("Response data is null")
+                )
+            }
+        } else {
+            RxApiResponse.Error(
+                code = response.code,
+                message = response.message
+            )
+        }
+    }
+    
+    /**
+     * 转换异常
+     * 
+     * @param throwable 异常
+     * @return RxApiResponse.Error
+     */
+    fun <T> convertError(throwable: Throwable): RxApiResponse.Error<T> {
+        return RxApiResponse.Error(
+            code = -1,
+            message = throwable.message ?: "网络错误",
+            error = throwable
+        )
+    }
+}

+ 113 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/RxApiResponseTransformer.kt

@@ -0,0 +1,113 @@
+package com.narutohuo.xindazhou.common.networkrx
+
+import io.reactivex.Observable
+import io.reactivex.ObservableTransformer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+
+/**
+ * RxJava API响应转换器
+ * 
+ * 用于在Observable链中统一处理API响应
+ * 
+ * 功能:
+ * - 线程调度
+ * - 响应转换
+ * - 错误处理
+ * - 统一的响应格式
+ * 
+ * 使用方式:
+ * ```kotlin
+ * apiService.login(request)
+ *     .compose(RxApiResponseTransformer.transform())
+ *     .subscribe({
+ *         // 处理成功
+ *     }, {
+ *         // 处理错误
+ *     })
+ * ```
+ */
+object RxApiResponseTransformer {
+    
+    /**
+     * 转换Observable
+     * 
+     * @return ObservableTransformer
+     */
+    fun <T> transform(): ObservableTransformer<T, RxApiResponse<T>> {
+        return ObservableTransformer {
+            it.subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .map<RxApiResponse<T>> { data ->
+                    RxApiResponse.Success(data)
+                }
+                .onErrorReturn { throwable ->
+                    RxApiResponseConverter.convertError<T>(throwable)
+                }
+        }
+    }
+    
+    /**
+     * 转换通用响应
+     * 
+     * @return ObservableTransformer
+     */
+    fun <T> transformCommonResponse(): ObservableTransformer<RxCommonResponse<T>, RxApiResponse<T>> {
+        return ObservableTransformer {upstream ->
+            upstream
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .map {
+                    RxApiResponseConverter.convert(it)
+                }
+                .onErrorReturn { throwable ->
+                    RxApiResponseConverter.convertError(throwable)
+                }
+        }
+    }
+    
+    /**
+     * 仅进行线程调度
+     * 
+     * @return ObservableTransformer
+     */
+    fun <T> schedulers(): ObservableTransformer<T, T> {
+        return ObservableTransformer {upstream ->
+            upstream
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+        }
+    }
+    
+    /**
+     * 带重试的转换器
+     * 
+     * @param maxRetries 最大重试次数
+     * @param retryDelayMillis 重试延迟时间(毫秒)
+     * @return ObservableTransformer
+     */
+    fun <T> transformWithRetry(
+        maxRetries: Int = 3,
+        retryDelayMillis: Long = 1000
+    ): ObservableTransformer<T, RxApiResponse<T>> {
+        return ObservableTransformer {
+            it.subscribeOn(Schedulers.io())
+                .retryWhen {errors ->
+                    errors.zipWith(Observable.range(1, maxRetries + 1)) { error, attempt ->
+                        if (attempt > maxRetries) {
+                            throw error
+                        }
+                        attempt
+                    }
+                    .flatMap { Observable.timer(retryDelayMillis, java.util.concurrent.TimeUnit.MILLISECONDS) }
+                }
+                .observeOn(AndroidSchedulers.mainThread())
+                .map<RxApiResponse<T>> { data ->
+                    RxApiResponse.Success(data)
+                }
+                .onErrorReturn { throwable ->
+                    RxApiResponseConverter.convertError<T>(throwable)
+                }
+        }
+    }
+}

+ 190 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/RxExceptionHandler.kt

@@ -0,0 +1,190 @@
+package com.narutohuo.xindazhou.common.networkrx
+
+import io.reactivex.observers.DisposableObserver
+
+/**
+ * RxJava异常处理器
+ * 
+ * 统一处理RxJava网络请求中的异常
+ * 
+ * 功能:
+ * - 统一的异常处理
+ * - 错误码解析
+ * - 网络错误处理
+ * - 业务错误处理
+ * 
+ * 使用方式:
+ * ```kotlin
+ * apiService.login(request)
+ *     .compose(RxApiResponseTransformer.transform())
+ *     .subscribe(object : RxApiObserver<LoginResponse>() {
+ *         override fun onSuccess(data: LoginResponse) {
+ *             // 处理成功
+ *         }
+ *         
+ *         override fun onError(code: Int, message: String) {
+ *             // 处理错误
+ *         }
+ *     })
+ * ```
+ */
+
+/**
+ * API响应观察者
+ * 
+ * 简化API响应的处理
+ */
+abstract class RxApiObserver<T> : DisposableObserver<RxApiResponse<T>>() {
+    
+    override fun onNext(response: RxApiResponse<T>) {
+        when (response) {
+            is RxApiResponse.Success -> {
+                onSuccess(response.data)
+            }
+            is RxApiResponse.Error -> {
+                onError(response.code, response.message)
+                onError(response)
+            }
+        }
+    }
+    
+    override fun onError(e: Throwable) {
+        // 这里不会被调用,因为错误已经在转换器中处理了
+        onError(-1, e.message ?: "未知错误")
+    }
+    
+    override fun onComplete() {
+        // 完成回调
+    }
+    
+    /**
+     * 成功回调
+     * 
+     * @param data 响应数据
+     */
+    abstract fun onSuccess(data: T)
+    
+    /**
+     * 错误回调
+     * 
+     * @param code 错误码
+     * @param message 错误消息
+     */
+    open fun onError(code: Int, message: String) {
+        // 默认实现,子类可以覆盖
+    }
+    
+    /**
+     * 错误回调(完整错误信息)
+     * 
+     * @param error 错误响应
+     */
+    open fun onError(error: RxApiResponse.Error<T>) {
+        // 默认实现,子类可以覆盖
+    }
+}
+
+/**
+ * 简单的API响应回调
+ * 
+ * 适用于不需要处理错误的场景
+ */
+class SimpleRxApiObserver<T>(
+    private val onSuccess: (T) -> Unit,
+    private val onError: ((Int, String) -> Unit)? = null
+) : RxApiObserver<T>() {
+    
+    override fun onSuccess(data: T) {
+        onSuccess.invoke(data)
+    }
+    
+    override fun onError(code: Int, message: String) {
+        onError?.invoke(code, message)
+    }
+}
+
+/**
+ * 网络异常类型
+ */
+enum class NetworkErrorType {
+    /** 网络错误 */
+    NETWORK_ERROR,
+    /** 服务器错误 */
+    SERVER_ERROR,
+    /** Token过期 */
+    TOKEN_EXPIRED,
+    /** 业务错误 */
+    BUSINESS_ERROR,
+    /** 未知错误 */
+    UNKNOWN_ERROR
+}
+
+/**
+ * 异常处理工具
+ */
+object RxExceptionHandler {
+    
+    /**
+     * 处理异常
+     * 
+     * @param throwable 异常
+     * @return 错误信息
+     */
+    fun handleException(throwable: Throwable): Pair<Int, String> {
+        return when (throwable) {
+            is java.net.SocketTimeoutException -> {
+                Pair(-1, "网络超时,请检查网络连接")
+            }
+            is java.net.ConnectException -> {
+                Pair(-1, "网络连接失败,请检查网络连接")
+            }
+            is java.net.UnknownHostException -> {
+                Pair(-1, "无法连接到服务器,请检查网络连接")
+            }
+            is retrofit2.HttpException -> {
+                val code = throwable.code()
+                val message = when (code) {
+                    400 -> "请求参数错误"
+                    401 -> "未授权,请重新登录"
+                    403 -> "禁止访问"
+                    404 -> "请求的资源不存在"
+                    500 -> "服务器内部错误"
+                    502 -> "网关错误"
+                    503 -> "服务不可用"
+                    504 -> "网关超时"
+                    else -> "HTTP错误:$code"
+                }
+                Pair(code, message)
+            }
+            else -> {
+                Pair(-1, throwable.message ?: "未知错误")
+            }
+        }
+    }
+    
+    /**
+     * 获取错误类型
+     * 
+     * @param throwable 异常
+     * @return 错误类型
+     */
+    fun getErrorType(throwable: Throwable): NetworkErrorType {
+        return when (throwable) {
+            is java.net.SocketTimeoutException,
+            is java.net.ConnectException,
+            is java.net.UnknownHostException -> {
+                NetworkErrorType.NETWORK_ERROR
+            }
+            is retrofit2.HttpException -> {
+                when (throwable.code()) {
+                    401 -> NetworkErrorType.TOKEN_EXPIRED
+                    in 500..599 -> NetworkErrorType.SERVER_ERROR
+                    else -> NetworkErrorType.BUSINESS_ERROR
+                }
+            }
+            else -> {
+                NetworkErrorType.UNKNOWN_ERROR
+            }
+        }
+    }
+}

+ 23 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/CookieJarImpl.kt

@@ -0,0 +1,23 @@
+package com.narutohuo.xindazhou.common.networkrx.cookie
+
+import okhttp3.Cookie
+import okhttp3.CookieJar
+import okhttp3.HttpUrl
+
+/**
+ * CookieJar 实现
+ * 
+ * 管理 HTTP Cookie
+ * 
+ * 对应 MVVMHabit 的 Cookie 管理
+ */
+class CookieJarImpl(private val cookieStore: CookieStore) : CookieJar {
+    
+    override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
+        cookieStore.saveCookie(url, cookies)
+    }
+    
+    override fun loadForRequest(url: HttpUrl): List<Cookie> {
+        return cookieStore.loadCookie(url)
+    }
+}

+ 42 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/CookieStore.kt

@@ -0,0 +1,42 @@
+package com.narutohuo.xindazhou.common.networkrx.cookie
+
+import okhttp3.Cookie
+import okhttp3.HttpUrl
+
+/**
+ * Cookie 存储接口
+ * 
+ * 定义 Cookie 的存储和加载方法
+ * 
+ * 对应 MVVMHabit 的 Cookie 存储
+ */
+interface CookieStore {
+    
+    /**
+     * 保存 Cookie
+     * 
+     * @param url HTTP URL
+     * @param cookies Cookie 列表
+     */
+    fun saveCookie(url: HttpUrl, cookies: List<Cookie>)
+    
+    /**
+     * 加载 Cookie
+     * 
+     * @param url HTTP URL
+     * @return Cookie 列表
+     */
+    fun loadCookie(url: HttpUrl): List<Cookie>
+    
+    /**
+     * 清除所有 Cookie
+     */
+    fun clearCookie()
+    
+    /**
+     * 清除指定 URL 的 Cookie
+     * 
+     * @param url HTTP URL
+     */
+    fun clearCookie(url: HttpUrl)
+}

+ 45 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/MemoryCookieStore.kt

@@ -0,0 +1,45 @@
+package com.narutohuo.xindazhou.common.networkrx.cookie
+
+import okhttp3.Cookie
+import okhttp3.HttpUrl
+
+/**
+ * 内存 Cookie 存储
+ * 
+ * 将 Cookie 存储在内存中,应用重启后会丢失
+ * 
+ * 对应 MVVMHabit 的内存 Cookie 存储
+ */
+class MemoryCookieStore : CookieStore {
+    
+    private val cookieMap = mutableMapOf<String, MutableList<Cookie>>()
+    
+    override fun saveCookie(url: HttpUrl, cookies: List<Cookie>) {
+        val host = url.host
+        val existingCookies = cookieMap.getOrDefault(host, mutableListOf())
+        
+        // 移除过期的 Cookie
+        existingCookies.removeAll { it.expiresAt < System.currentTimeMillis() }
+        
+        // 添加新的 Cookie
+        existingCookies.addAll(cookies)
+        cookieMap[host] = existingCookies
+    }
+    
+    override fun loadCookie(url: HttpUrl): List<Cookie> {
+        val host = url.host
+        val cookies = cookieMap.getOrDefault(host, mutableListOf())
+        
+        // 过滤掉过期的 Cookie
+        return cookies.filter { it.expiresAt > System.currentTimeMillis() }
+    }
+    
+    override fun clearCookie() {
+        cookieMap.clear()
+    }
+    
+    override fun clearCookie(url: HttpUrl) {
+        val host = url.host
+        cookieMap.remove(host)
+    }
+}

+ 99 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/cookie/SPCookieStore.kt

@@ -0,0 +1,99 @@
+package com.narutohuo.xindazhou.common.networkrx.cookie
+
+import android.content.Context
+import android.content.SharedPreferences
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import okhttp3.Cookie
+import okhttp3.HttpUrl
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * SharedPreferences Cookie 存储
+ * 
+ * 将 Cookie 存储在 SharedPreferences 中,应用重启后仍然保留
+ * 
+ * 对应 MVVMHabit 的持久化 Cookie 存储
+ */
+class SPCookieStore(private val context: Context) : CookieStore {
+    
+    private val sp: SharedPreferences = context.getSharedPreferences("cookie_store", Context.MODE_PRIVATE)
+    private val gson = Gson()
+    private val cookieMap = ConcurrentHashMap<String, MutableList<Cookie>>()
+    
+    init {
+        // 从 SharedPreferences 加载 Cookie
+        loadCookiesFromSP()
+    }
+    
+    private fun loadCookiesFromSP() {
+        val allCookies = sp.all
+        for ((host, cookieJson) in allCookies) {
+            if (cookieJson is String) {
+                val type = object : TypeToken<MutableList<Cookie>>() {}.type
+                val cookies = gson.fromJson<MutableList<Cookie>>(cookieJson, type)
+                if (cookies != null) {
+                    // 过滤掉过期的 Cookie
+                    val validCookies = cookies.filter { it.expiresAt > System.currentTimeMillis() }
+                    if (validCookies.isNotEmpty()) {
+                        cookieMap[host] = validCookies.toMutableList()
+                    } else {
+                        // 删除过期的 Cookie
+                        sp.edit().remove(host).apply()
+                    }
+                }
+            }
+        }
+    }
+    
+    private fun saveCookiesToSP() {
+        val editor = sp.edit()
+        for ((host, cookies) in cookieMap) {
+            val cookieJson = gson.toJson(cookies)
+            editor.putString(host, cookieJson)
+        }
+        editor.apply()
+    }
+    
+    override fun saveCookie(url: HttpUrl, cookies: List<Cookie>) {
+        val host = url.host
+        val existingCookies = cookieMap.getOrDefault(host, mutableListOf())
+        
+        // 移除过期的 Cookie
+        existingCookies.removeAll { it.expiresAt < System.currentTimeMillis() }
+        
+        // 添加新的 Cookie
+        existingCookies.addAll(cookies)
+        cookieMap[host] = existingCookies
+        
+        // 保存到 SharedPreferences
+        saveCookiesToSP()
+    }
+    
+    override fun loadCookie(url: HttpUrl): List<Cookie> {
+        val host = url.host
+        val cookies = cookieMap.getOrDefault(host, mutableListOf())
+        
+        // 过滤掉过期的 Cookie
+        val validCookies = cookies.filter { it.expiresAt > System.currentTimeMillis() }
+        
+        // 如果有过期的 Cookie,更新存储
+        if (validCookies.size != cookies.size) {
+            cookieMap[host] = validCookies.toMutableList()
+            saveCookiesToSP()
+        }
+        
+        return validCookies
+    }
+    
+    override fun clearCookie() {
+        cookieMap.clear()
+        sp.edit().clear().apply()
+    }
+    
+    override fun clearCookie(url: HttpUrl) {
+        val host = url.host
+        cookieMap.remove(host)
+        sp.edit().remove(host).apply()
+    }
+}

+ 127 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/download/DownloadManager.kt

@@ -0,0 +1,127 @@
+package com.narutohuo.xindazhou.common.networkrx.download
+
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import java.io.File
+import java.io.FileOutputStream
+import java.io.InputStream
+
+/**
+ * 下载管理器
+ * 
+ * 处理文件下载,支持进度监听
+ * 
+ * 对应 MVVMHabit 的 DownLoadManager
+ */
+class DownloadManager(private val client: OkHttpClient = OkHttpClient()) {
+    
+    /**
+     * 下载文件
+     * 
+     * @param url 下载链接
+     * @param destFile 目标文件
+     * @param progressListener 进度监听器
+     * @return 是否下载成功
+     */
+    fun download(
+        url: String,
+        destFile: File,
+        progressListener: DownloadProgressListener? = null
+    ): Boolean {
+        try {
+            val request = Request.Builder()
+                .url(url)
+                .build()
+            
+            val response = client.newCall(request).execute()
+            
+            if (!response.isSuccessful) {
+                progressListener?.onError("下载失败: ${response.code}")
+                return false
+            }
+            
+            val body = response.body ?: run {
+                progressListener?.onError("无响应体")
+                return false
+            }
+            
+            val totalBytes = body.contentLength()
+            var downloadedBytes: Long = 0
+            
+            // 确保目标目录存在
+            destFile.parentFile?.mkdirs()
+            
+            val inputStream: InputStream = body.byteStream()
+            val outputStream = FileOutputStream(destFile)
+            
+            val buffer = ByteArray(8192)
+            var bytesRead: Int
+            
+            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
+                outputStream.write(buffer, 0, bytesRead)
+                downloadedBytes += bytesRead
+                
+                // 通知进度
+                if (totalBytes > 0) {
+                    val progress = (downloadedBytes * 100 / totalBytes).toInt()
+                    progressListener?.onProgress(progress)
+                }
+            }
+            
+            outputStream.flush()
+            outputStream.close()
+            inputStream.close()
+            
+            progressListener?.onSuccess(destFile)
+            return true
+            
+        } catch (e: Exception) {
+            progressListener?.onError(e.message ?: "下载异常")
+            e.printStackTrace()
+            return false
+        }
+    }
+    
+    /**
+     * 下载进度监听器
+     */
+    interface DownloadProgressListener {
+        /**
+         * 进度更新
+         * 
+         * @param progress 进度百分比 (0-100)
+         */
+        fun onProgress(progress: Int)
+        
+        /**
+         * 下载成功
+         * 
+         * @param file 下载的文件
+         */
+        fun onSuccess(file: File)
+        
+        /**
+         * 下载失败
+         * 
+         * @param errorMessage 错误信息
+         */
+        fun onError(errorMessage: String)
+    }
+    
+    /**
+     * 简单的下载进度监听器实现
+     */
+    open class SimpleDownloadListener : DownloadProgressListener {
+        override fun onProgress(progress: Int) {
+            // 默认实现,可重写
+        }
+        
+        override fun onSuccess(file: File) {
+            // 默认实现,可重写
+        }
+        
+        override fun onError(errorMessage: String) {
+            // 默认实现,可重写
+        }
+    }
+}

+ 76 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/interceptor/HeaderInterceptor.kt

@@ -0,0 +1,76 @@
+package com.narutohuo.xindazhou.common.networkrx.interceptor
+
+import okhttp3.Interceptor
+import okhttp3.Request
+import okhttp3.Response
+
+/**
+ * 请求头拦截器(基于RxJava)
+ * 
+ * 为所有网络请求添加通用的请求头
+ * 
+ * 功能:
+ * - 添加Content-Type
+ * - 添加Accept
+ * - 添加设备信息
+ * - 添加App版本信息
+ * - 添加其他通用头
+ * 
+ * 使用方式:
+ * ```kotlin
+ * val client = NetworkManager.createOkHttpClient(HeaderInterceptor())
+ * ```
+ */
+class HeaderInterceptor : Interceptor {
+    
+    override fun intercept(chain: Interceptor.Chain): Response {
+        val originalRequest = chain.request()
+        
+        // 构建新的请求
+        val requestBuilder = originalRequest.newBuilder()
+            .addHeader("Content-Type", "application/json; charset=utf-8")
+            .addHeader("Accept", "application/json")
+            .addHeader("X-App-Version", getAppVersion())
+            .addHeader("X-Device-Type", "Android")
+            .addHeader("X-Platform", "Android")
+            .addHeader("X-Request-Id", generateRequestId())
+        
+        // 添加Token(如果存在)
+        val token = getToken()
+        if (!token.isNullOrEmpty()) {
+            requestBuilder.addHeader("Authorization", "Bearer $token")
+        }
+        
+        val request = requestBuilder.build()
+        return chain.proceed(request)
+    }
+    
+    /**
+     * 获取App版本号
+     * 
+     * @return 版本号
+     */
+    private fun getAppVersion(): String {
+        // 实际项目中应从BuildConfig或包管理器获取
+        return "1.0.0"
+    }
+    
+    /**
+     * 生成请求ID
+     * 
+     * @return 请求ID
+     */
+    private fun generateRequestId(): String {
+        return System.currentTimeMillis().toString() + "-" + Math.random().toString().substring(2, 8)
+    }
+    
+    /**
+     * 获取Token
+     * 
+     * @return Token
+     */
+    private fun getToken(): String? {
+        // 实际项目中应从存储或Token管理器获取
+        return null
+    }
+}

+ 126 - 0
base-common/src/main/java/com/narutohuo/xindazhou/common/networkrx/interceptor/TokenRefreshInterceptor.kt

@@ -0,0 +1,126 @@
+package com.narutohuo.xindazhou.common.networkrx.interceptor
+
+import okhttp3.Interceptor
+import okhttp3.Request
+import okhttp3.Response
+
+/**
+ * Token刷新拦截器(基于RxJava)
+ * 
+ * 处理Token过期的自动刷新
+ * 
+ * 功能:
+ * - 检测Token过期
+ * - 自动刷新Token
+ * - 重试失败的请求
+ * - 线程安全处理
+ * 
+ * 使用方式:
+ * ```kotlin
+ * val client = NetworkManager.createOkHttpClient(TokenRefreshInterceptor())
+ * ```
+ */
+class TokenRefreshInterceptor : Interceptor {
+    
+    // 锁对象,用于线程同步
+    private val lock = Any()
+    
+    // 是否正在刷新Token
+    private var isRefreshing = false
+    
+    // 刷新后的新Token
+    private var newToken: String? = null
+    
+    override fun intercept(chain: Interceptor.Chain): Response {
+        val request = chain.request()
+        val response = chain.proceed(request)
+        
+        // 检查是否需要刷新Token
+        if (isTokenExpired(response)) {
+            synchronized(lock) {
+                // 双重检查,避免重复刷新
+                if (!isRefreshing) {
+                    isRefreshing = true
+                    try {
+                        // 刷新Token
+                        newToken = refreshToken()
+                        if (!newToken.isNullOrEmpty()) {
+                            // 保存新Token
+                            saveToken(newToken!!)
+                        }
+                    } finally {
+                        isRefreshing = false
+                    }
+                } else {
+                    // 等待Token刷新完成
+                    while (isRefreshing) {
+                        Thread.sleep(100)
+                    }
+                }
+            }
+            
+            // 使用新Token重新请求
+            if (!newToken.isNullOrEmpty()) {
+                val newRequest = request.newBuilder()
+                    .header("Authorization", "Bearer $newToken")
+                    .build()
+                return chain.proceed(newRequest)
+            }
+        }
+        
+        return response
+    }
+    
+    /**
+     * 检查Token是否过期
+     * 
+     * @param response 响应
+     * @return 是否过期
+     */
+    private fun isTokenExpired(response: Response): Boolean {
+        // 检查HTTP状态码
+        if (response.code == 401) {
+            return true
+        }
+        
+        // 检查响应体中的错误码
+        try {
+            val responseBody = response.peekBody(1024 * 1024).string()
+            // 这里可以根据实际的响应格式检查错误码
+            // 例如:"code": 401, "message": "Token expired"
+            return responseBody.contains("Token expired") || responseBody.contains("\"code\": 401")
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+        
+        return false
+    }
+    
+    /**
+     * 刷新Token
+     * 
+     * @return 新Token
+     */
+    private fun refreshToken(): String? {
+        // 实际项目中应调用刷新Token的API
+        // 这里模拟刷新Token
+        try {
+            // 模拟网络请求延迟
+            Thread.sleep(1000)
+            return "new_token_" + System.currentTimeMillis()
+        } catch (e: Exception) {
+            e.printStackTrace()
+            return null
+        }
+    }
+    
+    /**
+     * 保存Token
+     * 
+     * @param token 新Token
+     */
+    private fun saveToken(token: String) {
+        // 实际项目中应保存到安全存储
+        // 例如:SharedPreferences、EncryptedSharedPreferences等
+    }
+}