Android 中Okhttp的同步请求与异步请求详解

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
点击跳转到网站

前言: 在过去,Android上发送HTTP请求一般有两种方式:HttpURLConnection和HttpClient,由于HttpClient存在的API数量过多,扩展困难等缺点,在Android6.0系统中,HttpClient的功能被完全移除了。
而 OkHttp 是由Square公司开发的,OkHttp在接口封装上做的简单易用,比起原生的HttpURLConnection,可以说是有过之而无不及,现在已经成为了广大Android开发者首选的网络通信库。

使用HttpURLConnection进行网络请求详解请看这篇文章

同步请求与异步请求的概念:

简单地说,同步就是发出一个请求后什么事都不做,一直等待请求返回后才会继续做事;异步就是发出请求后继续去做其他事,这个请求处理完成后会通知你,这时候就可以处理这个回应了。

写了个Demo去理解Okhttp中的get同步请求与异步请求,和post同步请求与异步请求
Android 中Okhttp的同步请求与异步请求详解_第1张图片
1.get的同步请求,其中的讲解,已经在代码中注释了出来。

//get同步请求
    public void getSync(View view) {
        //在Android 中完成网络请求必须在子线程中完成
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient okHttpClient = new OkHttpClient();
                Request request = new Request.Builder().url("http://www.httpbin.org/get?a=1&b=2").build();
                //准备好请求的Code对象
                Call call = okHttpClient.newCall(request);
                try {
                    //同步请求要创建子线程,是因为execute()方法,会阻塞后面代码的执行
                    //只有执行了execute方法之后,得到了服务器的响应response之后,才会执行后面的代码
                    //所以同步请求要在子线程中完成
                    Response response = call.execute();
                    //把服务器给我们响应的字符串数据打印出来
                    Log.i(TAG,"getSync:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

2.get异步请求:

//get的异步请求
    public void getAsync(View view) {
        //定义okhttp对象
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url("http://www.httpbin.org/get?a=1&b=2").build();
        Call call = okHttpClient.newCall(request);
        //异步请求:不用创建子线程
        //enqueue()并不会阻塞代码的执行,不需要与服务器请求完成之后,才会执行后面的代码
        //而且enqueue内部会为我们创建子线程
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
             Log.i("TAG", "onResponse: " + (Looper.getMainLooper().getThread() == Thread.currentThread()));//为false 表示这是在子线程,需要切换到主线程才能操作UI
                if (response.isSuccessful()){
                    Log.i(TAG,"getAsync:"+response.body().string());
                }
            }
        });

    }

3.post同步请求:

 //post同步请求
    public void postSync(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient okHttpClient = new OkHttpClient();
                //post请求规定,把参数放在请求体里面,用form表单的方式来添加我们的请求体
                FormBody formBody = new FormBody.Builder().add("a", "10000").add("b", "15000").build();
                Request request = new Request.Builder().url("http://www.httpbin.org/post")
                        .post(formBody)
                        .build();
                Call call = okHttpClient.newCall(request);
                try {
                    Response response = call.execute();
                    Log.i(TAG,"postSync:"+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

4.post的异步请求:

 //post异步请求
    public void postAsync(View view) {
        OkHttpClient okHttpClient = new OkHttpClient();
        FormBody formBody = new FormBody.Builder().add("a", "1000").add("b", "2000").build();
        Request request = new Request.Builder().url("http://www.httpbin.org/post")
                .post(formBody)
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {

            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
              Log.i("TAG", "onResponse: " + (Looper.getMainLooper().getThread() == Thread.currentThread()));//为false 表示这是在子线程,需要切换到主线程才能操作UI
                if (response.isSuccessful()){
                    Log.i(TAG,"postAsync:"+response.body().string());
                }
            }
        });
    }

上面用到的http服务器是公用的,需要的拿去用:地址www.httpbin.org/

新增:

一、 使用OkHttp 上传图片到服务器

private void UpLoadImage(String pictPath, String fileName) { //参数1:图片路径 参数2:图片名称
        new Thread(new Runnable() {
            @Override
            public void run() {
                String url = "具体的URL地址";
                //定义OkHttp
                OkHttpClient okHttpClient = new OkHttpClient();
                MediaType JSON = MediaType.parse("multipart/form-data");
                //定义请求体
                RequestBody body = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("file", fileName,
                                RequestBody.create(JSON, new File(pictPath)))//addFormDataPart方法的第一个参数是key值,第二个参数是上传文件的名字,第三个参数是需要上传的文件
                        .build();
                try {
                    //执行OkHttp
                    Request request = new Request.Builder()
                            .post(body)
                            .url(url)
                            .build();
                    Response response = okHttpClient.newCall(request).execute();
                    String ss = response.body().string();
                    ResultMsg resultMsg = new Gson().fromJson(ss, ResultMsg.class);
                    if (resultMsg.Result.equals("1")) {
                        Looper.prepare();
                        Toast.makeText(ChangeInformationActivity.this, "图片上传成功!", Toast.LENGTH_SHORT).show();
                        Looper.loop();
                    } else {
                        Looper.prepare();
                        Toast.makeText(ChangeInformationActivity.this, resultMsg.Message, Toast.LENGTH_SHORT).show();
                        Looper.loop();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }).start();
    }

二、 使用OkHttp 通过GET异步请求从服务器获取图片,下载到手机图库中,代码如下:

btn_save_image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //申请读取或修改存储卡的权限
                //对于共享区间写入的权限,在API29 Android系统10之前是需要申请的
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                    if (ContextCompat.checkSelfPermission(OkHttpActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                        ActivityCompat.requestPermissions(OkHttpActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                    } else {
                        SaveImage();
                    }
                } else {
                    SaveImage();
                }
            }
        });

SaveImage()方法实现从服务器下载一张图片,保存到图库中的功能:

        //定义OkHttp
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder()
                .url("https://cdn.pixabay.com/photo/2021/12/13/15/14/flowers-6868494_960_720.jpg")
                .build();

        Call call = okHttpClient.newCall(request);
        //进行GET的异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) { //没有网络的情况下,会回调这个方法
                Log.e(TAG, "onFailure: " + "失败");
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            	//当前就是子线程所以不用再开启子线程了
                InputStream inputStream = response.body().byteStream();
                //之后包装成处理流,提高流的读取
                BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
                BufferedOutputStream bufferedOutputStream = null;
                try {
                    //保存到图库的URI
                    Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
                    OutputStream outputStream = getContentResolver().openOutputStream(uri);
                    bufferedOutputStream = new BufferedOutputStream(outputStream);
                    //定义每次读取的字节数
                    byte[] buffer = new byte[1024 * 8];
                    int len;
                    int length = 0;
                    while ((len = bufferedInputStream.read(buffer)) != -1) {
                        bufferedOutputStream.write(buffer, 0, len);
                        length += len;
                    }
                    Log.i(TAG, "length: " + length);
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (bufferedOutputStream != null) {
                            bufferedOutputStream.close();
                        }
                        if (bufferedInputStream != null) {
                            bufferedInputStream.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

以上就是Okhttp框架的简单实用~,如有不当之处,还望各位网友加以指正!

你可能感兴趣的:(Android基础笔记,android,Okhttp,post,get)