王学岗OKHttp从简单到复杂

2018-11-02  本文已影响0人  王学岗

第一部分:快速使用

如果你对OkHttp比较熟悉了,完全可以跳过第一部分。

package com.example.okhttptest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {
    private String testUrl = "http://119.253.81.55/tkheal/";

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

    }

    public void getRequest(View view) {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(testUrl + "/rungroup/getRankForGroupUser ").build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
               Log.i("王迪迪",e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.i("王迪迪","成功");
                //response即是服务端给我们返回的对象
                String result = response.body().string();
                //因为response是一个流,所以我们需要关闭
                if (response.body() != null) {
                    response.body().close();
                }
            }
        });
    }
}

看下打印输出结果

11-01 19:34:23.617 15107-15187/com.example.okhttptest I/王迪迪: 成功

第二部分:Http协议简介

这一部分只是http相关的一些知识,如果你比较熟悉http协议,建议跳过这一部分。


1.png 1.png 1.png 1.png

request介绍


1.png

Response介绍


1.png

第三部分:Get请求


package com.example.okhttptest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {
    private String testUrl = "http://119.253.81.55/tkheal/";

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

    }

    public void getRequest(View view) {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder()
                .get()
//拼接请求参数
                .url(testUrl + "/rungroup/getRankForGroupUser?groupId=5&type=0&userId=3805&page=1&pageSize=5&token=c9e784425cdc9f7091e5980fd7870b5f")
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
               Log.i("王迪迪",e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.i("王迪迪","成功");
                //response即是服务端给我们返回的对象
                String result = response.body().string();
                Log.i("王迪迪","result:"+result);
                //因为response是一个流,所以我们需要关闭
                if (response.body() != null) {
                    response.body().close();
                }
            }
        });
    }
}

get请求我们可以直接在url地址后面添加参数。使用? &。

第四部分,post请求,使用form表单

首先我推荐一个post测试工具——postman 1.png

用户登陆,使用form表单


 private void loginWithForm(String name, String password) {
        OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
        //传入参数
        RequestBody body=new FormBody.Builder().add("username",name).add("password",password).build();
        final Request request=new Request.Builder()
                .url(testUrl)
                //声明post请求
                .post(body)
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){
                    String result=response.body().string();
                }
                //操作UI
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                    }
                });

            }
        });
        
    }

这是用phthon写成的服务端


1.png

第五部分,post请求,使用json数据

这是服务端


1.png

 private void loginWithjson(String name, String password) {
        OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
        JSONObject jsonObject=new JSONObject();
        try {
            jsonObject.put("username",name);
            jsonObject.put("password",password);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        String jsonParams=jsonObject.toString();
        RequestBody body=RequestBody.create(MediaType.parse("application/json;charset=utf-8"),jsonParams);
        final Request request=new Request.Builder()
                .url(testUrl2)
                //声明post请求
                .post(body)
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){
                    String result=response.body().string();
                }
                //操作UI
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                    }
                });

            }
        });
        
    }

第六部分,读取okhttp流下载文件

private void downloadFile() {
        Request request = new Request.Builder().url(testUrl).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
//文件下载要返回的不是一个字符串,而是一个流。我们读取服务器返回的流,然后再写入本地
                InputStream is = response.body().byteStream();
                File file = null;
                if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
                    file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"a.apk");
                } else {
                    file = new File(getCacheDir().getAbsolutePath(), "a.apk");
                }
                //获取文件的长度
                long total=response.body().contentLength();
                //当前读取的长度
                long sum=0;
                FileOutputStream fileOutputStream=new FileOutputStream(file);
                byte[] bytes=new byte[1024];
                int len=0;
                while((len=is.read(bytes))!=-1){
                    fileOutputStream.write(bytes);
                    sum=sum+len;
                    //这里可以使用handler message机制更新进度条,此处我略去,读者自己实现。
                    int progress = (int) ((float)sum / (float) total);

                }
            }
            //关闭流的操作此处略去
        });
    }

第七部分,拦截器下载文件

第一步:创建一个类继承ResponseBody

package com.example.okhttptest;

import android.support.annotation.Nullable;

import java.io.IOException;

import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

