使用网络技术—天气预报

一、功能需求及技术可行性分析

天气中至少应该具备以下功能。

1.        可以罗列出全国所有的省、市、县。

2.        可以查看全国任意城市的天气信息。

3.        可以自由地切换城市,去查看其他城市的天气。

4.        提供手动更新以及后台自动更新天气的功能。

 

二、界面效果图

 

三、核心代码

[java]  view plain  copy
  1. <span style="color:#3366ff;">WeatherActivity。java</span>  

[java]  view plain  copy
  1. public class WeatherActivity extends Activity implements OnClickListener{  
  2.   
  3.     private LinearLayout weatherInfoLayout;  
  4.     /** 
  5.      * 用于显示城市名 
  6.      */  
  7.     private TextView cityNameText;  
  8.     /** 
  9.      * 用于显示发布时间 
  10.      */  
  11.     private TextView publishText;  
  12.     /** 
  13.      * 用于显示天气描述信息 
  14.      */  
  15.     private TextView weatherDespText;  
  16.     /** 
  17.      * 用于显示气温1 
  18.      */  
  19.     private TextView temp1Text;  
  20.     /** 
  21.      * 用于显示气温2 
  22.      */  
  23.     private TextView temp2Text;  
  24.     /** 
  25.      * 用于显示当前日期 
  26.      */  
  27.     private TextView currentDateText;  
  28.     /** 
  29.      * 切换城市按钮 
  30.      */  
  31.     private Button switchCity;  
  32.     /** 
  33.      * 更新天气按钮 
  34.      */  
  35.     private Button refreshWeather;  
  36.       
  37.       
  38.     @Override  
  39.     protected void onCreate(Bundle savedInstanceState) {  
  40.         super.onCreate(savedInstanceState);  
  41.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  42.         setContentView(R.layout.weather_layout);  
  43.         // 初始化各控件  
  44.         weatherInfoLayout = (LinearLayout) findViewById(R.id.weather_info_layout);  
  45.         cityNameText = (TextView) findViewById(R.id.city_name);  
  46.         publishText = (TextView) findViewById(R.id.publish_text);  
  47.         weatherDespText = (TextView) findViewById(R.id.weather_desp);  
  48.         temp1Text = (TextView) findViewById(R.id.temp1);  
  49.         temp2Text = (TextView) findViewById(R.id.temp2);  
  50.         currentDateText = (TextView) findViewById(R.id.current_date);  
  51.         switchCity = (Button) findViewById(R.id.switch_city);  
  52.         refreshWeather = (Button) findViewById(R.id.refresh_weather);  
  53.         String countyCode = getIntent().getStringExtra("county_code");  
  54.         if (!TextUtils.isEmpty(countyCode)) {  
  55.             // 有县级代号时就去查询天气  
  56.             publishText.setText("同步中...");  
  57.             weatherInfoLayout.setVisibility(View.INVISIBLE);  
  58.             cityNameText.setVisibility(View.INVISIBLE);  
  59.             queryWeatherCode(countyCode);  
  60.         } else {  
  61.             // 没有县级代号时就直接显示本地天气  
  62.             showWeather();  
  63.         }  
  64.         switchCity = (Button) findViewById(R.id.switch_city);  
  65.         refreshWeather = (Button) findViewById(R.id.refresh_weather);  
  66.         switchCity.setOnClickListener(this);  
  67.         refreshWeather.setOnClickListener(this);  
  68.     }  
  69.       
  70.     @Override  
  71.     public void onClick(View v) {  
  72.         switch (v.getId()) {  
  73.         case R.id.switch_city:  
  74.             Intent intent = new Intent(this, ChooseAreaActivity.class);  
  75.             intent.putExtra("from_weather_activity"true);  
  76.             startActivity(intent);  
  77.             finish();  
  78.             break;  
  79.         case R.id.refresh_weather:  
  80.             publishText.setText("同步中...");  
  81.             SharedPreferences prefs = PreferenceManager. getDefaultSharedPreferences(this);  
  82.             String weatherCode = prefs.getString("weather_code""");  
  83.             if (!TextUtils.isEmpty(weatherCode)) {  
  84.                 queryWeatherInfo(weatherCode);  
  85.             }  
  86.             break;  
  87.         default:  
  88.             break;  
  89.         }  
  90.     }  
  91.       
  92.     /** 
  93.      * 查询县级代号所对应的天气代号。 
  94.      */  
  95.     private void queryWeatherCode(String countyCode) {  
  96.         String address = "http://www.weather.com.cn/data/list3/city" + countyCode + ".xml";  
  97.         queryFromServer(address, "countyCode");  
  98.     }  
  99.   
  100.     /** 
  101.      * 查询天气代号所对应的天气。 
  102.      */  
  103.     private void queryWeatherInfo(String weatherCode) {  
  104.         String address = "http://www.weather.com.cn/data/cityinfo/" + weatherCode + ".html";  
  105.         queryFromServer(address, "weatherCode");  
  106.     }  
  107.       
  108.     /** 
  109.      * 根据传入的地址和类型去向服务器查询天气代号或者天气信息。 
  110.      */  
  111.     private void queryFromServer(final String address, final String type) {  
  112.         HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {  
  113.             @Override  
  114.             public void onFinish(final String response) {  
  115.                 if ("countyCode".equals(type)) {  
  116.                     if (!TextUtils.isEmpty(response)) {  
  117.                         // 从服务器返回的数据中解析出天气代号  
  118.                         String[] array = response.split("\\|");  
  119.                         if (array != null && array.length == 2) {  
  120.                             String weatherCode = array[1];  
  121.                             queryWeatherInfo(weatherCode);  
  122.                         }  
  123.                     }  
  124.                 } else if ("weatherCode".equals(type)) {  
  125.                     // 处理服务器返回的天气信息  
  126.                     Utility.handleWeatherResponse(WeatherActivity.this, response);  
  127.                     runOnUiThread(new Runnable() {  
  128.                         @Override  
  129.                         public void run() {  
  130.                             showWeather();  
  131.                         }  
  132.                     });  
  133.                 }  
  134.             }  
  135.               
  136.             @Override  
  137.             public void onError(Exception e) {  
  138.                 runOnUiThread(new Runnable() {  
  139.                     @Override  
  140.                     public void run() {  
  141.                         publishText.setText("同步失败");  
  142.                     }  
  143.                 });  
  144.             }  
  145.         });   
  146. }  
  147.       
  148.     /** 
  149.      * 从SharedPreferences文件中读取存储的天气信息,并显示到界面上。 
  150.      */  
  151.     private void showWeather() {  
  152.         SharedPreferences prefs = PreferenceManager. getDefaultSharedPreferences(this);  
  153.         cityNameText.setText( prefs.getString("city_name"""));  
  154.         temp1Text.setText(prefs.getString("temp1"""));  
  155.         temp2Text.setText(prefs.getString("temp2"""));  
  156.         weatherDespText.setText(prefs.getString("weather_desp"""));  
  157.         publishText.setText("今天" + prefs.getString("publish_time""") + "发布");  
  158.         currentDateText.setText(prefs.getString("current_date"""));  
  159.         weatherInfoLayout.setVisibility(View.VISIBLE);  
  160.         cityNameText.setVisibility(View.VISIBLE);  
  161.         Intent intent = new Intent(this, AutoUpdateService.class);  
  162.         startService(intent);  
  163.     }  
  164.   
  165. }  
  166.   
  167. <pre class="java" name="code"><span style="color:#6666cc;">ChooseAreaActivity.java</span></pre>  
  168. <pre></pre>  
  169. <p></p>  
  170. <pre></pre>  
  171. <pre class="java" name="code">public class ChooseAreaActivity extends Activity {  
  172.   
  173.     public static final int LEVEL_PROVINCE = 0;  
  174.     public static final int LEVEL_CITY = 1;  
  175.     public static final int LEVEL_COUNTY = 2;  
  176.   
  177.     private ProgressDialog progressDialog;  
  178.     private TextView titleText;  
  179.     private ListView listView;  
  180.     private ArrayAdapter<String> adapter;  
  181.     private CoolWeatherDB coolWeatherDB;  
  182.     private List<String> dataList = new ArrayList<String>();  
  183.     /** 
  184.      * 省列表 
  185.      */  
  186.     private List<Province> provinceList;  
  187.     /** 
  188.      * 市列表 
  189.      */  
  190.     private List<City> cityList;  
  191.     /** 
  192.      * 县列表 
  193.      */  
  194.     private List<County> countyList;  
  195.     /** 
  196.      * 选中的省份 
  197.      */  
  198.     private Province selectedProvince;  
  199.     /** 
  200.      * 选中的城市 
  201.      */  
  202.     private City selectedCity;  
  203.     /** 
  204.      * 当前选中的级别 
  205.      */  
  206.     private int currentLevel;  
  207.     /** 
  208.      * 是否从WeatherActivity中跳转过来。 
  209.      */  
  210.     private boolean isFromWeatherActivity;  
  211.   
  212.     @Override  
  213.     protected void onCreate(Bundle savedInstanceState) {  
  214.         super.onCreate(savedInstanceState);  
  215.         isFromWeatherActivity = getIntent().getBooleanExtra(  
  216.                 "from_weather_ activity"false);  
  217.         SharedPreferences prefs = PreferenceManager  
  218.                 .getDefaultSharedPreferences(this);  
  219.         // 已经选择了城市且不是从WeatherActivity跳转过来,才会直接跳转到WeatherActivity  
  220.         if (prefs.getBoolean("city_selected"false) && !isFromWeatherActivity) {  
  221.             Intent intent = new Intent(this, WeatherActivity.class);  
  222.             startActivity(intent);  
  223.             finish();  
  224.             return;  
  225.         }  
  226.   
  227.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  228.         setContentView(R.layout.choose_area);  
  229.         listView = (ListView) findViewById(R.id.list_view);  
  230.         titleText = (TextView) findViewById(R.id.title_text);  
  231.         adapter = new ArrayAdapter<String>(this,  
  232.                 android.R.layout.simple_list_item_1, dataList);  
  233.         listView.setAdapter(adapter);  
  234.         coolWeatherDB = CoolWeatherDB.getInstance(this);  
  235.         listView.setOnItemClickListener(new OnItemClickListener() {  
  236.             @Override  
  237.             public void onItemClick(AdapterView<?> arg0, View view, int index,  
  238.                     long arg3) {  
  239.                 if (currentLevel == LEVEL_PROVINCE) {  
  240.                     selectedProvince = provinceList.get(index);  
  241.                     queryCities();  
  242.                 } else if (currentLevel == LEVEL_CITY) {  
  243.                     selectedCity = cityList.get(index);  
  244.                     queryCounties();  
  245.                 } else if (currentLevel == LEVEL_COUNTY) {  
  246.                     String countyCode = countyList.get(index).getCountyCode();  
  247.                     Intent intent = new Intent(ChooseAreaActivity.this,  
  248.                             WeatherActivity.class);  
  249.                     intent.putExtra("county_code", countyCode);  
  250.                     startActivity(intent);  
  251.                     finish();  
  252.                 }  
  253.             }  
  254.         });  
  255.         queryProvinces(); // 加载省级数据  
  256.     }  
  257.   
  258.     /** 
  259.      * 查询全国所有的省,优先从数据库查询,如果没有查询到再去服务器上查询。 
  260.      */  
  261.     private void queryProvinces() {  
  262.         provinceList = coolWeatherDB.loadProvinces();  
  263.         if (provinceList.size() > 0) {  
  264.             dataList.clear();  
  265.             for (Province province : provinceList) {  
  266.                 dataList.add(province.getProvinceName());  
  267.             }  
  268.             adapter.notifyDataSetChanged();  
  269.             listView.setSelection(0);  
  270.             titleText.setText("中国");  
  271.             currentLevel = LEVEL_PROVINCE;  
  272.         } else {  
  273.             queryFromServer(null"province");  
  274.         }  
  275.     }  
  276.   
  277.     /** 
  278.      * 查询选中省内所有的市,优先从数据库查询,如果没有查询到再去服务器上查询。 
  279.      */  
  280.     private void queryCities() {  
  281.         cityList = coolWeatherDB.loadCities(selectedProvince.getId());  
  282.         if (cityList.size() > 0) {  
  283.             dataList.clear();  
  284.             for (City city : cityList) {  
  285.                 dataList.add(city.getCityName());  
  286.             }  
  287.             adapter.notifyDataSetChanged();  
  288.             listView.setSelection(0);  
  289.             titleText.setText(selectedProvince.getProvinceName());  
  290.             currentLevel = LEVEL_CITY;  
  291.         } else {  
  292.             queryFromServer(selectedProvince.getProvinceCode(), "city");  
  293.         }  
  294.     }  
  295.   
  296.     /** 
  297.      * 查询选中市内所有的县,优先从数据库查询,如果没有查询到再去服务器上查询。 
  298.      */  
  299.     private void queryCounties() {  
  300.         countyList = coolWeatherDB.loadCounties(selectedCity.getId());  
  301.         if (countyList.size() > 0) {  
  302.             dataList.clear();  
  303.             for (County county : countyList) {  
  304.                 dataList.add(county.getCountyName());  
  305.             }  
  306.             adapter.notifyDataSetChanged();  
  307.             listView.setSelection(0);  
  308.             titleText.setText(selectedCity.getCityName());  
  309.             currentLevel = LEVEL_COUNTY;  
  310.         } else {  
  311.             queryFromServer(selectedCity.getCityCode(), "county");  
  312.         }  
  313.     }  
  314.   
  315.     /** 
  316.      * 根据传入的代号和类型从服务器上查询省市县数据。 
  317.      */  
  318.     private void queryFromServer(final String code, final String type) {  
  319.         String address;  
  320.         if (!TextUtils.isEmpty(code)) {  
  321.             address = "http://www.weather.com.cn/data/list3/city" + code  
  322.                     + ".xml";  
  323.         } else {  
  324.             address = "http://www.weather.com.cn/data/list3/city.xml";  
  325.         }  
  326.         showProgressDialog();  
  327.         HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {  
  328.             @Override  
  329.             public void onFinish(String response) {  
  330.                 boolean result = false;  
  331.                 if ("province".equals(type)) {  
  332.                     result = Utility.handleProvincesResponse(coolWeatherDB,  
  333.                             response);  
  334.                 } else if ("city".equals(type)) {  
  335.                     result = Utility.handleCitiesResponse(coolWeatherDB,  
  336.                             response, selectedProvince.getId());  
  337.                 } else if ("county".equals(type)) {  
  338.                     result = Utility.handleCountiesResponse(coolWeatherDB,  
  339.                             response, selectedCity.getId());  
  340.                 }  
  341.                 if (result) {  
  342.                     // 通过runOnUiThread()方法回到主线程处理逻辑  
  343.                     runOnUiThread(new Runnable() {  
  344.                         @Override  
  345.                         public void run() {  
  346.                             closeProgressDialog();  
  347.                             if ("province".equals(type)) {  
  348.                                 queryProvinces();  
  349.                             } else if ("city".equals(type)) {  
  350.                                 queryCities();  
  351.                             } else if ("county".equals(type)) {  
  352.                                 queryCounties();  
  353.                             }  
  354.                         }  
  355.                     });  
  356.                 }  
  357.             }  
  358.   
  359.             @Override  
  360.             public void onError(Exception e) {  
  361.                 // 通过runOnUiThread()方法回到主线程处理逻辑  
  362.                 runOnUiThread(new Runnable() {  
  363.                     @Override  
  364.                     public void run() {  
  365.                         closeProgressDialog();  
  366.                         Toast.makeText(ChooseAreaActivity.this"加载失败",  
  367.                                 Toast.LENGTH_SHORT).show();  
  368.                     }  
  369.                 });  
  370.             }  
  371.         });  
  372.     }  
  373.   
  374.     /** 
  375.      * 显示进度对话框 
  376.      */  
  377.     private void showProgressDialog() {  
  378.         if (progressDialog == null) {  
  379.             progressDialog = new ProgressDialog(this);  
  380.             progressDialog.setMessage("正在加载...");  
  381.             progressDialog.setCanceledOnTouchOutside(false);  
  382.         }  
  383.         progressDialog.show();  
  384.     }  
  385.   
  386.     /** 
  387.      * 关闭进度对话框 
  388.      */  
  389.     private void closeProgressDialog() {  
  390.         if (progressDialog != null) {  
  391.             progressDialog.dismiss();  
  392.         }  
  393.     }  
  394.   
  395.     /** 
  396.      * 捕获Back按键,根据当前的级别来判断,此时应该返回市列表、省列表、还是直接退出。 
  397.      */  
  398.     @Override  
  399.     public void onBackPressed() {  
  400.         if (currentLevel == LEVEL_COUNTY) {  
  401.             queryCities();  
  402.         } else if (currentLevel == LEVEL_CITY) {  
  403.             queryProvinces();  
  404.         } else {  
  405.             if (isFromWeatherActivity) {  
  406.                 Intent intent = new Intent(this, WeatherActivity.class);  
  407.                 startActivity(intent);  
  408.             }  
  409.             finish();  
  410.         }  
  411.     }  
  412.   
  413. }</pre><pre class="java" name="code"><pre class="html" name="code"></pre><span style="color:#ff0000">weather_layout.java</span><br>  
  414. <pre class="java" name="code"><?xml version="1.0" encoding="utf-8"?>  
  415. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  416.     android:layout_width="match_parent"  
  417.     android:layout_height="match_parent"  
  418.     android:orientation="vertical" >  
  419.     <RelativeLayout  
  420.         android:layout_width="match_parent"  
  421.         android:layout_height="50dp"  
  422.         android:background="#484E61" >  
  423.           <Button  
  424.             android:id="@+id/switch_city"  
  425.             android:layout_width="30dp"  
  426.             android:layout_height="30dp"  
  427.             android:layout_centerVertical="true"  
  428.             android:layout_marginLeft="10dp"  
  429.             android:background="@drawable/home" />  
  430.   
  431.         <TextView  
  432.             android:id="@+id/city_name"  
  433.             android:layout_width="wrap_content"  
  434.             android:layout_height="wrap_content"  
  435.             android:layout_centerInParent="true"  
  436.             android:textColor="#fff"  
  437.             android:textSize="24sp" />  
  438.          <Button  
  439.             android:id="@+id/refresh_weather"  
  440.             android:layout_width="30dp"  
  441.             android:layout_height="30dp"  
  442.             android:layout_alignParentRight="true"  
  443.             android:layout_centerVertical="true"  
  444.             android:layout_marginRight="10dp"  
  445.             android:background="@drawable/refresh" />  
  446.     </RelativeLayout>  
  447.   
  448.     <RelativeLayout  
  449.         android:layout_width="match_parent"  
  450.         android:layout_height="0dp"  
  451.         android:layout_weight="1"  
  452.         android:background="#27A5F9" >  
  453.   
  454.         <TextView  
  455.             android:id="@+id/publish_text"  
  456.             android:layout_width="wrap_content"  
  457.             android:layout_height="wrap_content"  
  458.             android:layout_alignParentRight="true"  
  459.             android:layout_marginRight="10dp"  
  460.             android:layout_marginTop="10dp"  
  461.             android:textColor="#FFF"  
  462.             android:textSize="18sp" />  
  463.   
  464.         <LinearLayout  
  465.             android:id="@+id/weather_info_layout"  
  466.             android:layout_width="wrap_content"  
  467.             android:layout_height="wrap_content"  
  468.             android:layout_centerInParent="true"  
  469.             android:orientation="vertical" >  
  470.   
  471.             <TextView  
  472.                 android:id="@+id/current_date"  
  473.                 android:layout_width="wrap_content"  
  474.                 android:layout_height="40dp"  
  475.                 android:gravity="center"  
  476.                 android:textColor="#FFF"  
  477.                 android:textSize="18sp" />  
  478.   
  479.             <TextView  
  480.                 android:id="@+id/weather_desp"  
  481.                 android:layout_width="wrap_content"  
  482.                 android:layout_height="60dp"  
  483.                 android:layout_gravity="center_horizontal"  
  484.                 android:gravity="center"  
  485.                 android:textColor="#FFF"  
  486.                 android:textSize="40sp" />  
  487.   
  488.             <LinearLayout  
  489.                 android:layout_width="wrap_content"  
  490.                 android:layout_height="60dp"  
  491.                 android:layout_gravity="center_horizontal"  
  492.                 android:orientation="horizontal" >  
  493.   
  494.                 <TextView  
  495.                     android:id="@+id/temp1"  
  496.                     android:layout_width="wrap_content"  
  497.                     android:layout_height="wrap_content"  
  498.                     android:layout_gravity="center_vertical"  
  499.                     android:textColor="#FFF"  
  500.                     android:textSize="40sp" />  
  501.   
  502.                 <TextView  
  503.                     android:layout_width="wrap_content"  
  504.                     android:layout_height="wrap_content"  
  505.                     android:layout_gravity="center_vertical"  
  506.                     android:layout_marginLeft="10dp"  
  507.                     android:layout_marginRight="10dp"  
  508.                     android:text="~"  
  509.                     android:textColor="#FFF"  
  510.                     android:textSize="40sp" />  
  511.   
  512.                 <TextView  
  513.                     android:id="@+id/temp2"  
  514.                     android:layout_width="wrap_content"  
  515.                     android:layout_height="wrap_content"  
  516.                     android:layout_gravity="center_vertical"  
  517.                     android:textColor="#FFF"  
  518.                     android:textSize="40sp" />  
  519.             </LinearLayout>  
  520.         </LinearLayout>  
  521.     </RelativeLayout>  
  522.   
  523. </LinearLayout>  
  524. </pre>  
  525. <p> </p>  
  526. <br>  
  527. <pre></pre>  
  528. <pre></pre>  
  529.      
  530. </pre>  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值