Android网络部分-----网络数据请求、解析

简介: Android网络部分-----网络数据请求、解析

一.网络知识简介

      1. 网络操作是Android开发中很重要的一部分,我们在移动端开发的app如何不断地向服务器发送请求并接受服务器发送来的json格式的字符串,通过json解析技术把指定的内容展示在指定的控件上面。

      2. 首先客户端在发送请求之前是需要TCP或者UDP来基于三次握手技术和服务端建立连接,然后通过http协议这种应用技术发送请求和接收响应,http提供了封装或者显示数据的具体形式,Socket提供了网络通信的能力。

      3. 网络请求方式:GET和POST

GET 主要作用是从服务器获取数据,方式是将参数拼接在url后面,前端直接可以看到,传输层角度来说不是很安全,但是本质层来说,因为get是获取数据不会对服务器数据修改,所以安全。

POST主要作用是给服务器提交数据,方式是将数据放在数据包发送,看不到的,传输层角度来说比较安全,但是本质层来说,因为post是操作是对服务器数据修改,所以不是很安全。

二:get请求数据(原生方法)

public class IndexActivity extends AppCompatActivity implements View.OnClickListener {
    private String result;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
 
    @Override
    public void onClick(View v) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                URL url = null;
                try {
                    //获取URL实例
                    url = new URL("xxxx请求地址");
                    //获取链接对象
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    //设置请求方法
                    connection.setRequestMethod("GET");
                    //设置请求超时时间
                    connection.setConnectTimeout(30 * 1000);
                    connection.setRequestProperty("Content-type", "application/json");
                    connection.setRequestProperty("Charset", "UTF-8");
                    connection.setRequestProperty("Accept-Charset", "UTF-8");
                    //发起连接
                    connection.connect();
                    int responseCode = connection.getResponseCode();
                    String message = connection.getResponseMessage();
                    if (responseCode == HttpURLConnection.HTTP_OK) {
                        //获取inputStream流
                        InputStream inputStream = connection.getInputStream();
                        //将得到的inputStream流转成字符串
                        result = streamToString(inputStream);
                        Log.e("结果是", result);
                        final TextView textView = findViewById(R.id.result);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                result=decode(result);
                                textView.setText(result);
                            }
                        });
                       /* textView.post(new Runnable() {
                            @Override
                            public void run() {
                                textView.setText(result);
                            }
                        });*/
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
 
    }
 
    /**
     * inputStream转为String
     *
     * @param in 要传入的流对象
     * @return 结果字符串
     */
    private String streamToString(InputStream in) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();//定义一个输出管道
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read()) != -1) {//写入管道
                baos.write(buffer, 0, len);
            }
            baos.close();
            in.close();
            byte[] bytesArray = baos.toByteArray();//管道转为字节数组
            return new String(bytesArray);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 将Unicode字符转换为UTF-8类型字符串
     */
    public static String decode(String unicodeStr) {
        if (unicodeStr == null) {
            return null;
        }
        StringBuilder retBuf = new StringBuilder();
        int maxLoop = unicodeStr.length();
        for (int i = 0; i < maxLoop; i++) {
            if (unicodeStr.charAt(i) == '\\') {
                if ((i < maxLoop - 5)
                        && ((unicodeStr.charAt(i + 1) == 'u') || (unicodeStr
                        .charAt(i + 1) == 'U')))
                    try {
                        retBuf.append((char) Integer.parseInt(unicodeStr.substring(i + 2, i + 6), 16));
                        i += 5;
                    } catch (NumberFormatException localNumberFormatException) {
                        retBuf.append(unicodeStr.charAt(i));
                    }
                else {
                    retBuf.append(unicodeStr.charAt(i));
                }
            } else {
                retBuf.append(unicodeStr.charAt(i));
            }
        }
        return retBuf.toString();
    }
}

重点:

1.因为我们请求网络数据会有数据等待,这时候如果我们在主线程中操作,就会出现卡死主线程异常,所以对于数据请求的操作我们要放在一个子线程中让其运行

2.在涉及到请求网络的时候在mainifest配置文件中需要声明网络权限

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

3.只有在主线程中才能更新ui,子线程中不能操作ui,可以通过Handler更新UI,后面或介绍这种方法,这里还有两种处理方法就是

代码中的

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        textView.setText(result);
    }
});

把ui更新操作放到主线程中运行

另外就是TextView的post方法可以直接将操作更新到主线程中进行

textView.post(new Runnable() {
    @Override
    public void run() {
        textView.setText(result);
    }
});

4.在Android9.0中对http的请求进行了限制,不能访问,我们需要在res中创建一个xml/network-security-config文件

增加cleartextTrafficPermitted属性,如下

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted = "true"/>
</network-security-config>

添加到安全配置文件mainifest.xml中

上面这个限制只有在9.0中并且

targetSdkVersion 是29才会发生

三:post请求