public class ProgressResponseBody extends ResponseBody {
    private ResponseBody responseBody;
    private ProgressListenner progressListenner;
    private BufferedSource bufferedSource;

    public ProgressResponseBody(ResponseBody responseBody, ProgressListenner progressListenner) {
        this.responseBody = responseBody;
        this.progressListenner = progressListenner;
    }

    @Nullable
    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }

    @Override
    public long contentLength() {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(getSourse(responseBody.source()));
        }
        return bufferedSource;
    }

    //Okio是OkHttp底层IO操作
    //如果我们不实现进度条,那么这里可以什么也不写。
    private Source getSourse(Source source) {
        return new ForwardingSource(source) {
            long totalSize = 0l;
            long sum = 0;

            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                long len = super.read(sink, byteCount);
                if (totalSize == 0) {
                    totalSize = contentLength();
                }
                sum += (len == -1 ? 0 : len);
                int progress = (int) ((float) sum / (float) totalSize);
                if (len == -1) {
                    progressListenner.onDone(totalSize);
                } else {
                    progressListenner.onProgress(progress);
                }
                return len;
            }
        };
    }

    public interface ProgressListenner {
        void onProgress(int progress);

        void onDone(long totalSize);
    }
}


package com.example.okhttptest;

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {
    private String testUrl = "http://119.253.81.55/tkheal/";
    private ProgressBar progressBar;
    private OkHttpClient okHttpClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progressBar = findViewById(R.id.progressbar);
        okHttpClient = new OkHttpClient();
        initOkHttpClient();
    }

    public void callNet(View view) {
        Request request = new Request.Builder().url(testUrl).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
//文件下载要返回的不是一个字符串,而是一个流。我们读取服务器返回的流,然后再写入本地
                InputStream is = response.body().byteStream();
                File file = null;
                if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
                    file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "a.apk");
                } else {
                    file = new File(getCacheDir().getAbsolutePath(), "a.apk");
                }
                //当前读取的长度
                FileOutputStream fileOutputStream = new FileOutputStream(file);
                byte[] bytes = new byte[1024];
                int len = 0;
                while ((len = is.read(bytes)) != -1) {
                    fileOutputStream.write(bytes);
                }
            }
            //关闭流的操作此处略去
        });
    }

    private void initOkHttpClient() {
        okHttpClient = new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Response response = chain.proceed(chain.request());

                return response.newBuilder().body(new ProgressResponseBody(response.body(), new Pg())).build();
            }
        }).build();
    }

    private class Pg implements ProgressResponseBody.ProgressListenner {

        @Override
        public void onProgress(final int progress) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progressBar.setProgress(progress);
                }
            });
        }

        @Override
        public void onDone(long totalSize) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_LONG).show();
                }
            });
        }
    }
}

第六部分:上传文件

private void uploadFele(){
        OkHttpClient okHttpClient=new OkHttpClient.Builder().build();
        //图片数据类型
        // png : image/png
        //jpg : image/jpeg
        //gif : imge/gif
        //其它数据类型
//        json : application/json
//        xml : application/xml
        RequestBody requestBody=RequestBody.create(MediaType.parse("image.jpeg"),new File("/scard/a.jpg"));
        Request request=new Request.Builder()
                .url(testUrl)
                .post(requestBody)
                .build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });
    }

第七部分:上传文件和文字

在OkHttp中实现上传文件是MultipartBuilder,比如我们现在需要更改用户的信息。用户更改了姓名和头像,头像是一个文件,我们这里就需要上传文件。我们上传的信息包括文件和表单。


  private void uploadFileAndString() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        File file = new File("/scard/a.png");
        //"application/octet-stream":传进去2进制流数据,流数据就包括文件和表单
        RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        MultipartBody multipartBody = new MultipartBody.Builder()
                //设置为form表单的类型
                .setType(MultipartBody.FORM)
                //name 和值
                .addFormDataPart("name", "wangdidi")
                //传入image字段,取名为"test.png"
                .addFormDataPart("image", "test.png", fileBody).build();
        Request request = new Request.Builder()
                .post(multipartBody)
                .url(testUrl).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });
    }
上一篇下一篇

猜你喜欢

热点阅读