代理模式是开发中很常用的设计模式,此模式主要有两个部分,一部分是代理部分,一部分是真实部分.
代理模式的官方解释是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
实现代理模式有两种方案:静态代理和动态代理。静态代理是指代理类在编译期就已经确定,即需要事先手动编写一个代理类。动态代理则是在运行时动态生成代理类。
这里带给大家一个动态代理一个很实用的开发技巧:动态设置Release包和Debug包的配置,以解决开发中频繁手动切换正式服和测试服服务器地址等功能,当然还可以通过这个扩展很多动态切换的功能.此处只是举一个例子.
接口代码:
interface HttpApi : Environment { @Test("test.w3cvs.com") @Product("release.w3cvs.com") fun baseUrl():String }
动态代理环境代码:
enum class Env { Test,Product } interface Environment{ fun env():Env } object EnvironmentUtil { lateinit var env: Env fun init(envStr: String) { env = Env.valueOf(envStr) Log.w(this::class.java.simpleName, "init ---> envStr:$envStr env:${env.name}") } inline fun <reified T : Environment> get(): T { val clazz = T::class.java println("env clazz content $clazz") require(clazz.isInterface) { "API declarations must be interfaces." } return Proxy.newProxyInstance( clazz.classLoader, arrayOf(clazz), object : InvocationHandler { override fun invoke(proxy: Any, method: Method, args: Array<out Any>?): Any { if (method.name == "env") return env when (val annotation = method.annotations.find { it.annotationClass.simpleName == env.name }) { is Product -> return annotation.value is Test -> return annotation.value } return "" } } ) as T } } @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.FUNCTION) annotation class (val value: String) @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.FUNCTION) annotation class Product(val value: String)
Application代码: 此处别忘记设置清单文件中的 android:name=".App"
class App : Application(){ private var context : Context? = null override fun onCreate() { super.onCreate() context = this EnvironmentUtil.init(BuildConfig.Env) } }
MainActivity代码:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Log.d("${this.componentName}", EnvironmentUtil.get<HttpApi>().baseUrl()) Log.d("${this.componentName}", EnvironmentUtil.env.name) } }
build.gradle(:app)
android { compileSdk 31 defaultConfig { applicationId "com.yaoyu.dynamicproxydemo" minSdk 23 targetSdk 31 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } //在apk文件后边生成版本号信息 applicationVariants.all { variant -> variant.outputs.all { output -> def outputFile = output.outputFile def fileName = "" if (outputFile != null && outputFile.name.endsWith('.apk')) { if (variant.buildType.name == 'release') { fileName = "ProxyDemo_release_${defaultConfig.versionName}_${new Date().format("yyyyMMdd")}.apk" } else if (variant.buildType.name == 'debug') { fileName = "ProxyDemo_${defaultConfig.versionName}_${new Date().format("yyyyMMdd")}_debug.apk" } output.outputFileName = fileName } } } signingConfigs{ release{ File strFile = new File("你的签名路径:") storeFile file(strFile) storePassword "你的storePassword " keyPassword "你的keyPassword " keyAlias "你的keyAlias " } } buildTypes { release { minifyEnabled false signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' buildConfigField "String", "Env", "\"$RELEASE_ENV\"" } debug { // signingConfig signingConfigs.debug buildConfigField "String", "Env", "\"$DEBUG_ENV\"" } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } }
注:红色代码是是关键代码,蓝色代码是需要替代成你自己的