public void onClick(View v) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    URL url = null;
                    try {
                        //获取URL实例
                        url = new URL("xxxx请求地址,不带有参数");
                        //获取链接对象
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        //设置请求方法
                        connection.setRequestMethod("POST");
                        //设置请求超时时间
                        connection.setConnectTimeout(30 * 1000);
                        connection.setRequestProperty("Content-type", "application/json");
                        connection.setRequestProperty("Charset", "UTF-8");
                        connection.setRequestProperty("Accept-Charset", "UTF-8");
                        connection.setDoOutput(true);
                        connection.setDoInput(true);
                        //不用缓存
                        connection.setUseCaches(false);
                        //发起连接
                        connection.connect();
                        String data = "username=" + URLEncoder.encode("123", "UTF-8") + "123";/*有编码问题的的也可以处理*/
                        OutputStream outputStream = connection.getOutputStream();
                        outputStream.write(data.getBytes());
                        outputStream.flush();
                        outputStream.close();
                        int responseCode = connection.getResponseCode();
                        String message = connection.getResponseMessage();
                        if (responseCode == HttpURLConnection.HTTP_OK) {
                            //获取inputStream流
                            InputStream inputStream = connection.getInputStream();
                            //将得到的inputStream流转成字符串
                            result = streamToString(inputStream);
                            Log.e("结果是", result);
                            final TextView textView = findViewById(R.id.result);
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    result = decode(result);
                                    textView.setText(result);
                                }
                            });
                   /* textView.post(new Runnable() {
                        @Override
                        public void run() {
                            textView.setText(result);
                        }
                    });*/
                        }
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
}

上面的get和post都是通过原生实现的,实际生产场景中往往使用第三方库

四:数据解析

我们通过上面的get或者post方法从网络拿到数据之后,如何把得到的json字符串解析呢?

解析json数据主要两种方法,第一种使用JSONObject解析json数据,第二种使用第三方库解析,比如谷歌提供的GSON解析JSON数据,这里演示JSONObject解析json数据

用于测试的json数据如下

{
  "status": 1,
  "data": [{
      "id": 1,
      "name": "abc"
    },
    {
      "id": 2,
      "name": "123"
    }
  ],
  "msg": "成功"
}

在json数据中每一个{}代表一个JSONObject即json对象,每一个[ ]就是一个JSONArray即json数组,所以案例数据就是一个json对象包含了一个json数组,这个json数组里面有两个json对象

我们定义对应的实体类(set、get方法省)

//最外面的json对象
public class Result {
    private int status;
    //json数组
    private List<Person> personList;
    //json数组里面的对象
    private static class Person{
        private int id;
        private String name;
    }
}

解析java代码

 public void jsonToPo(String resultJson) throws JSONException {
        JSONObject resultObject = new JSONObject(resultJson);
        int status = resultObject.getInt("status");
        JSONArray jsonArray = resultObject.getJSONArray("data");
        Result result = new Result();
        List<Result.Person> personList = new ArrayList<>();
        result.setStatus(status);
        if (jsonArray != null && jsonArray.length() > 0) {
            for (int i = 0; i < jsonArray.length(); i++) {
                //遍历每一个json对象
                JSONObject jsonObject = (JSONObject) jsonArray.get(i);
                int id  = jsonObject.getInt("id");
                String name = jsonObject.getString("name");
                Result.Person person = new Result.Person();
                person.setId(id);
                person.setName(name);
                //添加到list中
                personList.add(person);
            }
            result.setPersonList(personList);
        }
    }

更多内容关注微信公众号 java一号

文章首发地址  www.javayihao.top


相关文章
|
23小时前
|
Android开发
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
|
23小时前
Android-kotlin-接口与多态的表现,面经解析
Android-kotlin-接口与多态的表现,面经解析
|
1天前
|
Web App开发 存储 缓存
第八篇 提升网页性能:深入解析HTTP请求优化策略(三)
第八篇 提升网页性能:深入解析HTTP请求优化策略(三)
|
1天前
|
消息中间件 前端开发 JavaScript
第七篇 提升网页性能:深入解析HTTP请求优化策略(二)
第七篇 提升网页性能:深入解析HTTP请求优化策略(二)
|
1天前
|
编解码 前端开发 JavaScript
第六篇 提升网页性能:深入解析HTTP请求优化策略(一)
第六篇 提升网页性能:深入解析HTTP请求优化策略(一)
|
1天前
|
存储 缓存 安全
第二章 HTTP请求方法、状态码详解与缓存机制解析
第二章 HTTP请求方法、状态码详解与缓存机制解析
|
1天前
|
Android开发 Java Kotlin
阿里P8大佬亲自讲解,android面试题解析
阿里P8大佬亲自讲解,android面试题解析
|
1天前
|
Android开发 前端开发 数据可视化
2024年大厂Android面经,深度解析,值得收藏
2024年大厂Android面经,深度解析,值得收藏
|
1天前
|
设计模式 算法 Android开发
2024年Android网络编程总结篇,androidview绘制流程面试
2024年Android网络编程总结篇,androidview绘制流程面试
2024年Android网络编程总结篇,androidview绘制流程面试
|
2天前
|
存储 Java Android开发
Android轻量级数据SparseArray详解
Android轻量级数据SparseArray详解
6 0

推荐镜像

更多