美文网首页Android开发Android知识Android开发
Android框架学习笔记01Okhttp框架

Android框架学习笔记01Okhttp框架

作者: 张文文同学 | 来源:发表于2016-09-19 15:14 被阅读376次

    Google在Android6.0之后就删除了HttpClient相关的API,使用HttpUrlConnection代替,在Android开发中,网络访问是必不可少的,网络上也有很多网络操作的框架,这一篇,我们介绍一下网络上非常火的一个网络框架——Okhttp框架。

    概述

    Okhttp现在已经出到3.4.1版本,主要包含的功能有:

    • 一般的get请求

    • 一般的post请求

    • 基于Http的文件上传

    • 文件下载

    • 加载图片

    • 支持请求回调,直接返回对象、对象集合

    • 支持session的保持

    下面我们介绍一下Okhttp的简单使用:

    使用

    使用Okhttp需要在项目的gradle文件中导入包,直接添加如下代码:

     compile 'com.squareup.okhttp3:okhttp:3.4.1'
    

    不过建议先去okhttp的github上查看最新的版本,okhttp的github地址是:https://github.com/square/okhttp

    使用Eclipse的话需要下载相应的JAR包,也可以到上述地址下载。

    还有需要在清单文件中添加联网的权限

     <uses-permission android:name="android.permission.INTERNET"/>
    

    完成准备工作之后,我们就而已开始使用这个网络框架了,下面我们通过具体的例子实现以下okhttp的各种功能:

    实现异步GET请求

         //异步get请求
        findViewById(R.id.tv_async_get).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OkHttpClient okHttpClient = new OkHttpClient();
                Request.Builder builder = new Request.Builder();
                Request request = builder.url("http://blog.csdn.net/lmj623565791/article/details/49734867").method("GET", null).build();
                Call call = okHttpClient.newCall(request);
                //回调监听
                call.enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "异步get请求失败", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                    //    if (response.cacheResponse() != null) {
                    //  String str = response.cacheResponse().toString();
                    //     Log.i(TAG, "onResponse" + str);
                    //   } else {
                    //   String str = response.networkResponse().toString();
                    //   Log.i(TAG, "onResponse" + str);
                    //   }
    
                        Log.i(TAG, "===============================================================================");
                        String str = response.body().string();
                        Log.i(TAG, "onResponse" + str);
                        Log.i(TAG, "===============================================================================");
    
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "异步get请求成功", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                });
    
            }
        });
    

    这里就是构建一个请求回调,不过回调不是在主线程,所以不能直接更新UI

    实现同步GET请求

        //同步get请求
        findViewById(R.id.tv_sync_get).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
    
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        OkHttpClient okHttpClient = new OkHttpClient();
                        Request.Builder builder = new Request.Builder();
                        Request request = builder.url("http://www.baidu.com").method("GET", null).build();
                        Call call = okHttpClient.newCall(request);
                        try {
                            Response response = call.execute();
                            if (response.isSuccessful()) {
    
                                Log.i(TAG, "=======================================================");
                                Log.i(TAG, "run" + response.body().string());
                                Log.i(TAG, "=======================================================");
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.i(TAG, "同步get请求成功");
                                        Toast.makeText(MainActivity.this, "同步get请求成功", Toast.LENGTH_SHORT).show();
                                    }
                                });
                            } else {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.i(TAG, "同步get请求失败");
                                        Toast.makeText(MainActivity.this, "同步get请求失败", Toast.LENGTH_SHORT).show();
                                    }
                                });
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
    
                    }
                }).start();
    
            }
        });
    

    同步GET请求和异步GET请求最大的区别就是调用不同的方法,同步调用的是execute,而异步调用的是enqueue,网络请求不能主线程中。

    实现异步POST请求

    客户端代码:

         //异步post请求
        findViewById(R.id.tv_async_post).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OkHttpClient okHttpClient = new OkHttpClient();
                RequestBody formBody = new FormBody.Builder().add("username", "zhangsan")
                        .add("password", "zhangsan").build();
                Request resuest = new Request.Builder().post(formBody).url("http://192.168.0.218:8080/sayHello").build();
                Call call = okHttpClient.newCall(resuest);
                call.enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "服务器无法连接", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "post请求成功", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                });
            }
        });
    

    服务器端:

    服务器端我是用Intelij IDEA2016写的,就是简单实现上传两个字符串而已,代码也非常简单。

    实现异步下载文件

         //异步下载文件
        findViewById(R.id.tv_async_download_file).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OkHttpClient okHttpClient = new OkHttpClient();
                Request request = new Request.Builder().url("http://192.168.0.218:8080/okhttp-3.4.1.jar").build();
                okHttpClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "下载失败,请稍后重试", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        InputStream inputStream = response.body().byteStream();
                        FileOutputStream fileOutputStream = null;
                        fileOutputStream = new FileOutputStream(new File("/sdcard/okhttp-3.4.1.jar"));
                        byte[] bytes = new byte[1024];
                        int len = 0;
                        while ((len = inputStream.read(bytes)) != -1) {
                            fileOutputStream.write(bytes, 0, len);
                        }
                        fileOutputStream.flush();
                        Log.i(TAG, "onResponse----->>文件下载成功");
    
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "文件下载成功", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                });
    
            }
        });
    

    实现的效果如下:

    实现异步上传文件

             //异步上传文件
        findViewById(R.id.tv_async_upload_file).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MediaType mime = MediaType.parse("application/java-archive;charset=utf-8");
                String url = "http://192.168.0.218:8080/upload";
                OkHttpClient okHttpClient = new OkHttpClient();
                File file = new File("/sdcard/okhttp-3.4.1.jar");
                Request request = new Request.Builder().url(url).post(RequestBody.create(mime, file)).build();
                okHttpClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Log.i(TAG, "onResponse---->>上传失败");
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "文件上传失败", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
    
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        Log.i(TAG, "onResponse---->>上传成功");
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "文件上传成功", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                });
            }
        });
    

    文件上传需要用服务器接收,这里我是自己写一个简单的Servlet去接收的,实际开发肯定会有服务器接收的。这里需要注意的是需要设置文件的MIME类型,如果不知道相应后缀名的文件的MIME类型,可以去这里查看一下:http://www.cnblogs.com/linyijia/p/5466317.html

    请求超时设置

    与前面版本不同的是,3.0之后就不再允许直接通过OkhttpClient设置超时了,而是通过OkHttpClient.Builder设置,设置好之后我们可以直接通过builder.build获取到一个OkHttpClient,这样我们就不再需要new一个OkHttpClient。请看下面的代码:

    OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
        OkHttpClient mOkHttpClient=builder.build();  
    

    取消请求和简单封装

    可以直接调用call.cancel()取消掉请求,这个框架的二次封装网上有很多,这里就不再贴代码了,关于这个框架就简单介绍到这里了,推荐几篇关于这个框架的介绍博文:

    Android 一个改善的okHttp封装库

    OkHttp3源码分析

    okhttp3与旧版本okhttp的区别分析

    相关文章

      网友评论

      本文标题:Android框架学习笔记01Okhttp框架

      本文链接:https://www.haomeiwen.com/subject/xjknettx.html