网络框架Retrofit(一)--了解封装的Okhttp

对于网络框架,一直都处于一知半解的状态,所以除了基本的应用之外,怎么延伸都不知从何下手,于是,我就抽时间进一步的去了解:
众所周知,retrofit是对okhttp进行封装,而retrofit只是简单的去使用okhttp的框架,但是想更深入了解网络请求,建议还是先从okhttp进行了解,所以下面我会先去了解okhttp:
1、导入okhttp:
访问https://github.com/square/okhttp

image.png

获取最新版本的okhttp,进入项目的build.gradle添加依赖

2、根据官网的提示去使用okhttp


image.png

发现出现这样的报错,那是因为最新的okhttp要求的最低版本是21以及jdk版本为8.0,解决方案如下:


image.png

顺便说下怎么找到对应的配置方法,可以在官网里面看到作者写的android-text文档,然后点开他的build.gradle,就可以看到作者是怎么配置,那样就可以拿到最新的配置。

还有需要说明下:因为android9.0及以上的版本会默认不予许直接方法http的,因为官网觉得这样不安全,所以需要做如下的配置:
①访问官网:
https://developer.android.com/training/articles/security-config

image.png

然后往下面拉的话,就会看到各种证书的添加方法,我就直接上我的吧:

<network-security-config>
    <base-config cleartextTrafficPermitted="true">//支持访问HTTP协议的
        <trust-anchors>
            <certificates src="system" />//信任系统里面内置的CA证书
            <certificates src="user" />//信任用户自己安装的证书,这个是为了抓包软件可以正常工作,记得还要安装抓包的插件
        </trust-anchors>
    </base-config>
</network-security-config>

3、添加okhttp拦截器,打印我们构造出来的请求和已接收到结果,在官网中okhttp-logging-interceptor这个文档中就可以看到怎添加使用
然后下面就直接上代码了,代码细节都写在里面,好好看哈:
build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.retrofit"
        minSdkVersion 21
        targetSdkVersion 29
        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
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation("com.squareup.okhttp3:okhttp:4.8.1")
    implementation("com.squareup.okhttp3:logging-interceptor:4.8.1")
}

INetCallBack

public interface INetCallBack {
    void onSuccess(String response);

    void onFailed(Throwable ex);
}

OkhttpUtils

public class OkhttpUtils {
    private OkHttpClient client;
    private OkhttpUtils(){
        //添加拦截器
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.d("jeffrey",message);
            }
        });
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
         client = new OkHttpClient.Builder()
                 .addInterceptor(new AuthIntercetor())
                .addInterceptor(logging)
                .build();
    }
    private static OkhttpUtils sInstance=new OkhttpUtils();
    //对外公开一个获取方法
    public  static  OkhttpUtils getInstance(){
        return sInstance;
    }
    private Handler mUiHandler=new Handler(Looper.getMainLooper());

/*    //同步请求
    public String doGet(String url){

        try {
            //1、构造OkHttpClient对象;
            OkHttpClient client=new OkHttpClient();
            //2.通过Request.Builder()去构造Request对象;
            Request request=new Request.Builder()
                    .url(url)
                    .build();
            //3、通过Request对象去拿到Call对象;
            Call call=client.newCall(request);

            //4.通过Call对象执行去拿到Response对象
            Response response = call.execute();
            return response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }*/
//异步请求
    public void doGet(String url,HashMap<String,String> headers,INetCallBack callBack){
        //添加请求头信息
        Request.Builder builder=new Request.Builder();
        if (headers !=null){
            for (String key:headers.keySet()){
                builder.addHeader(key,headers.get(key));
            }
        }
        Request request=builder
                .url(url)
                .build();
        executeRequest(callBack, request);
    }



    //注意下POST请求的参数不是接到url后面的,所以需要参数2
    public void doPost(String url, HashMap<String,String> headers,HashMap<String,String> params,INetCallBack callBack){
        FormBody.Builder formBodyBuilder=new FormBody.Builder();
        if (params!=null){
            for (String param:params.keySet()){
                formBodyBuilder.add(param,params.get(param));
            }
        }
        Request.Builder requsetBuilder=new Request.Builder();
        if (headers !=null){
            for (String key:headers.keySet()){
                requsetBuilder.addHeader(key,headers.get(key));
            }
        }
        Request request = requsetBuilder
                .url(url)
                .post(formBodyBuilder.build())
                .build();
        executeRequest(callBack, request);
    }

    public void doPostMultiPart(String url,HashMap<String,String> headers, HashMap<String,String> params,INetCallBack callBack){
        MultipartBody.Builder multipartBodyBuilder=new MultipartBody.Builder();
        multipartBodyBuilder.setType(MultipartBody.FORM);
        if (params!=null){
            for (String param:params.keySet()){
                multipartBodyBuilder.addFormDataPart(param,params.get(param));
            }
        }
        Request.Builder requsetBuilder=new Request.Builder();
        if (headers !=null){
            for (String key:headers.keySet()){
                requsetBuilder.addHeader(key,headers.get(key));
            }
        }
        Request request=requsetBuilder
                .url(url)
                .post(multipartBodyBuilder.build())
                .build();
        executeRequest(callBack, request);
    }

    public void doPostJson(String url,HashMap<String,String> headers,String jsonStr,INetCallBack callBack){
        //MediaType代表jSon字符串所含的格式
        MediaType jsonMediaType=MediaType.get("application/json");
        RequestBody requestBody=RequestBody.create(jsonStr,jsonMediaType);
        Request.Builder requsetBuilder=new Request.Builder();
        if (headers !=null){
            for (String key:headers.keySet()){
                requsetBuilder.addHeader(key,headers.get(key));
            }
        }
        Request request=requsetBuilder
                .url(url)
                .post(requestBody)
                .build();
        executeRequest(callBack, request);
    }

    private void executeRequest(INetCallBack callBack, Request request) {
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                mUiHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.onFailed(e);
                    }
                });
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                //注意response.body().string()也是耗时操作,所以要拿出来
                String respStr = null;
                try {
                    respStr = response.body().string();
                } catch (IOException e) {
                    mUiHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            callBack.onFailed(e);
                        }
                    });
                    return;
                }

                String finalRespStr = respStr;
                mUiHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        callBack.onSuccess(finalRespStr);
                    }
                });

            }
        });
    }
}

