网络请求框架OkHttp基础用法

本文详细介绍使用OkHttp进行网络请求的各种方式,并提供了一个简单的封装类以减少代码重复,提高开发效率。

导包

在module下的build.gradle文件中添加代码

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"

    repositories {
        mavenCentral() // jcenter() works as well because it pulls from Maven Central
    }
    defaultConfig {
        applicationId "com.alearningwu.sample"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'

    **compile 'com.squareup.okhttp3:okhttp:3.6.0'**
}

使用方法

定义一些后面将统一用到的变量

    public static String targetIp = "http://192.168.191.1:8080/" +
            "okhttp/" +
            "login.action?" +
            "username=99&password=110";//get方法参数放在请求链接中
  public static String mBaseUrl="http://192.168.191.1:8080/okhttp/";//post方法使用的请求ip

    private TextView textView;
    private ImageView imageView;
    private OkHttpClient okHttpClient;
  1. doGet()(用户名,密码什么的)
 public void doGet(View view)throws IOException{
  //1.构造request
        Request.Builder builder=new Request.Builder();//构造者设计模式
        Request request=builder.
                get().
                url(targetIp).//自定义的targetIp变量
                build();
        //3.将request封装成call
        Call call=okHttpClient.newCall(request);
        //4.执行call
        //Response response=call.execute();同步方法
        /*
        异步方法
        * */

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                L.e("onFailure:" + e.getMessage());//自定义打印日志类就不说了
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                L.e("onResponse:");
                final String res = response.body().string();
                L.e(res);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(res);//将返回内容显示在TextView中
                    }
                });//UI线程  因为callback在子线程中,更新UI需要在主线程(UI线程)中
            }
        });
        }

后台相应接收前台doGet()方法


    public String login() throws IOException{
        System.out.println(username+","+password);
        System.out.println(ServletActionContext.getRequest().getSession().toString());
        HttpServletResponse response=ServletActionContext.getResponse();
        PrintWriter writer =response.getWriter();
        writer.write("login success!");//返回数据给前台“login success!”
        writer.flush();
        return null;
    }

2.doPost()上传表单数据

  public void doPost(View view){
        //2.构造request
        //2.1 构造FormBody(post)表单
        FormBody formbody=new FormBody.Builder()//建post方法发送信息的表单
                .add("username","wu")
                .add("password","2017")
                .build();
        //2.1构造request
        Request.Builder builder=new Request.Builder();
        Request request=builder.
                post(formbody).
                url(mBaseUrl+"login.action").
                build();
        //3.将request封装成call
        Call call=okHttpClient.newCall(request);
        //4.执行call
        //Response response=call.execute();同步方法
        /*
        异步方法
        * */

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                L.e("onFailure:" + e.getMessage());
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                L.e("onResponse:");
                final String res = response.body().string();
                L.e(res);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(res);
                    }
                });
            }
        });
        }

大家是不是发现了什么

第3步:将request封装成call
第4步:执行call

在doGet()方法和doPost()方法中都有出现,有一句话,程序猿都是懒的,咱能封装就尽量要封装

于是我们可以把3.4步封装成函数executeRequest(Request request)

private void executeRequest(Request request) {
        //3.将request封装成call
        Call call=okHttpClient.newCall(request);
        //4.执行call
        //Response response=call.execute();同步方法
        /*
        异步方法
        * */

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                L.e("onFailure:" + e.getMessage());
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                L.e("onResponse:");
                final String res = response.body().string();
                L.e(res);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText(res);
                    }
                });
            }
        });
    }

之前出现这段代码的地方可以直接替换,传入一个Request类型变量即可
3.doPostString()上传字符串,例如json格式字符串

    public void doPostString(View view){

        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;chaset=utf-8"),
                "{username:wuzi,password:1996}");
              Request.Builder builder=new Request.Builder();
        Request request=builder
                post(requestBody ).
                url(mBaseUrl+"postString.action").
                build();
        //3.将request封装成call
        //4.执行call
        executeRequest(request);
    }

后台相应接收代码

    public String postString() throws IOException{
        HttpServletRequest request=ServletActionContext.getRequest();
        ServletInputStream isInputStream=request.getInputStream();
        StringBuilder sbBuilder=new StringBuilder();
        int len=0;
        byte[] buf =new byte[1024];
        while((len=isInputStream.read(buf))!=-1){
            sbBuilder.append(new String(buf,0,len));
        }
        System.out.println(sbBuilder.toString());
        isInputStream.close();
        return null;
    }

4.doPostFile()上传文件

  public void doPostFile(View view){
  File file =new File(Environment.getExternalStorageDirectory(),"banner2.jpg");//获得手机目录第一层
        if (!file.exists()){
            L.e(file.getAbsolutePath()+"  not exist!");
            return;
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/octec-steam"),//不知道发送的数据MIME格式可用这字符串代替
                file);
        Request.Builder builder=new Request.Builder();
        Request request=builder.
                post(requestBody).
                url(mBaseUrl+"postFile.action").
                build();
        executeRequest(request);
        }

