王学岗------隔离层的设计

假设我们开发一个APP,版本一访问网络用的是HttpClient,版本二访问网络要求改成OKHttp,这种需求是不是很蛋疼,没关系,等我们学会了隔离层设计。这个问题就会迎刃而解。隔离层有三种实现方式:
1,代理模式 轻量级,耦合度高
2,HILT注入 重量级 耦合度低
3,SPI机制 零耦合 内存消耗大
我们一 一来看下。

代理模式

王学岗------隔离层的设计_第1张图片
看下项目结构
王学岗------隔离层的设计_第2张图片
看下httpprocessor代码

package com.example.test0530.httpprocessor;

import java.util.Map;

/**
 * 房产公司
 */
public interface IHttpProcessor {
    //有卖房的能力,访问网络的能力,这里只写一个POST请求,你可以添加其他请求方式
    void post(String url, Map params,ICallback callback);
}

package com.example.test0530.httpprocessor;

/**
 * 顶层的回调接口
 */
public interface ICallback {
    void onSucess(String result);
    void onFailure(String e);
}

package com.example.test0530.httpprocessor;

import java.util.Map;

public class HttpHelper implements IHttpProcessor{
    //定义一个业主,卖房的人
    private static IHttpProcessor mIHttpProcessor = null;
    //通过API来设置哪一个业主卖出自己的房子,(谁来完成网络访问)
    public static void init(IHttpProcessor httpProcessor){//传入第三方框架
        mIHttpProcessor = httpProcessor;
    }
    //单例
    private HttpHelper(){}
    private static HttpHelper instance;
    public static HttpHelper obtain(){
        synchronized (HttpHelper.class){
            if(instance == null){
                instance = new HttpHelper();
            }
        }
        return instance;
    }
    @Override
    public void post(String url, Map params, ICallback callback) {
             mIHttpProcessor.post(url, params, callback);
    }
}

package com.example.test0530.httpprocessor;

import com.google.gson.Gson;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 回调接口的一种实现
 */
public abstract class HttpCallBack implements ICallback {
    @Override
    public void onSucess(String result) {
        //网络上回来的结果都在Result上,要做三件事
        //1,得到调用者用什么样的javabean来接收数据
        Class clz = analysisClassInfo(this);//得到泛型result的类型
        //2,把String 转成javabean
        Gson gson = new Gson();
        T objectResult = (T) gson.fromJson(result, clz);
        //3,把结果交给用户(交给程序员使用)
        sucess(objectResult);
    }

    //交给别人使用最好的就是用抽象方法
    public abstract void sucess(T t);

    @Override
    public void onFailure(String e) {

    }

    /**
     * 得到输入参数的实际类型
     */
    private Class analysisClassInfo(Object object) {
        //获取到各种各样数据类型
        Type type = object.getClass().getGenericSuperclass();
        //获得各种泛型,比如我们传入了三个泛型,params数组就会有三个元素,三个class对象
        Type[] params = ((ParameterizedType) type).getActualTypeArguments();
        //我只有一个泛型,所以返回数组的第0个元素
        return (Class) params[0];

    }
}

各类网络访问框架,有需要自己可以加更多。这里只展示两种。

package com.example.test0530.volley;

import android.content.Context;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.example.test0530.httpprocessor.ICallback;
import com.example.test0530.httpprocessor.IHttpProcessor;

import java.util.Map;

public class VolleyProcessor implements IHttpProcessor {

    //以下是volley的用法
    private static RequestQueue mQueue = null;

    public VolleyProcessor(Context context) {
        mQueue = Volley.newRequestQueue(context);
    }

    @Override
    public void post(String url, Map params, ICallback callback) {
//        //获取第三方框架从网络回来的String结果
//        callback.onSucess();
        StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener() {
            @Override
            public void onResponse(String response) {
            //这句代码至为关键
                callback.onSucess(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        mQueue.add(stringRequest);
    }
}

package com.example.test0530.okhttp;

import com.example.test0530.httpprocessor.ICallback;
import com.example.test0530.httpprocessor.IHttpProcessor;

import java.util.Map;

public class OKHttpProcessor implements IHttpProcessor {
    @Override
    public void post(String url, Map params, ICallback callback) {
         略
    }
}

接下来我们看下怎么使用

package com.example.test0530;

import com.example.test0530.httpprocessor.HttpHelper;
import com.example.test0530.okhttp.OKHttpProcessor;
import com.example.test0530.volley.VolleyProcessor;

public class Application extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //以前我们用Volley,后来要改成OKHTTP,我们在这里该一句代码就可以了。
        //但是单例初始化后,对象就不会释放,耦合度很高。
      //  HttpHelper.init(new VolleyProcessor(this));
        HttpHelper.init(new OKHttpProcessor());
    }
}

package com.example.test0530

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.test0530.httpprocessor.HttpCallBack
import com.example.test0530.httpprocessor.HttpHelper

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val url = ""
        val parames = null;
        HttpHelper.obtain().post(url,parames,object: HttpCallBack() {
            override fun sucess(t: JavaBean?) {
                TODO("Not yet implemented")
            }

        })
     }

}



