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

相較之前還是簡潔一點的,代碼能簡潔一點都是好的嘛

參考資料 慕課網視頻

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