实战第10篇:JSONObject联网解析天气预报

282 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情


今日实战内容:写一个网络版的天气预报App。 image3.GIF

一、知识储备

两个知识点:第一,利用HttpURLConnection实现网络请求;第二,利用JSONObject解析json数据。

1.1 HttpURLConnection 网络请求

我们开发App,肯定需要连接网络,比如获取最新天气、资讯,都需要通过网络进行传输。

网络传输就牵扯到了网络协议,我们要协商以怎样的方式交互:我说了你懂,你发送的我能收到

HTTP协议是现在Internet上使用得最多、最重要的协议,我们通过HTTP来访问网络资源。

image.png

Android已经提供了访问HTTP协议的基本功能的类:HttpURLConnection。它可用于向指定网站发送GET、POST请求。

构建一个网络连接很简单,指定url配置请求方式就可以了。

 // 构建URL对象
URL url = new URL("http://www.weather.com.cn/data/sk/101010100.html");
//建立HttpURLConnection实例
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置请求方式
connection.setRequestMethod("GET");

HttpURLConnection连接建立完成,就可以去访问和获取数据了。

// 使用getInputStream获取服务器返回的输入流
InputStream stresm = connection.getInputStream();
//对返回的输入流进行读取
BufferedReader reader = new BufferedReader(new InputStreamReader(stresm));
//构建字符对象存放数据
StringBuilder response = new StringBuilder();
String line;
//循环数据流存入字符对象
while ((line = reader.readLine()) != null) {
    response.append(line);
}
// 输出字符对象,这就是网络返回的数据
String res =  response.toString();

步骤如下:

  1. 使用getInputStream获取服务器返回的输入流。
  2. 对返回的输入流进行读取。
  3. 构建字符对象存放数据,循环数据流存入字符对象。
  4. 输出字符对象,这就是网络返回的数据。

以上就是网络请求的过程。

1.2 JSONObject解析json

网络交互的格式有很多,比较常用的就是json。

image.png

我们面临json如何处理呢?不对,应该先说json是什么样子的?

// 一段json
{
    "code":1,
    "name":"tom",
    "num":"it1011"
}

// 一个Java类
public class LoginBean {
    private int code;
    private String name;
    private String num;
}

你可以认为json和Java类对应,因为最终我们也是要把json转换成实体类。

Android系统提供解析json的类JSONObject,具体使用方法如下:

  1. 将json字符串jsonData装入JSONObject,实例jsonObject对象。
  2. 根据json的键,从jsonObject中读取期望的值。

举个例子,还是这一段json:

{
    "code":1,
    "name":"tom",
    "num":"it1011"
}

我们如何解析呢?

先将json字符串jsonData装入JSONObject,然后根据数据类型和键值取值就可以了。

JSONObject jsonObject = new JSONObject(jsonData);
int code = jsonObject.getInt("code");
String name = jsonObject.getString("name");
String num = jsonObject.getString("num");

二、实战应用

2.1 效果

现在再来看看,我们要实战的一个应用。这是一个天气预报程序。

image3.GIF

如果要开发它,那么流程应该是:点击按钮请求网络,获取数据并解析,最后展示到界面上。

2.2 接口和格式

数据来源我们使用天气网,接口的url是 www.weather.com.cn/data/sk/101… ,这是北京天气。此接口通过get方式可直接访问,返回json格式:

 {
     "weatherinfo": {
     "city": "北京",
     "temp": "27.9",
     "WD": "南风",
     "WS": "小于3级",
     "SD": "28%",
         ……
     }
 }

2.3 逻辑架构

写代码前,我们先想一想逻辑流程和数据流转,最好能简单写一写伪代码,先整体思考。

public class MainActivity extends Activity {

    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = findViewById(R.id.tv);
    }

    // 1、新启动一个线程用于网络请求
    public void getTextFromNet(View view) {
    
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 2、从接口url访问获取json
                String jsonText = getNetString(url);
                // 3、解析json显示到界面上
                showData(jsonText);
            }
        }).start();
    }
}

为什么要新启动线程去请求网络,之前讲过UI的线程模型,有兴趣的可以去参考。

下面我们进行功能拆分,首先访问接口获取json,也就是那个getNetString函数,代码如下,还是联网的那一套,主要通过HttpURLConnection来实现。

private String getNetString(String urlString){

    try {
        // 构建一个URL
        URL url = new URL(urlString);
        // 通过url对象来打开一个HttpURLConnection
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置请求方式
        connection.setRequestMethod("GET");
        // 获取输入流
        InputStream stresm = connection.getInputStream();
        // 把输入流读取到buffer
        BufferedReader reader = new BufferedReader(new InputStreamReader(stresm));
        // 构建一个字符对象
        StringBuilder response = new StringBuilder();
        String line;
        // 将网络的输入流转化到字符串当中
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
        // 返回网络的结果
        return response.toString();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "";
}

接下来是解析数据和展示数据,我们来看一下代码:

private void showData(final String jsonText) {

    try {
        JSONObject jsonObject = new JSONObject(jsonText);
        JSONObject weatherObj = jsonObject.getJSONObject("weatherinfo");
        String city = weatherObj.getString("city");
        String temp = weatherObj.getString("temp");
        String WD = weatherObj.getString("WD");
        String text = city + temp + WD;

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tv.setText(text);
            }
        });

    } catch (JSONException e) {
        e.printStackTrace();
    }
}

解析数据通过构造JSONObject实例,然后通过get对应的类型获取出对应的数值,然后拼装成我们需要字符串。

重点看一下,当我们有展示的数据后,如何交给UI呈现出来。要记住,现在我们还处于子线程中,不能直接进行viewsetText操作,原因是子线程别直接访问主线程。我们要通过runOnUiThread方法,在主线程里去给视图做赋值操作。

三、总结

文中讲的两项内容HttpURLConnectionJSONObject都比较底层(虽然我认为这是高阶API)。

Android新人基本不用这个,因为网络框架有很多,例如VolleyOKHttp。解析框架也有很多,比如Gsonfastjson。但是,从学习的角度,我依然建议大家从底层开始学,这个底层其实也是调用Android SDK这个大框架。

可能你最终用不到,但是必须要知其然,知其所以然,这将是技术人最终的自信。

用框架很方便,没错,但是框架也是开发者写的,到某个阶段,你最终也要写框架。

我是TF男孩,关注掘金专栏《Java转Android》。每天800字,30天入门安卓开发。