實踐--天氣預報應用實例

主要功能

  • 省市縣三級列表展示城市,按選擇查詢對應城市的當天天氣和近期天氣情況
  • 可以手動的切換城市
  • 可以手動更新天氣以及後臺的自動更新天氣
  • 自定義折線圖顯示近期的溫度變化
  • 桌面小組件實時顯現天氣和時間

  • 效果圖如下

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

這個小應用開發過程中用到的自定義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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章