实践--天气预报应用实例

主要功能

  • 省市县三级列表展示城市,按选择查询对应城市的当天天气和近期天气情况
  • 可以手动的切换城市
  • 可以手动更新天气以及后台的自动更新天气
  • 自定义折线图显示近期的温度变化
  • 桌面小组件实时显现天气和时间

  • 效果图如下

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

这个小应用开发过程中用到的自定义View–折线图实践–桌面小组件之天气小组件在前面的博客中都有讲解,如有疑惑,请前往查看。

数据的获取

http://www.weather.com.cn/data/list3/city.xml
  • 这个网址返回的是全国所有的省的数据,大家访问自行查看数据内容,里面包含了省名称和省id,id就用于继续查询市级信息
address = "http://www.weather.com.cn/data/list3/city"+id+".xml";
  • 上面的id就用来继续拼接成上述网址,用来查询对应的省下属的市级列表,返回的数据一样,是市名称和市id
  • 同样的查询县级信息和上面一样,不过将id换为市id,用来查询下属的县级信息。

  • 获取到县的信息和id,在次发送消息,我们就能获取到对应县的天气的id了,通过天气的id我们就能获取相应的县的天气了

http://api.k780.com:88/?app=weather.future&weaid=" + substring + "&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=xml
  • 我们将substring对应换成就可以获取到相应的县的近7天的天气信息了,返回的数据是xml格式的数据 ,我们对应解析就可以了。

  • 例如江苏省 id为19

  • 苏州 id为1904
  • 昆山 id为190404
  • 昆山对应的天气id为101190404
  • 下面为对应的代码
    /**
     * 根据传入的代号和类型从服务器上查询省市县数据。
     */
    private void queryFromServer(final String code, final String type, final int position) {
        String address;
        if (!TextUtils.isEmpty(code)) {
            address = "http://www.weather.com.cn/data/list3/city" + code + ".xml";
        } else {
            address = "http://www.weather.com.cn/data/list3/city.xml";
        }
        if (!dialog.isShowing()) {
            dialog.show();
        }
        HttpUtils.sendHttpRequest(address, new HttpUtils.HttpCallbackListener() {
            @Override
            public void onFinish(String response) {
                boolean result = false;
                if ("province".equals(type)) {
                    result = HandleResponceUtils.handleProvincesResponse(coolWeatherDB,
                            response);
                } else if ("city".equals(type)) {
                    result = HandleResponceUtils.handleCitiesResponse(coolWeatherDB,
                            response, provinceList.get(position).getId());
                } else if ("county".equals(type)) {
                    result = HandleResponceUtils.handleCountiesResponse(coolWeatherDB,
                            response, cityList.get(position).getId());
                }
                if (result) {
                    // 通过runOnUiThread()方法回到主线程处理逻辑
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (dialog.isShowing()) {
                                dialog.dismiss();
                            }
                            if ("province".equals(type)) {
                                queryProvinces();
                            } else if ("city".equals(type)) {
                                queryCities(position);
                            } else if ("county".equals(type)) {
                                queryCounties(position);
                            }
                        }
                    });
                }
            }

            @Override
            public void onError(Exception e) {
                // 通过runOnUiThread()方法回到主线程处理逻辑
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (dialog.isShowing()) {
                            dialog.dismiss();
                        }
                        Toast.makeText(ChooseAreaActivity.this, "请检查手机网络", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
  • 对应的网络处理的类就是
public class HttpUtils {

    public interface HttpCallbackListener {

        void onFinish(String response);

        void onError(Exception e);

    }

    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL(address);
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    InputStream in = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                    if (listener != null) {
                        // 回调onFinish()方法
                        listener.onFinish(response.toString());
                    }
                } catch (Exception e) {
                    if (listener != null) {
                        // 回调onError()方法
                        listener.onError(e);
                    }
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

}

#

数据库的设计

首先我们根据上面的数据信息,需要建三张表
省名称和对应的省id的表
市名称和对应的市id,以及市所属的省的id的表
县名称和对应县的天气的id,以及县所属的市的id的表
同时还有一个我们用于保存目前定位的城市的天气信息的表

界面展示

  • 界面展示我们选择用Viewpager来展示两个Fragment,分别展示当天天气和一周天气的情况
  • 具体布局如下
  • 当天天气
    这里写图片描述
  • 近期天气
    这里写图片描述
    近期天气使用了n个竖直的线性布局,线性布局中在放置对应的天气信息的控件
    下方放置一个天气的折线图控件

后台的更新

我们检测开机的广播,实现开机我们就开启后台的服务,在服务中设置定时逻辑,当时间到了之后,我们就执行更新天气的代码逻辑。
同时我们在每次开启软件的时候,也进行服务的开启逻辑,如果服务微开启,那么我们开启软件的同时,服务也会启动

         //定时两小时更新数据库天气信息
        AlarmManager manager= (AlarmManager) getSystemService(ALARM_SERVICE);
        int alarmTime=60*2*60*1000;
        long time= System.currentTimeMillis()+alarmTime;
        PendingIntent i=PendingIntent.getBroadcast(this,0,new Intent("START_AlARM"),0);
        manager.set(AlarmManager.RTC_WAKEUP,time,i);

整体逻辑

  • 我们每次进入程序都先查询数据库中的天气的表中是否有数据,若有,我们就直接进入天气展示界面,将获取的天气信息展示在界面上,如果为获取相应的天气信息,我们就进入城市选择界面,选择城市的时候我们是先从数据库查询城市信息,没有的话,再去服务器查询城市信息并先保存到本地数据库以便下次查询使用。当我们点击相应的城市列表的名称,我们就去服务器获取新的天气信息,同时删除本地天气信息,将新获取的天气信息保存即可。

  • 整体的逻辑就是这样的,再有就是一些小细节的知识,比如UI的及时更新,桌面小组件的实时显示,直接根据天气图片的网址,将图片显示在界面上等等。

  • -

如果对上面的讲解疑惑,如果有需要,欢迎下载天气APP源码

在源码中,大部分方法、代码我都加了相应的功能逻辑的注释,这样可以保证你阅读源码更易于理解*

数据的提供地址:

网址,最后的cityKey就是对应的城市id(一周的天气)
http://api.k780.com:88/?app=weather.future&weaid=101010100&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=xml

  • 这是另外一个可用的获取城市名称和id的网址

查询城市名称和id的网址,返回的是xml数据,可以使用xml数据解析,获取的是全国所有的县的信息
http://api.k780.com:88/?app=weather.city&format=xml

天气API接口大全

发布了121 篇原创文章 · 获赞 18 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章