Android网络连接和网络数据处理

Android网络连接和网络数据处理

  • HTTP请求方式GET与POST
  • Android网络请求
    • OkHttp
      • 添加OKHttp库的依赖
      • 声明网络权限
      • 简单布局
      • OkHttp具体用法
  • 同步、异步概念
    • 同步
    • 异步
    • 异步方法示例
  • 数据解析
    • 概念
    • 实践
    • GsonFormat插件的安装

HTTP请求方式GET与POST

在Android开发中我们会接触到数据的交互,比如写入数据、读取数据等,因此我们需要使用通讯间的协议来进行请求,最常见的协议是HTTP协议,而GET和POST则是HTTP协议中最常用的两种请求方式。

  • HTTP协议
    HTTP(HyperText Transfer Protocol超文本传输协议)是一个设计来使客户端和服务器顺利进行通讯的协议。
    HTTP在客户端和服务器之间以request-response protocol(请求-回复协议)工作。
  • GET和POST的区别
GET POST
一般是从服务器上获取数据 一般用来上传表单到服务器1
URL 可见,安全性低 URL 不可见,安全性高
提交的数据有长度限制 提交的数据无长度限制
数据可缓存 数据不可缓存
通过拼接URL进行参数传递 数据放在请求体中发送

现在一般使用安全性较高的POST进行请求,在发送密码或其他敏感信息时一定不能使用 GET。POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。GET的数据在 URL 中对所有人都是可见的。

Android网络请求

Android进行网络请求有三种方法:HttpURLConnection、 HttpClient以及OkHttp。
HttpClient由于存在API数量过多、扩展困难等缺点,在Android6.0系统中,该功能已经被正式弃用。而原生的HttpURLConnection是JDK里提供的联网API,但是由于网络操作涉及到异步以及多线程,自己使用原生API编写比较麻烦,所以实际开发更偏向于直接使用第三方网络通信库,而我们今天要介绍的OkHttp就属于众多网络通信库中做的最出色的一个。

OkHttp

添加OKHttp库的依赖

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

声明网络权限

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

如果使用了不安全的http链接,应该在在清单文件中声明:

	android:usesCleartextTraffic="true"

简单布局

<Button
        android:id="@+id/btn_request"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="请求数据"/>

    <Button
        android:id="@+id/btn_jump"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="跳转解析页"/>


    <TextView
        android:id="@+id/tv_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

OkHttp具体用法

  1. 定义并实例化一个OkHttpClient
	OkHttpClient client = new OkHttpClient();
  1. 创建一个Request对象以发起一条HTTP请求,并通过url()方法来设置目标的网络地址。
	Request request = new Request.Builder()
	.url("http://106.53.96.124/wanted/public/index.php/index/article/find")
	.build();
  1. 调用OkHttpClient的newCall()方法创建一个Call对象,并调用execute()方法发送请求并获取响应数据。
  2. 定义一个response对象来接收获取到的响应数据,并通过responseData来取得我们返回的具体内容。
 	Response response = client.newCall(request).execute();
	String responseData = response.body().string();
  1. 由于网络请求属于耗时操作,应该在子线程中执行。因此我们在设置点击事件时,在onClick()方法中我们应该新开一个子线程。示例如下:
btn_request.setOnClickListener(new View.OnClickListener() {
     
            @Override
            public void onClick(View v) {
     
                new Thread(new Runnable() {
     
                    @Override
                    public void run() {
     
                        sendRequestWithOkHttp();//该方法封装了以上1-4步的内容
                    }
                }).start();
            }
        });
  1. sendRequestWithOkHttp()方法具体内容如下:
private void sendRequestWithOkHttp(){
     
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("http://106.53.96.124/wanted/public/index.php/index/article/find")
                .build();
        //try catch进行异常捕捉
        try {
     
        //同步写法
            Response response = client.newCall(request).execute();
            String responseData = response.body().string();
            //由于我们进行网络请求是在子线程执行,因此获取到的数据需要从子线程传递到主线程的Ui界面才能显示
            runOnUiThread(new Runnable() {
     
                @Override
                public void run() {
     
                    tv_data.setText(responseData);
                }
            });
        }catch (Exception e){
     
            e.printStackTrace();
        }
}

同步、异步概念

同步

