关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android 网络请求详解

    Android 网络请求详解

    2015-12-29 00:00:00 出处:linuxidc
    分享

    我们知道大多数的 Android 应用程序都是通过和服务器进行交互来获取数据的。假如使用 HTTP 协议来发送和接收网络数据,就免不了使用 HttpURLConnection 和 HttpClient,而 Android 中主要提供了上述两种方式来进行 HTTP 操作。并且这两种方式都支持 HTTPS 协议、以流的形式进行上传和下载、配置超时时间、IPv6、以及连接池等功能。

    但是 Googl e发布 6.0 版本的时候声明原生剔除 HttpClient,但是笔者认为 HttpClient 会提供相应的 jar 包做支持,毕竟 Google 对向下兼容这方面一直都做的很好,相信在选择网络功能的时候我们会选自己喜欢的方法。

    HttpURLConnection

    接着我们来看一下如何使用 HttpURLConnection 来处理简单的网络请求。

    // Get方式请求  
    public static void requestByGet() throws Exception {  
        String path = "10.128.7.34:3000/name=helloworld&password=android";  
        // 新建一个URL对象  
        URL url = new URL(path);  
        // 打开一个HttpURLConnection连接  
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
        // 设置连接超时时间  
        urlConn.setConnectTimeout(6 * 1000);  
        // 开始连接  
        urlConn.connect();  
        // 判断请求是否成功  
        if (urlConn.getResponseCode() == HTTP_200) {  
            // 获取返回的数据  
            byte[] data = readStream(urlConn.getInputStream());  
            Log.i(TAG_GET, new String(data, "UTF-8"));  
        } else {  
            Log.i(TAG_GET, "Get方式请求失败");  
        }  
        // 关闭连接  
        urlConn.disconnect();  
    }
    // Post方式请求  
    public static void requestByPost() throws Throwable {  
        String path = "http://10.128.7.34:3000/login";  
        // 请求的参数转换为byte数组  
        String params = "name+ URLEncoder.encode("helloworld", "UTF-8")  
                + "&password=" + URLEncoder.encode("android", "UTF-8");  
        byte[] postData = params.getBytes();  
        // 新建一个URL对象  
        URL url = new URL(path);  
        // 打开一个HttpURLConnection连接  
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
        // 设置连接超时时间  
        urlConn.setConnectTimeout(5 * 1000);  
        // Post请求必须设置允许输出  
        urlConn.setDoOutput(true);  
        // Post请求不能使用缓存  
        urlConn.setUseCaches(false);  
        // 设置为Post请求  
        urlConn.setRequestMethod("POST");  
        urlConn.setInstanceFollowRedirects(true);  
        // 配置请求Content-Type  
        urlConn.setRequestProperty("Content-Type",  
                "application/x-www-form-urlencode");  
        // 开始连接  
        urlConn.connect();  
        // 发送请求参数  
        DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());  
        dos.write(postData);  
        dos.flush();  
        dos.close();  
        // 判断请求是否成功  
        if (urlConn.getResponseCode() == HTTP_200) {  
            // 获取返回的数据  
            byte[] data = readStream(urlConn.getInputStream());  
            Log.i(TAG_POST, new String(data, "UTF-8"));  
        } else {  
            Log.i(TAG_POST, "Post方式请求失败");  
        }  
    }

    关于HttpURLConnection的相关开源工程

    由于 Google 已经表明了推荐广大开发者使用 HttpURLConnection,那么想必是有一定原因的。

    xUtils3

    这里就推荐大伙都很熟悉的开源项目 xUtils 的“弟弟“,xUtils3。xUtils 包含了 view 注入,图片处理,数据库操作以及网络请求封装,xUtils 使用的网络请求封装是基于 HttpClient 的。xUtils3 使用的网络请求是基于 HttpURLConnection,我们着重说明一下xUtils3。

    RequestParams params = new RequestParams("http://10.128.7.34:3000/upload");  
            // 加到url里的参数, http://xxxx/s wd=xUtils
            params.addQueryStringParameter("wd", "xUtils");
            // 添加到请求 body 体的参数, 只有 POST, PUT, PATCH, DELETE 请求支持.
            // params.addBodyParameter("wd", "xUtils");
    
            // 使用 multipart 表单上传文件
            params.setMultipart(true);
            params.addBodyParameter(
                    "file",
                    new File("/sdcard/test.jpg"),
                    null); // 假如文件没有扩展名, 最好设置contentType 参数.
            params.addBodyParameter(
                    "file2",
                    new FileInputStream(new File("/sdcard/test2.jpg")),
                    "image/jpeg",
                    // 测试中文文件名
                    "你+& /" 好.jpg"); // InputStream 参数获取不到文件名, 最好设置, 除非服务端不关心这个参数.
            x.http().post(params, new Callback.CommonCallback<String>() {
                @Override
                public void onSuccess(String result) {
                    Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
                }
    
                @Override
                public void onError(Throwable ex, boolean isOnCallback) {
                    Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
                }
    
                @Override
                public void onCancelled(CancelledException cex) {
                    Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
                }
    
                @Override
                public void onFinished() {
    
                }
            });

    具有 cache 功能

    RequestParams params = new RequestParams("http://10.128.7.34:3000/upload");  
            params.wd = "xUtils";
            // 默认缓存存活时间, 单位:毫秒.(假如服务没有返回有效的max-age 或 Expires)
            params.setCacheMaxAge(1000 * 60);
            Callback.Cancelable cancelable
                    // 使用 CacheCallback, xUtils 将为该请求缓存数据.
                    = x.http().get(params, new Callback.CacheCallback<String>() {
    
                private boolean hasError = false;
                private String result = null;
    
                @Override
                public boolean onCache(String result) {
                    // 得到缓存数据, 缓存过期后不会进入这个方法.
                    // 假如服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法.
                    //
                    // * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法.
                    //   假如服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的
                    //   逻辑, 那么xUtils将请求新数据, 来覆盖它.
                    //
                    // * 假如信任该缓存返回 true, 将不再请求网络;
                    //   返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息,
                    //   假如服务端返回 304, 则表示数据没有更新, 不继续加载数据.
                    //
                    this.result = result;
                    return false; // true: 信任缓存数据, 不在发起网络请求; false 不信任缓存数据.
                }
    
                @Override
                public void onSuccess(String result) {
                    // 注意: 假如服务返回 304 或 onCache 选择了信任缓存, 这里将不会被调用,
                    // 但是 onFinished 总会被调用.
                    this.result = result;
                }
    
                @Override
                public void onError(Throwable ex, boolean isOnCallback) {
                    hasError = true;
                    Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
                    if (ex instanceof HttpException) { // 网络错误
                        HttpException httpEx = (HttpException) ex;
                        int responseCode = httpEx.getCode();
                        String responseMsg = httpEx.getMessage();
                        String errorResult = httpEx.getResult();
                        // ...
                    } else { // 其他错误
                        // ...
                    }
                }
    
                @Override
                public void onCancelled(CancelledException cex) {
                    Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
                }
    
                @Override
                public void onFinished() {
                    if (!hasError && result != null) {
                        // 成功获取数据
                        Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
                    }
                }
            });

    post请求直接更改 post 方式,以及需要提交的参数即可,篇幅问题这里就不在一一列举了。通过以上代码可以看到,我们在使用 xUtils 来请求网络的时候会非常的方便,只用在回调函数里面做对应的代码逻辑处理即可,不用关心线程问题,极大的解放了我们的生产力。Android Stuido Gradle使用方法如下:

    compile ‘org.xutils:xutils:3.1.+’

    Volley

    在 Android 2.3 及以上版本,使用的是 HttpURLConnection,而在Android 2.2 及以下版本,使用的是 HttpClient。鉴于现在的手机行业发展速度,我们已经不考虑 Android2.2 了。

    简单提供一些 Volley 的实例:

    //简单的 GET 请求
    mQueue = Volley.newRequestQueue(getApplicationContext());  
    mQueue.add(new JsonObjectRequest(Method.GET, url, null,  
                new Listener() {  
                    @Override  
                    public void onResponse(JSONObject response) {  
                        Log.d(TAG, "response : " + response.toString());  
                    }  
                }, null));  
    mQueue.start();
    //对 ImageView 的操作
    ImageListener listener = ImageLoader.getImageListener(imageView, android.R.drawable.ic_launcher, android.R.drawable.ic_launcher);  
    mImageLoader.get(url, listener);  
    
    //对 ImageView 网络加载的处理
    mImageView.setImageUrl(url, imageLoader);

    当然我们也可以定制自己的 request

    mRequestQueue.add( new GsonRequest(url, ListResponse.class, null,  
        new Listener() {  
            public void onResponse(ListResponse response) {  
                appendItemsToList(response.item);  
                notifyDataSetChanged();  
            }  
        }  
    }

    HttpClient

    同样,我们来看一下 HttpClient 的简单请求。

    // HttpGet 方式请求  
    public static void requestByHttpGet() throws Exception {  
        String path = "http://10.128.7.34:3000/name=helloworld&password=android";  
        // 新建 HttpGet 对象  
        HttpGet httpGet = new HttpGet(path);  
        // 获取 HttpClient 对象  
        HttpClient httpClient = new DefaultHttpClient();  
        // 获取 HttpResponse 实例  
        HttpResponse httpResp = httpClient.execute(httpGet);  
        // 判断是够请求成功  
        if (httpResp.getStatusLine().getStatusCode() == HTTP_200) {  
            // 获取返回的数据  
            String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");  
            Log.i(TAG_HTTPGET, "HttpGet 方式请求成功,返回数据如下:");  
            Log.i(TAG_HTTPGET, result);  
        } else {  
            Log.i(TAG_HTTPGET, "HttpGet 方式请求失败");  
        }  
    }
    // HttpPost 方式请求  
    public static void requestByHttpPost() throws Exception {  
        String path = "https://reg.163.com/login";  
        // 新建 HttpPost 对象  
        HttpPost httpPost = new HttpPost(path);  
        // Post 参数  
        List<NameValuePair> params = new ArrayList<NameValuePair>();  
        params.add(new BasicNameValuePair("name", "helloworld"));  
        params.add(new BasicNameValuePair("password", "android"));  
        // 设置字符集  
        HttpEntity entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);  
        // 设置参数实体  
        httpPost.setEntity(entity);  
        // 获取 HttpClient 对象  
        HttpClient httpClient = new DefaultHttpClient();  
        // 获取 HttpResponse 实例  
        HttpResponse httpResp = httpClient.execute(httpPost);  
        // 判断是够请求成功  
        if (httpResp.getStatusLine().getStatusCode() == HTTP_200) {  
            // 获取返回的数据  
            String result = EntityUtils.toString(httpResp.getEntity(), "UTF-8");  
            Log.i(TAG_HTTPGET, "HttpPost 方式请求成功,返回数据如下:");  
            Log.i(TAG_HTTPGET, result);  
        } else {  
            Log.i(TAG_HTTPGET, "HttpPost 方式请求失败");  
        }  
    }

    关于 HttpClinet 的相关开源工程

    HttpClient 也拥有这大量优秀的开源工程,afinal、xUtils 以及AsyncHttpClient,也可以为广大开发者提供已经造好的轮子。由于xUtils 是基于 afinal 重写的,现在 xUtils3 也有替代 xUtils 的趋势,所以我们在这就简单介绍一下 AsyncHttpClient。

    AsyncHttpClient

    见名知意,AsyncHttpClient 对处理异步 Http 请求相当擅长,并通过匿名内部类处理回调结果,Http 异步请求均位于非 UI 线程,不会阻塞 UI 操作,通过线程池处理并发请求处理文件上传、下载、响应结果自动打包 JSON 格式。使用起来会很方便。

    //GET请求
    AsyncHttpClient client = new AsyncHttpClient();  
    //当然这里也可以换成 new JsonHttpResponseHandler(),我们就能直接获得 JSON 数据了。
    client.get("http://www.google.com", new AsyncHttpResponseHandler() {
    
        @Override
        public void onStart() {
            // called before request is started
        }
    
        @Override
        public void onSuccess(int statusCode, Header[] headers, byte[] response) {
            // called when response HTTP status is "200 OK"
        }
    
        @Override
        public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
            // called when response HTTP status is "4XX" (eg. 401, 403, 404)
        }
    
        @Override
        public void onRetry(int retryNo) {
            // called when request is retried
        }
    });
    //POST 请求
    AsyncHttpClient client = new AsyncHttpClient();  
    RequestParams params = new RequestParams();  
    params.put("key", "value");  
    params.put("more", "data");  
    //同上,这里一样可以改成处理 JSON 数据的方法
    client.get("http://www.google.com", params, new  
        TextHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, String response) {
                System.out.println(response);
            }
    
            @Override
            public void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) {
                Log.d("ERROR", error);
            }    
        }
    );

    经过上面的代码发现,AsyncHttpClient 使用起来也是异常简洁,主要靠回调方法来处理成功或失败之后的逻辑。仔细想想,xUtils 的处理方式和这个处理方式很类似,看来好用设计还是很受人青睐的。

    OKHttp

    假如两种网络请求都想使用怎么办?那么 OkHttp 是一个最佳解决方案了。

    OkHttp 在网络请求方面的口碑很好,就连 Google 自己也有使用OkHttp。虽然 Google6.0 中剔除了 HttpClient 的 Api,但是由于OkHttp 的影响力以及其强大的功能,使用 OkHttp 无需重写您程序中的网络代码。同时最重要的一点 OkHttp 实现了几乎和java.net.HttpURLConnection 一样的 API。假如您用了 Apache HttpClient,则 OkHttp 也提供了一个对应的 okhttp-apache 模块。足以说明 OkHttp 的强大,下面是一些例子。

    一般的 get 请求 一般的 post 请求 基于 Http 的文件上传 文件下载 加载图片 支持请求回调,直接返回对象、对象集合 支持 session 的保持

    简单代码实例

    //GET 请求
    OkHttpClient client = new OkHttpClient();
    
    String run(String url) throws IOException {  
      Request request = new Request.Builder()
          .url(url)
          .build();
    
      Response response = client.newCall(request).execute();
      return response.body().string();
    }
    //POST 请求
    public static final MediaType JSON  
        = MediaType.parse("application/json; charset=utf-8");
    
    OkHttpClient client = new OkHttpClient();
    
    String post(String url, String json) throws IOException {  
      RequestBody body = RequestBody.create(JSON, json);
      Request request = new Request.Builder()
          .url(url)
          .post(body)
          .build();
      Response response = client.newCall(request).execute();
      return response.body().string();
    }

    Android Studio Gradle 使用方式:

    compile ‘com.squareup.okhttp:okhttp:2.7.0′

    总结

    Android 开发应用少不了使用网络,移动互联时代,抢占终端入口变得异常重要,那么我们在开发过程中,不管使用哪一种网络请求,HttpURLConnection 或者是 HttpClient,都可以满足我们和服务器的沟通。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    SQL汉字转换为拼音的函数

    windows 7系统无法运行Photoshop CS3的解决方法

    巧用MySQL加密函数对Web网站敏感数据进行保护

    MySQL基础知识简介

    Windows7和WinXP下如何实现不输密码自动登录系统的设置方法介绍

    windows 7系统ip地址冲突怎么办?windows 7系统IP地址冲突问题的

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。