网络请求框架OkHttp基础用法

来源:互联网 发布:js concat连接字符串 编辑:程序博客网 时间:2024/06/05 06:23

导包

在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老师
作者:吴梓轩:原文地址

原创粉丝点击