【Android】网络请求框架OkHttp基础用法

导包

在build.gradle文件中添加代码

dependencies {
	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 {
                    }
                });
    }

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

参考资料 慕课网视频

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章