> 文档中心 > 【Android】8.0网络请求数据与JSON解析

【Android】8.0网络请求数据与JSON解析

🍀【Android】8.0网络请求数据与JSON解析

  • 🍁网络请求权限
  • 🌳网络请求
      • 网络在主线程异常
      • 子线程网络请求
      • 线程切换
  • 🌺JSON数据解析
  • 🌷第三方框架 gson
    • 添加依赖
    • 创建一个实体类
    • 使用GSON框架解析
      • 普通json数据类型类
      • 嵌套json类型实体类
      • json数组实体类
    • 实体类插件GsonFormatPlus
      • 安装
      • 打开
      • 设置
      • 使用
    • MainActivity完整代码
    • Student类完整代码

注意:不是教程只是笔记,如有错误欢迎批评指正

🍁网络请求权限

既然需要访问网络自然需要网络请求权限

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

除此之外还需要加上这一行,否则http的网页请求不成功

android:usesCleartextTraffic="true"

【Android】8.0网络请求数据与JSON解析

🌳网络请求

网络在主线程异常

这段代码是网络请求数据,http://121.4.44.56/user这是老师提前发在网上的数据文件,可通过这个网址访问,其中的数据是:

【Android】8.0网络请求数据与JSON解析

  try {     URL url = new URL("http://121.4.44.56/user");     HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();     urlConnection.setRequestMethod("GET");   InputStream inputStream = urlConnection.getInputStream();// 字节流     Reader reader = new InputStreamReader(inputStream);//字符流     BufferedReader bufferedReader = new BufferedReader(reader);// 缓存流     String result = "";     String temp;     while ((temp = bufferedReader.readLine()) != null) {  result += temp;     }     Log.i("MainActivity", result);     inputStream.close();     reader.close();     bufferedReader.close(); } catch (Exception e) {     e.printStackTrace(); }

将这段代码放在主线程下执行会出现警告warn

W/System.err: android.os.NetworkOnMainThreadException

网络在主线程异常-》网络请求不能在主线程

生命周期中执行的方法默认是主线程(UI线程)不能执行耗时的操作

耗时操作-》such as:

读取文件(读数据库)、网络请求

子线程网络请求

因此我们需要创建一个子线程来访问网络数据,并且在子线程中将获取到的数据显示在TextView控件上

Thread thread=new Thread(){@Overridepublic void run() {    //run()方法执行的代码都是在子线程中    super.run();    //网络请求    try { //请求服务器端 URL url = new URL("http://121.4.44.56/user"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); //获取io输入字节流->字符流->缓存流 InputStream inputStream = urlConnection.getInputStream();// 字节流 Reader reader = new InputStreamReader(inputStream);//字符流 BufferedReader bufferedReader = new BufferedReader(reader);// 缓存流 String result = ""; String temp; while ((temp = bufferedReader.readLine()) != null) { result += temp;   } Log.i("MainActivity", result); //在子线程中将获取到的数据显示在`TextView`控件上 textView.setText(result); inputStream.close(); reader.close(); bufferedReader.close();   } catch (Exception e) {    e.printStackTrace();    }    }};thread.start();

运行发现虚拟机上只显示一部分数据,查看日志窗口发现:

【Android】8.0网络请求数据与JSON解析

线程切换

出现警告:在错误的线程中执行

W/System.err: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

原因: 对于UI控件的操作不能放在子线程中->需要放到主线程中执行->线程切换

【Android】8.0网络请求数据与JSON解析

不能直接在主线程中设置,因为主线程和子线程是一起运行的,它们在运行时是无法人为预知的

在子线程中通过runOnUiThread(new Runnable()实现线程切换

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

【Android】8.0网络请求数据与JSON解析

🌺JSON数据解析

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

问题:网络请求是耗时的,那么如何一次请求到所有的数据呢?

如图一次请求到年龄,姓名和是否是学生三个数据,但是我们只需要姓名,我们就只需要通过JSON解析字符串,再通过 键名 获取到姓名

基本类型

json数据结构的特点:"key":value

//json结构 "key":value { "age":30,"name":"张三", "isstudent":true }//如何从json结构中解析出数据
 try {     //json解析字符串     JSONObject jsonObject=new JSONObject(finalResult);     //通过 键 获取到 值     String name=jsonObject.getString("name");     textView.setText(name);     } catch (JSONException e) {     e.printStackTrace();  }

json字符串的数据结构可以是浮点型,整型,长整型,字符串型,布尔型 ,数组类型,josn类型,class类型等等

【Android】8.0网络请求数据与JSON解析

json类型

json数据结构还可以是json类型的,这种情况需要嵌套解析,http://121.4.44.56/object1文件里的内容如下:

{ "age":20,"name":"张三", "isstudent":true,"class":{"grade":"18级","classname":"计算机科学与技术"} }
//json解析字符串JSONObject jsonObject=new JSONObject(finalResult);//首先获取到嵌套的json类型,这也可以看做通过 键 找 值//class是键名,{"grade":"18级","classname":"计算机科学与技术"}是值JSONObject classObj=jsonObject.getJSONObject("class");//再通过 键 获取到 值String className=classObj.getString("classname");

【Android】8.0网络请求数据与JSON解析

数组类型

json数据结构还可以数数组类型,http://121.4.44.56/object2文件里的内容如下:

{ "grade":"18级","classname":"计算机科学与技术","students":["张三","李四","王五"] }
JSONObject jsonObject=new JSONObject(finalResult);//通过数组名获取到数组JSONArray jsonArray= jsonObject.getJSONArray("students");//遍历数组,打印日志for(int i=0;i<jsonArray.length();++i){     String student=jsonArray.getString(i);//根据下标获取     Log.i("Students","student = "+student);}

【Android】8.0网络请求数据与JSON解析

json数组类型

再复杂一丢丢,json数组类型,http://121.4.44.56/object3文件里的内容如下:

{ "grade":"20级","classname":"计算机科学与技术","students":[{ "id":"001","age":30,"name":"张三", "isstudent":false },{ "id":"002","age":25,"name":"李四111", "isstudent":true },{ "id":"003","age":26,"name":"王1111五", "isstudent":true }]}
//通过数组名获取到数组JSONArray jsonArray= jsonObject.getJSONArray("students");//遍历数组,打印日志 for(int i=0;i<jsonArray.length();++i){    //根据下标获取每一个json数据 JSONObject studentobj=jsonArray.getJSONObject(i);    //通键名获取到每一个json数据下的值    String name=studentobj.getString("name");    Integer age=studentobj.getInt("age");    //打印日志    Log.i("MainActivity","name = "+name+" age = "+age);  }

【Android】8.0网络请求数据与JSON解析

学习要求:会解析json数据结构,会构json造数据结构

例如京东列表:

{"list":[{"name":iphone12,"price":6799},{"name":iphone12 plus,"price":7988},{},{}]}

🌷第三方框架 gson

google/gson:一个Java序列化/反序列化库,用于将Java Objects转换为JSON并返回 (github.com)

优点

  1. 直接将字符串解析成对象
  2. 解析成为一个实体类

添加依赖

implementation 'com.google.code.gson:gson:2.9.0'

创建一个实体类

实体类要求字段的名称和类型严格一致

{ "age":30,"name":"张三", "isstudent":true }

【Android】8.0网络请求数据与JSON解析

使用GSON框架解析

普通json数据类型类

Gson gson=new Gson();Student student=gson.fromJson(finalResult,Student.class);Log.i("MainActivity", "run: "+student.name);

【Android】8.0网络请求数据与JSON解析

嵌套json类型实体类

如果是json类型嵌套实体类,那么实体类应该做如下修改:

{ "age":20,"name":"张三", "isstudent":true,"class":{"grade":"18级","classname":"计算机科学与技术"} }

json数据类型对应java的类,所以嵌套的json结构,改写成实体类时也是嵌套的类(内部类),除此之外还要声明这个内部类,因为这里键名是class与java的关键字冲突,所以要注解"class",然后换个变量名

【Android】8.0网络请求数据与JSON解析

【Android】8.0网络请求数据与JSON解析

MainActivity的子线程中解析数据并打印

【Android】8.0网络请求数据与JSON解析

json数组实体类

通常使用java集合类中的List可变数组定义json数据结构中的数组

【Android】8.0网络请求数据与JSON解析

【Android】8.0网络请求数据与JSON解析

实体类插件GsonFormatPlus

GSON框架虽然简化了我们解析数据的过程,但是需要书写一个实体类又给我们添加了麻烦,可以通过如下插件一键生成json数据结构的实体类

安装

【Android】8.0网络请求数据与JSON解析

打开

【Android】8.0网络请求数据与JSON解析

设置

【Android】8.0网络请求数据与JSON解析

使用

在左侧粘贴json数据结构的字符串,然后ok即可

【Android】8.0网络请求数据与JSON解析

MainActivity完整代码

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView=findViewById(R.id.textView); /*网络在主线程异常-》网络请求不能在主线程 生命周期中执行的方法默认时主线程(UI线程)不能执行耗时的操作 耗时操作-》such as: 读取文件(读数据库)、网络请求*/ Log.i("MainActivity", "test1 "); Thread thread=new Thread(){     @Override     public void run() {  //run()方法执行的代码都是在子线程中  super.run();  //网络请求  try {      //请求服务器端      URL url = new URL("http://121.4.44.56/user");      HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();      urlConnection.setRequestMethod("GET");      //获取io输入字节流->字符流->缓存流      InputStream inputStream = urlConnection.getInputStream();// 字节流      Reader reader = new InputStreamReader(inputStream);//字符流      BufferedReader bufferedReader = new BufferedReader(reader);// 缓存流      //      String result = "";      String temp;      while ((temp = bufferedReader.readLine()) != null) {   result += temp;      }      Log.i("MainActivity", result);      Log.i("MainActivity", "test3 ");      //在子线程中设置文本      /*W/System.err: android.view.ViewRootImpl$CalledFromWrongThreadException:      Only the original thread that created a view hierarchy can touch its views.      对于UI控件的操作不能放在子线程中->需要放到主线程中执行->线程切换*/      //textView.setText(result);      //切换到主线程      String finalResult=result;      runOnUiThread(new Runnable() {   @Override   public void run() {Gson gson=new Gson();Student student=gson.fromJson(finalResult,Student.class);//Log.i("MainActivity", "run: "+student.class1.classname);Log.i("MainActivity", "run: "+student.students.get(0).name+" "+ student.students.get(0).id);// user// json结构 本质性是一个字符串 ”key“:value { "age":30,"name":"张三", "isstudent":true }//如何从json结构中解析出数据/*object1嵌套解析->json类型{ "age":20,"name":"张三", "isstudent":true,"class":{"grade":"18级","classname":"计算机科学与技术"} }* *//*object2* { "grade":"18级","classname":"计算机科学与技术","students":["张三","李四","王五"] }* 数组类型,josn类型,浮点型,整型,字符串型,布尔型 等等* *//*object3*  { "grade":"18级","classname":"计算机科学与技术",* "students":[* { "id":"001","age":30,"name":"张三", "isstudent":false },* { "id":"002","age":25,"name":"李四", "isstudent":true },* { "id":"003","age":26,"name":"王五", "isstudent":true }* ]}* json数组*/try {    JSONObject jsonObject=new JSONObject(finalResult);    String name=jsonObject.getString("name");    textView.setText(name);    /*JSONObject classObj=jsonObject.getJSONObject("class");    String className=classObj.getString("classname");//    String name=jsonObject.getString("name");//    textView.setText(name);    textView.setText(className);*/    /*JSONArray jsonArray= jsonObject.getJSONArray("students");    for(int i=0;i<jsonArray.length();++i){ String student=jsonArray.getString(i);//根据下标获取 Log.i("Students","student = "+student);    }*/    /*JSONArray jsonArray= jsonObject.getJSONArray("students");    for(int i=0;i<jsonArray.length();++i){ JSONObject studentobj=jsonArray.getJSONObject(i);//根据下标获取 String name=studentobj.getString("name"); Integer age=studentobj.getInt("age"); Log.i("MainActivity","name = "+name+" age = "+age);    }*/} catch (JSONException e) {    e.printStackTrace();}//textView.setText(finalResult);   }      });      inputStream.close();      reader.close();      bufferedReader.close();  } catch (Exception e) {      e.printStackTrace();  }     } }; thread.start(); Log.i("MainActivity", "test2 ");    }}

Student类完整代码

//{"age":30,"name":"张三", "isstudent":true}/** 字段的名称和类型要求严格一致* *//*object1{ "age":20,"name":"张三", "isstudent":true,"class":{"grade":"18级","classname":"计算机科学与技术"} } *//*object3{ "grade":"20级","classname":"计算机科学与技术","students":[{ "id":"001","age":30,"name":"张三", "isstudent":false },{ "id":"002","age":25,"name":"李四111", "isstudent":true },{ "id":"003","age":26,"name":"王1111五", "isstudent":true }]} *//*public class Student {    public int age;    public String name;    public boolean isstudent;    //设置注解,解决关键字重复    @SerializedName("class")    public MyClass class1;    public class MyClass{ public String grade; public String classname;    }}*/public class Student{    public String grade;    public String classname;    /*public MyStudent[] students;*/    public List<MyStudent> students;    public class MyStudent{ public String id; public int age; public String name; public boolean isstudent;    }}

【Android】8.0网络请求数据与JSON解析 创作打卡挑战赛 【Android】8.0网络请求数据与JSON解析 赢取流量/现金/CSDN周边激励大奖51mike麦克疯