同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。当前主线程会阻塞,直到子线程通知主线程为止。
提交请求 → 等待服务器处理 → 处理完毕返回

异步

异步方法调用通常会在另外一个线程中继续执行。整个过程,不会阻碍调用者的工作。主线程可以继续干其它的事情,当子线程完成任务的时候通知一下主线程就可以了,类似于接口回调或消息队列的思想。
请求通过事件触发>服务器处理(无需等待,主线程可以做别的事)>处理完毕
两者比较更推荐使用异步方法进行网络请求。

异步方法示例

定义一个Call对象,并把把request传给call,通过call调用.enqueue()方法执行。需要给enqueue()方法传一个Callback接口的匿名实现类(包含了onFailure()和onRresponse()方法)。
以下是异步监听方法示例:

private void sendRequestWithOkHttp(){
     
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("http://106.53.96.124/wanted/public/index.php/index/article/find")
                .build();
        //异步监听写法
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
     
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
     
                e.printStackTrace();
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
     
                String jsonData = response.body().string();
                //	传递到主线程UI界面
                runOnUiThread(new Runnable() {
     
                    @Override
                    public void run() {
     
                        tv_data.setText(jsonData);
                    }
                });
            }
        });
	}

数据解析

概念

一般来说通过网络请求获取到的数据有很多种,xml格式数据、Json格式数据等。我们以上通过网络请求获取到的数据就是Json格式数据。
比如

{
     "name":"alex","age":"18","friends":[{
     "name":"Amy","age":"19"},{
     "name":"Jack","age":"18"}]}

以上{}中相当于是一个类的实例,[{},{}]相当于是一个有两个类组成的数组,包括了两个类的实例。

实践

  1. 添加Gson库的依赖
    implementation 'com.google.code.gson:gson:2.7'
  1. 新建一个BaseResponse< T >基类来接收我们从服务端获取到的数据,类的内容可以通过Gsonformat插件导入,alt+s唤出插件界面,复制我们的json格式数据,点击OK。
  2. 创建一个parseJSONWithGSON()方法
private void parseJSONWithGSON(){
     
        Gson gson = new Gson();
        //由于我们这里需要解析的Json数据中包含了数组,所以需要使用TypeToken将期望解析成数据类型传入到fromJson()方法中
        BaseResponse<List<BaseResponse.Article>> baseResponse = gson.fromJson(jsonData,new TypeToken<BaseResponse<List<BaseResponse.Article>>>(){
     }.getType());
        List<BaseResponse.Article> articleList = baseResponse.getData();
        Log.d("code", "code is " + baseResponse.getCode());
        Log.d("msg", "msg is " + baseResponse.getMsg());
        for (BaseResponse.Article article:articleList){
     
            Log.d("Data", "id is "+article.getId());
            Log.d("Data", "title is "+article.getTitle());
            Log.d("Data", "content is "+article.getContent());
            Log.d("Data", "tags is "+article.getTags());
            Log.d("Data", "create_time is "+article.getCreate_time());
            Log.d("Data", "writer is "+article.getWriter());
            Log.d("Data", "images is "+article.getImages());
            Log.d("Data", "photo is "+article.getPhoto());
            Log.d("Data", "like_number is "+article.getLike_number());
            Log.d("Data", "comment_number is "+article.getComment_number());
        }
    }
  1. 在点击事件OnClick()方法中,调用parseJSONWithGSON()方法。
btn_show.setOnClickListener(new View.OnClickListener() {
     
            @Override
            public void onClick(View v) {
     
                if (jsonData==null){
     
                    Toast.makeText(MainActivity.this,"数据为空",Toast.LENGTH_SHORT).show();
                }
                else parseJSONWithGSON();
            }
        });

GsonFormat插件的安装

File→setting→plugin→Marketplace,搜索gsonformat/Sgsonformat/gsonfromatplus,通过alt+insert唤出gsonformat插件,复制json格式数据点击ok。

接口测试:https://getman.cn/
接口文档:http://www.docway.net/

参考资料:
Android入门之Http请求方式Get与Post
同步和异步的区别
同步(Synchronous)和异步(Asynchronous)


  1. 一般用来上传表单(数据集合)到服务器,服务器处理后再返回数据给客户端。 ↩︎

你可能感兴趣的:(Android,android,网络,java)