后台相应接收

    public String postFile() throws IOException{
        HttpServletRequest request=ServletActionContext.getRequest();
        ServletInputStream isInputStream=request.getInputStream();

        String dirString=ServletActionContext.getServletContext().getRealPath("/file2");
        File file=new File(dirString,"banner2.jpg");
        FileOutputStream fo=new FileOutputStream(file);
        int len=0;
        byte[] buf =new byte[1024];
        while((len=isInputStream.read(buf))!=-1){//isInputStream输入流读操作读到“()”内容中
            fo.write(buf,0,len);//fo输出流写操作写入与fo绑定的文件中
        }
        System.out.println("postfile");
        fo.flush();
        fo.close();
        return null;
    }

5.doUpload()上传文件携带参数

public void doUpload(View view){
        File file =new File(Environment.getExternalStorageDirectory(),"banner2.jpg");
        if (!file.exists()){
            L.e(file.getAbsolutePath()+"  not exist!");
            return;
        }
        RequestBody requestBodyfile = RequestBody.create(MediaType.parse("application/octec-steam"), file);
        //MultiPartBuilder已被MultiPartBody替代
        //MultipartBody extends RequestBody
        MultipartBody requestBody=new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("username","wu")
                .addFormDataPart("password","1996")
                .addFormDataPart("mphoto","banner2.jpg"
                        ,requestBodyfile).build();

        Request.Builder builder=new Request.Builder();
        Request request=builder.
                post(requestBody).
                url(mBaseUrl+"uploadInfo.action").
                build();
        executeRequest(request);
    }

后台相应接收

    public String uploadInfo() throws IOException{
        System.out.print(username+","+mphotoFileName+"\n");
        if(mphoto==null){
            System.out.print(mphotoContentType+mphotoFileName+"no exist");
        }
        if(mphoto!=null){
        String dir=ServletActionContext.getServletContext().getRealPath("/file2");//文件位置在运行哪个服务器就在他存储目录下file2
        //E:\study\JAVA\MyEclipse\MyeclipseProject\.metadata\.me_tcat\webapps\okhttp\file2
        //或下载的tomcat位置
        File file=new File(dir,mphotoFileName);
         FileUtils.copyFile(mphoto,file);//把mPhoto文件copy在file文件目录下
        }
        return null;
    }

特别说明下这种方法,本人觉得此方法是比较简便的传图方法,后台获取图片也相对容易,[键值对]方式需要名字相同
6.doDownLoad()下载文件

 public void doDownload(View view){
        Request.Builder builder=new Request.Builder();
        final Request request=builder.
                get().
                url(mBaseUrl+"file2/banner2.jpg").//目标文件地址
                build();
        Call call=okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                L.e("onFailure:" + e.getMessage());
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final InputStream is = response.body().byteStream();//文件下载,流方式
                /*
                * 下载文件事图片及其显示方法
                * */
                final Bitmap bitmap=BitmapFactory.decodeStream(is);//图片解码字节流
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        imageView.setImageBitmap(bitmap);
                    }
                });
                /*
                * 下载文件及其储存方法
                * */
                FileOutputStream fos=new FileOutputStream
                        (new File(Environment.getExternalStorageDirectory(),"bannerdownload.jpg"));
                int len=0;
                byte[] buf=new byte[1024];
                while((len=is.read(buf))!=-1){//什么都读不到返回-1 //循环读取会自动read到的位置++
                    fos.write(buf,0,len);
                }
                fos.flush();
                fos.close();
                is.close();
            }
        });
    }

大家发现没有,这几个函数还是有许多的重复代码
OkHttp要交互只需要requestbody->request->call

于是我们可以再封装下OkHttp

这是我自己的封装方式,有点菜

封装成类 OkHttpEncapsulation

public class OkHttpEncapsulation {
    public static String mBaseUrl="http://192.168.191.1:8080/okhttp/";
    public OkHttpClient okHttpClient=new OkHttpClient();
    private RequestBody requestBody;
    private String targetFun;

    public  OkHttpEncapsulation setRequestBody(RequestBody requestBody){
        this.requestBody=requestBody;
        return this;
    }

    public OkHttpEncapsulation setTargetFun(String targetFun){
        this.targetFun=targetFun;
        return this;
    }

    public void execute(Callback callback){
        //创建request
        if (requestBody!=null){
            Request.Builder builder=new Request.Builder();
            Request request=builder.
                    post(requestBody).
                    url(mBaseUrl+targetFun).
                    build();
            //call请求
            Call call=okHttpClient.newCall(request);
            call.enqueue(callback);
        }
        else {//get方法不需要requestBody
            Request.Builder builder=new Request.Builder();
            Request request=builder.
                    get().
                    url(mBaseUrl+targetFun).
                    build();
            Call call=okHttpClient.newCall(request);
            call.enqueue(callback);
        }
    }
}

使用封装类方法:
*使用方法
new OkHttpEncapsulation()
.setRequestBody(RequestBody类型)
.setTargetFun(“目标后台函数映射名”)
.execute(Callback类型)

如doPostString()函数可写成

   public void doPostString(View view){

        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;chaset=utf-8"),
                "{username:wuzi,password:1996}");
        new OkHttpEncapsulation()
                .setRequestBody(requestBody)
                .setTargetFun("postString.action")
                .execute(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                    }
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                    }
                });
    }

相较之前还是简洁一点的,代码能简洁一点都是好的嘛

参考资料 慕课网视频
感谢hyman老师
作者:吴梓轩:原文地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值