package com.example.test0530;

public class JavaBean {
}

不过这种方法已经过时了,18年以前可以这么干。现在就有点out了。现在我们用第二种方式来实现。

HILT注入

专门针对Android的依赖注入框架,由Dagger2团队提供,我们看下如何使用
王学岗------隔离层的设计_第3张图片
先看下依赖的添加
项目gradle中

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    //新增
    id 'dagger.hilt.android.plugin'
    id 'kotlin-kapt'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.example.test0530"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    //新增
    implementation "com.google.dagger:hilt-android:2.41"
    kapt "com.google.dagger:hilt-android-compiler:2.41"
    //新增net
    implementation("com.android.volley:volley:1.2.1")
    implementation("com.squareup.okhttp3:okhttp:4.9.3")
    implementation("org.xutils:xutils:3.4.0")
    implementation 'com.google.code.gson:gson:2.9.0'
}

根gradle中

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.2.1' apply false
    id 'com.android.library' version '7.2.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
    //新增
    id 'com.google.dagger.hilt.android' version '2.41' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

我们现在用注解生成一个HttpObject对象

package com.example.test0530;

public class HttpObject {
    //网络访问对象,项目用什么由你自己决定
}

package com.example.test0530;


import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import dagger.hilt.InstallIn;
import dagger.hilt.android.components.ActivityComponent;
import dagger.hilt.android.scopes.ActivityScoped;

@InstallIn(ActivityComponent.class)//在哪个组件使用
@Module
public class HttpModele {
   // @Singleton //全局单例模式
    //@ActivityScoped//只在一个Activity里面单例模式
    @Provides
    public HttpObject getHttpObject(){
        //对象初始化......
        return new HttpObject();
    }
}

Application的配置

package com.example.test0530;

import dagger.hilt.android.HiltAndroidApp;

@HiltAndroidApp//这个注解必须在APPlication添加
public class MyApplication extends android.app.Application {
    @Override
    public void onCreate() {
        super.onCreate();

    }
}

package com.example.test0530;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import javax.inject.Inject;

import dagger.hilt.android.AndroidEntryPoint;

@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
    @Inject
    HttpObject httpObject;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //这里就可以使用httpObject对象了
    }
}

除此之外,hilt还支持接口注入

package com.example.test0530;

public interface TestInterface {
    void method();
}

package com.example.test0530;

import javax.inject.Inject;

public class TestClass implements TestInterface{
    //一定要写构造方法
    @Inject
    public TestClass(){}

    @Override
    public void method() {
     System.out.println("----------------");
    }
}

package com.example.test0530;

import dagger.Binds;
import dagger.Module;
import dagger.hilt.InstallIn;
import dagger.hilt.android.components.ActivityComponent;

@InstallIn(ActivityComponent.class)
@Module
public abstract class TestInterfaceModule {
    @Binds//绑定接口实现来
    public abstract TestInterface abc(TestClass testClass);
//    返回接口,参数为实现类
}

Application同上

下面我们看下怎么使用Hilt来做隔离层设计

package com.example.test0530;

import javax.inject.Inject;

import dagger.hilt.android.HiltAndroidApp;

@HiltAndroidApp//这个注解必须在APPlication添加
public class MyApplication extends android.app.Application {
    @BindVOlley
    @Inject
    IHttpProcessor iHttpProcessor;
    @Override
    public void onCreate() {
        super.onCreate();
    }

    public IHttpProcessor getiHttpProcessor() {
        return iHttpProcessor;
    }
}

package com.example.test0530;

import java.util.Map;

import javax.inject.Inject;

public class OKHttpProcessor implements IHttpProcessor{
    @Inject
    public OKHttpProcessor() {
    }



    @Override
    public void post(String url, Map params, ICallback callback) {

    }
}

package com.example.test0530;

import android.content.Context;

import java.util.Map;

import javax.inject.Inject;

import dagger.hilt.android.qualifiers.ApplicationContext;

public class VolleyProcessor implements IHttpProcessor{
    @Inject
    public VolleyProcessor(@ApplicationContext Context context) {
        //注入上下文
    }
    @Override
    public void post(String url, Map params, ICallback callback) {

    }
}

package com.example.test0530;

import javax.inject.Singleton;

import dagger.Binds;
import dagger.Module;
import dagger.hilt.InstallIn;
import dagger.hilt.components.SingletonComponent;

@Module
@InstallIn(SingletonComponent.class)//相当于旧版本的ApplicationComponent.class
public abstract class HttpProcessorModule {
    @BindOKHttp
    @Binds
    @Singleton //全局单例
    abstract IHttpProcessor bindOKHttpProcessor(OKHttpProcessor okHttpProcessor);
    @BindVOlley
    @Binds
    @Singleton //全局单例
    abstract IHttpProcessor bindVolleyProcessor(VolleyProcessor volleyProcessor);

}

package com.example.test0530;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface BindOKHttp {
}

package com.example.test0530;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface BindVOlley {
}

另外附kotlin中的用法

你可能感兴趣的:(移动架构,android)