Kotlin中如何运行时修改接口伴生对象的BASE_URL变量值
实现Kotlin应用运行时动态修改Retrofit BaseURL的方案
步骤1:创建配置管理类存储动态BaseURL
实现一个AppConfig类,封装SharedPreferences操作,负责保存和读取用户设置的服务器地址:
class AppConfig(private val context: Context) { private val prefs = context.getSharedPreferences("app_config", Context.MODE_PRIVATE) // 默认地址,与原硬编码值一致 private val DEFAULT_BASE_URL = "http://192.168.3.118:5000/" // 获取当前使用的BaseURL fun getBaseUrl(): String { return prefs.getString("base_url", DEFAULT_BASE_URL) ?: DEFAULT_BASE_URL } // 保存新的BaseURL fun saveBaseUrl(url: String) { prefs.edit().putString("base_url", url.trim()).apply() } }
步骤2:修改Dagger Hilt模块,注入配置依赖
在AppModule中添加AppConfig的单例提供,并调整Retrofit和OkHttp的初始化逻辑:
@Module @InstallIn(SingletonComponent::class) object AppModule { // 提供AppConfig单例 @Provides @Singleton fun provideAppConfig(app: Application): AppConfig = AppConfig(app) // 提供带有BaseURL动态替换拦截器的OkHttpClient @Provides @Singleton fun provideOkHttpClient(appConfig: AppConfig) = OkHttpClient.Builder() .addInterceptor(BaseUrlInterceptor(appConfig)) .readTimeout(6000, TimeUnit.SECONDS) .callTimeout(6000, TimeUnit.SECONDS) .build() // 初始化Retrofit,使用AppConfig中的地址 @Provides @Singleton fun provideRetrofit(appConfig: AppConfig): Retrofit = Retrofit.Builder() .baseUrl(appConfig.getBaseUrl()) .client(provideOkHttpClient(appConfig)) .addConverterFactory(GsonConverterFactory.create()) .build() @Provides @Singleton fun provideSybaseApi(retrofit: Retrofit): SybaseApi = retrofit.create(SybaseApi::class.java) @Provides @Singleton fun provideDatabase(app: Application): SybaseDatabase = Room.databaseBuilder(app, SybaseDatabase::class.java, "horovice") .fallbackToDestructiveMigration() .allowMainThreadQueries() .build() }
步骤3:实现动态BaseURL拦截器
添加OkHttp拦截器,在每次请求时替换为最新配置的BaseURL,解决Retrofit实例创建后地址无法修改的问题:
class BaseUrlInterceptor(private val appConfig: AppConfig) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() val currentBaseUrl = appConfig.getBaseUrl().trimEnd('/') + "/" val originalBaseUrl = originalRequest.url.baseUrl().toString() // 替换请求中的旧BaseURL为最新地址 val newUrl = originalRequest.url.toString() .replace(originalBaseUrl, currentBaseUrl) .let { HttpUrl.parse(it) } ?: originalRequest.url val newRequest = originalRequest.newBuilder() .url(newUrl) .build() return chain.proceed(newRequest) } }
步骤4:移除硬编码的BaseURL
修改SybaseApi接口,删除伴生对象中的硬编码常量:
interface SybaseApi { @GET("getItem") suspend fun getItem(): List<Items> }
步骤5:实现用户修改界面
创建对话框让用户输入新服务器地址并保存,示例代码:
fun showServerConfigDialog(context: Context, appConfig: AppConfig) { val inputEditText = EditText(context).apply { hint = "输入服务器地址(如http://192.168.3.119:5000/)" setText(appConfig.getBaseUrl()) inputType = InputType.TYPE_TEXT_VARIATION_URI } AlertDialog.Builder(context) .setTitle("修改服务器地址") .setView(inputEditText) .setPositiveButton("保存") { dialog, _ -> val newUrl = inputEditText.text.toString().trim() if (newUrl.isNotEmpty()) { appConfig.saveBaseUrl(newUrl) Toast.makeText(context, "服务器地址已更新", Toast.LENGTH_SHORT).show() } dialog.dismiss() } .setNegativeButton("取消") { dialog, _ -> dialog.dismiss() } .show() }
在Activity中调用示例:
@Inject lateinit var appConfig: AppConfig // 绑定按钮点击事件打开修改对话框 btnConfig.setOnClickListener { showServerConfigDialog(this, appConfig) }
用户修改地址后,后续所有网络请求会自动使用新地址,无需重启应用。
内容的提问来源于stack exchange,提问作者jenik2205
相关产品推荐
相关产品推荐