AuthIntercetor

public class AuthIntercetor implements Interceptor {
    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {

        Request originRequest=chain.request();
        Request newRequest=originRequest.newBuilder()
                .addHeader("author","jeffrey")
                .build();
        return chain.proceed(newRequest);
    }
}

MainActivity

public class MainActivity extends AppCompatActivity {
    private Button mBtnGet,mBtnPost,mBtnPostMultipart,mBtnPostJson;
    private TextView mTvContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initViews();
        initEvents();
    }

    private void initEvents() {
        mBtnGet.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                HashMap<String,String> headers=new HashMap<>();
                headers.put("author_headr","jeffer");
                OkhttpUtils.getInstance()
                        .doGet("",headers, new INetCallBack() {
                            @Override
                            public void onSuccess(String response) {
                                mTvContent.setText(response);
                            }

                            @Override
                            public void onFailed(Throwable ex) {
                                Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
                            }
                        });
               /* //发送网络请求
                new Thread(){
                    @Override
                    public void run() {
                        super.run();
                        String content=OkhttpUtils.getInstance().
                                doGet("");
                        mUiHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                mTvContent.setText(content);
                            }
                        });
                    }
                }.start();*/
            }
        });
        mBtnPost.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                HashMap<String,String> headers=new HashMap<>();
                headers.put("author_headr","jeffer");
                HashMap<String,String> params=new HashMap<>();
                params.put("author","jeffrey");
                params.put("abc","xyz");
                OkhttpUtils.getInstance().doPost("", headers,null, new INetCallBack() {
                    @Override
                    public void onSuccess(String response) {
                        mTvContent.setText(response);
                    }

                    @Override
                    public void onFailed(Throwable ex) {
                        Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
        mBtnPostMultipart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                HashMap<String,String> headers=new HashMap<>();
                headers.put("author_headr","jeffer");
                HashMap<String,String> params=new HashMap<>();
                params.put("author","jeffrey");
                params.put("abc","xyz");
                OkhttpUtils.getInstance().doPostMultiPart("", headers,null, new INetCallBack() {
                    @Override
                    public void onSuccess(String response) {
                        mTvContent.setText(response);
                    }

                    @Override
                    public void onFailed(Throwable ex) {
                        Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
        mBtnPostJson.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                HashMap<String,String> headers=new HashMap<>();
                headers.put("author_headr","jeffer");
                OkhttpUtils.getInstance().doPostJson("", headers,"{\"name\":\"jeffrey\",\"age\":18}", new INetCallBack() {
                    @Override
                    public void onSuccess(String response) {
                        mTvContent.setText(response);
                    }
                    @Override
                    public void onFailed(Throwable ex) {
                        Toast.makeText(MainActivity.this,"网络发生错误",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

    private void initViews() {
        mBtnGet=findViewById(R.id.bt_get);
        mTvContent=findViewById(R.id.tv_content);
        mBtnPost=findViewById(R.id.bt_post);
        mBtnPostMultipart=findViewById(R.id.bt_post_multipart);
        mBtnPost=findViewById(R.id.bt_post_json);
    }
}

这里我小结一下:
1、其实从开头就开始说如何从文档中读取使用方法,是建议大家真的多去官网看文档,因为很多时候看别人的文章,都是别人总结好的东西,很难去了解所用的框架后面怎么去拓展,所以,最好还是以官网的文档使用为准会比较好;
2、okttp的使用步骤其实就是:
①、构造OkHttpClient对象;
②、通过Request.Builder()去构造Request对象;
③、通过Request对象去拿到Call对象;
④、通过Call对象执行去拿到Response对象
好啦!下一章,我会说下Retrofit的用法,然后进行对比,尽量让大家可以一眼就看透他们的对比性,觉得写得可以话,请关注和点赞哦!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342