一、需求
选择城市获得相应城市最近几天的天气预报
数据源:
1、全国城市列表xml -----http://yunpan.cn/cmMA5DrFeM4m6 (提取码:ccb1)
2、天气json数据源 http://weather.xcyh.org/101210401/json/6 101210401部分为城市的编号
二、设计思路
三个下拉列表 分别显示省、市、县的名字,一个按钮 为查询 一个ListView显示最近该城市几天的天气预报
xml解析获取城市名称集合,json解析获取天气
1、点击省列表选择省,对应市列表和县列表名跟随变化
2、点击市列表选择市,对应县列表名跟随变化
3、点击查询按钮,获得当前县名的天气预报数据,显示在ListView控件中 (每一个县都有一个id,根据该id获得天气数据的网址,获得json解析并显示)
效果图:
三、Demo代码
1、布局文件
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 > 7 8 <LinearLayout 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:orientation="horizontal" 12 > 13 <Spinner 14 android:layout_width="0dp" 15 android:layout_weight="1" 16 android:layout_height="wrap_content" 17 android:id="@+id/province" 18 /> 19 <Spinner 20 android:layout_width="0dp" 21 android:layout_weight="1" 22 android:layout_height="wrap_content" 23 android:id="@+id/city" 24 /> 25 <Spinner 26 android:layout_width="0dp" 27 android:layout_weight="1" 28 android:layout_height="wrap_content" 29 android:id="@+id/district" 30 /> 31 <Button 32 android:layout_width="wrap_content" 33 android:layout_height="wrap_content" 34 android:id="@+id/submit" 35 android:text="@string/select" 36 /> 37 </LinearLayout> 38 39 <LinearLayout 40 android:layout_width="match_parent" 41 android:layout_height="wrap_content" 42 android:orientation="vertical" 43 > 44 <ListView 45 android:layout_width="match_parent" 46 android:layout_height="wrap_content" 47 android:id="@+id/id_listview" 48 ></ListView> 49 50 </LinearLayout> 51 </LinearLayout>
activity_main
2、实体类(省类,市类,县类)
1 package entity; 2 3 import java.util.List; 4 5 public class Province { 6 //根据城市xml文件可知, 省有id ,省名 ,该省所有的市集合 三个属性 7 private String id; 8 private String name; 9 private List<City> citys; 10 public Province() { 11 super(); 12 // TODO Auto-generated constructor stub 13 } 14 public Province(String id, String name, List<City> citys) { 15 super(); 16 this.id = id; 17 this.name = name; 18 this.citys = citys; 19 } 20 public String getId() { 21 return id; 22 } 23 public void setId(String id) { 24 this.id = id; 25 } 26 public String getName() { 27 return name; 28 } 29 public void setName(String name) { 30 this.name = name; 31 } 32 public List<City> getCitys() { 33 return citys; 34 } 35 public void setCitys(List<City> citys) { 36 this.citys = citys; 37 } 38 @Override 39 public String toString() { 40 return name; 41 } 42 43 44 45 }
Province.class
1 package entity; 2 3 import java.util.List; 4 5 public class City { 6 //根据城市xml文件可知,市 有id,市名,该市所有的县 的集合 三个属性 7 private String id; 8 private String name; 9 private List<District> districts; 10 public City() { 11 super(); 12 // TODO Auto-generated constructor stub 13 } 14 public City(String id, String name, List<District> districts) { 15 super(); 16 this.id = id; 17 this.name = name; 18 this.districts = districts; 19 } 20 public String getId() { 21 return id; 22 } 23 public void setId(String id) { 24 this.id = id; 25 } 26 public String getName() { 27 return name; 28 } 29 public void setName(String name) { 30 this.name = name; 31 } 32 public List<District> getDistricts() { 33 return districts; 34 } 35 public void setDistricts(List<District> districts) { 36 this.districts = districts; 37 } 38 @Override 39 public String toString() { 40 return name; 41 } 42 43 44 45 }
City.class
1 package entity; 2 3 import java.util.Arrays; 4 5 public class District { 6 //根据城市XML文件可知 县有 id,县名 两个属性 7 private String id; 8 private String name; 9 10 //根据天气数据源和需求可知,县还具有 日期,天气,温度,风向 四个属性 ,每一个属性包含该县最近几天的相应情况 11 private String date[] = new String[6]; 12 private String weather[] = new String[6]; 13 private String temperature[] = new String[6]; 14 private String winddirect[] = new String[6]; 15 public District() { 16 super(); 17 // TODO Auto-generated constructor stub 18 } 19 public District(String id, String name, String[] date, String[] weather, 20 String[] temperature, String[] winddirect) { 21 super(); 22 this.id = id; 23 this.name = name; 24 this.date = date; 25 this.weather = weather; 26 this.temperature = temperature; 27 this.winddirect = winddirect; 28 } 29 public String getId() { 30 return id; 31 } 32 public void setId(String id) { 33 this.id = id; 34 } 35 public String getName() { 36 return name; 37 } 38 public void setName(String name) { 39 this.name = name; 40 } 41 public String[] getDate() { 42 return date; 43 } 44 public void setDate(String[] date) { 45 this.date = date; 46 } 47 public String[] getWeather() { 48 return weather; 49 } 50 public void setWeather(String[] weather) { 51 this.weather = weather; 52 } 53 public String[] getTemperature() { 54 return temperature; 55 } 56 public void setTemperature(String[] temperature) { 57 this.temperature = temperature; 58 } 59 public String[] getWinddirect() { 60 return winddirect; 61 } 62 public void setWinddirect(String[] winddirect) { 63 this.winddirect = winddirect; 64 } 65 @Override 66 public String toString() { 67 return name; 68 } 69 70 71 72 73 }
District.class
3、解析城市列表xml文件的自定义工具类
1 package tools; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import org.xmlpull.v1.XmlPullParser; 8 import org.xmlpull.v1.XmlPullParserException; 9 import org.xmlpull.v1.XmlPullParserFactory; 10 11 import com.example.weather_day.R; 12 13 import android.content.Context; 14 import android.content.res.Resources; 15 import android.util.Log; 16 import entity.City; 17 import entity.District; 18 import entity.Province; 19 20 public class ParserTool { 21 //pull解析 22 private Context context; 23 public ParserTool(Context context) 24 { 25 this.context = context; 26 } 27 public static List PullParser(Context context) throws XmlPullParserException, IOException 28 { 29 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 30 XmlPullParser parser = factory.newPullParser(); 31 List<Province> provinces = null; 32 List<City> citys = null; 33 List<District> districts = null; 34 Province province = null; 35 City city = null; 36 District district =null; 37 38 //城市列表xml文件在res-raw文件夹下 39 Resources resources = context.getResources(); 40 parser.setInput(resources.openRawResource(R.raw.citys_weather),"utf-8"); 41 42 int event = parser.getEventType(); 43 44 while(event!=XmlPullParser.END_DOCUMENT) 45 { 46 switch (event) { 47 case XmlPullParser.START_DOCUMENT: 48 provinces = new ArrayList<Province>(); 49 50 break; 51 52 case XmlPullParser.START_TAG: 53 if("p".equals(parser.getName())) 54 { 55 province = new Province(); 56 citys = new ArrayList<City>(); 57 int count = parser.getAttributeCount(); 58 for(int i=0;i<count;i++) 59 { 60 String key = parser.getAttributeName(i); 61 String value = parser.getAttributeValue(i); 62 if("p_id".equals(key)) 63 { 64 province.setId(value); 65 } 66 } 67 // provinces.add(province); 68 } 69 else if("pn".equals(parser.getName())) 70 { 71 province.setName(parser.nextText()); 72 } 73 else if("c".equals(parser.getName())) 74 { 75 city = new City(); 76 districts = new ArrayList<District>(); 77 int count = parser.getAttributeCount(); 78 for(int i=0;i<count;i++) 79 { 80 81 String key = parser.getAttributeName(i); 82 String value = parser.getAttributeValue(i); 83 if("c_id".equals(key)) 84 { 85 city.setId(value); 86 } 87 } 88 // citys.add(city); 89 } 90 else if("cn".equals(parser.getName())) 91 { 92 city.setName(parser.nextText()); 93 } 94 else if("d".equals(parser.getName())) 95 { 96 district = new District(); 97 int count = parser.getAttributeCount(); 98 for(int i=0;i<count;i++) 99 { 100 String key = parser.getAttributeName(i); 101 String value = parser.getAttributeValue(i); 102 if("d_id".equals(key)) 103 { 104 district.setId(value); 105 } 106 } 107 district.setName(parser.nextText()); 108 districts.add(district); 109 } 110 break; 111 case XmlPullParser.END_TAG: 112 if("p".equals(parser.getName())) 113 { 114 province.setCitys(citys); 115 provinces.add(province); 116 } 117 else if("c".equals(parser.getName())) 118 { 119 city.setDistricts(districts); 120 citys.add(city); 121 } 122 123 124 break; 125 default: 126 break; 127 } 128 event = parser.next(); 129 } 130 //返回省的列表 131 return provinces; 132 } 133 }
ParserTool.class
4、解析网络天气数据源的自定义工具类
(1)、获取json字符串
1 package tools; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.UnsupportedEncodingException; 7 import java.net.HttpURLConnection; 8 import java.net.URL; 9 10 public class HttpUtil { 11 public static String getJsonString(String path) throws IOException{ 12 //参数为解析数据源的地址 13 URL url = new URL(path); 14 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 15 //GET连接 16 conn.setRequestMethod("GET"); 17 conn.setConnectTimeout(5000); 18 conn.setDoInput(true); 19 20 if(conn.getResponseCode()==200) 21 { 22 InputStream in = conn.getInputStream(); 23 return getJson(in); 24 } 25 return null; 26 } 27 28 public static String getJson(InputStream in ) throws IOException 29 { 30 //将解析后的数据写入内存 31 ByteArrayOutputStream out = new ByteArrayOutputStream(); 32 int len = 0; 33 byte b[] = new byte[1024]; 34 while((len=in.read(b))!=-1) 35 { 36 //不要写成out.write(b); 37 out.write(b,0,len); 38 } 39 //不要忘记第二个参数,避免乱码 40 return new String(out.toByteArray(),"utf-8"); 41 42 } 43 }
HttpUtil.class
(2)、解析json字符串
1 package tools; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import org.json.JSONArray; 7 import org.json.JSONException; 8 import org.json.JSONObject; 9 10 import android.util.Log; 11 12 import entity.District; 13 14 public class ParserJson { 15 public static District JsonString(String json) throws JSONException 16 { 17 JSONObject obj = new JSONObject(json); 18 JSONArray arr = obj.getJSONArray("data"); 19 District district2 = new District(); 20 String date[] = new String[6]; 21 String weather[] = new String[6]; 22 String temperature[] = new String[6]; 23 String winddirect[] = new String[6]; 24 /* 25 *思路为实体类 -县 具有日期date,天气weather,温度temperature,风向winddirect 四个属性 26 *每一个属性为一个字符串数据,存放该县近几天的对应数据 27 */ 28 for(int i=0;i<arr.length();i++) 29 { 30 JSONObject data = arr.getJSONObject(i); 31 date[i] = data.getString("date"); 32 weather[i] = data.getString("weather"); 33 temperature[i] = data.getString("temperature"); 34 winddirect[i] = data.getString("winddirect"); 35 } 36 district2.setDate(date); 37 district2.setWeather(weather); 38 district2.setTemperature(temperature); 39 district2.setWinddirect(winddirect); 40 //返回县 的对象 41 return district2; 42 } 43 }
ParserJson.class
5、异步任务
网络下载解析等耗时操作一定要放入异步任务中实现功能!
1 package Asynch; 2 3 import java.io.IOException; 4 import java.util.List; 5 6 import org.json.JSONException; 7 8 import tools.HttpUtil; 9 import tools.ParserJson; 10 import entity.District; 11 12 import android.content.Context; 13 import android.os.AsyncTask; 14 import android.util.Log; 15 import android.widget.ArrayAdapter; 16 import android.widget.ListView; 17 18 public class AsynchTaskWeather extends AsyncTask<String, Void, District>{ 19 20 private Context context; 21 private ListView listview; 22 List<District> list_district; 23 private District district; 24 public AsynchTaskWeather(Context context,ListView listview) 25 { 26 this.context =context; 27 this.listview = listview; 28 } 29 @Override 30 protected District doInBackground(String... params) { 31 // TODO Auto-generated method stub 32 //实现任务功能的方法 33 if(params[0]!=null) 34 { 35 String json; 36 try { 37 //获得json字符串 38 json = HttpUtil.getJsonString(params[0]); 39 //解析Json字符串返回该对象,该对象为一个县 包含该县近几天的天气情况 40 district = ParserJson.JsonString(json); 41 42 } catch (IOException e) { 43 // TODO Auto-generated catch block 44 e.printStackTrace(); 45 } catch (JSONException e) { 46 // TODO Auto-generated catch block 47 e.printStackTrace(); 48 } 49 } 50 return district; 51 } 52 53 @Override 54 protected void onPostExecute(District result) { 55 // TODO Auto-generated method stub 56 // Log.i("-------------------", result.toString()); 57 super.onPostExecute(result); 58 String date[] = result.getDate(); 59 String weather[] = result.getWeather(); 60 String temperature[] = result.getTemperature(); 61 String winddirect[] = result.getWinddirect(); 62 int n = date.length; 63 String arr[] = new String[6]; 64 //将返回对象的属性(天气温度风向等)放入字符串数组中作为listview适配器的数据源 65 for(int i=0;i<date.length;i++) 66 { 67 arr[i]=("日期:"+date[i]+"|天气:"+weather[i]+"|温度:"+temperature[i]+"|风向:"+winddirect[i]); 68 } 69 ArrayAdapter<String> ada = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1,arr); 70 listview.setAdapter(ada); 71 } 72 }
AsynchTaskWeather.class
6、主Activity
1 package com.example.weather_day; 2 3 import java.io.IOException; 4 import java.nio.channels.AsynchronousCloseException; 5 import java.util.List; 6 7 import org.json.JSONException; 8 import org.xmlpull.v1.XmlPullParserException; 9 10 import tools.HttpUtil; 11 import tools.ParserJson; 12 import tools.ParserTool; 13 import Asynch.AsynchTaskWeather; 14 import android.app.Activity; 15 import android.os.Bundle; 16 import android.view.View; 17 import android.view.View.OnClickListener; 18 import android.widget.AdapterView; 19 import android.widget.AdapterView.OnItemSelectedListener; 20 import android.widget.ArrayAdapter; 21 import android.widget.Button; 22 import android.widget.ListView; 23 import android.widget.Spinner; 24 import entity.City; 25 import entity.District; 26 import entity.Province; 27 28 public class MainActivity extends Activity { 29 30 private Spinner spinner_province; 31 private Spinner spinner_city; 32 private Spinner spinner_district; 33 private ListView listview; 34 35 private Button btn_submit; 36 37 int province = 0; 38 int city = 0; 39 int district = 0; 40 41 List<Province> list; 42 @Override 43 protected void onCreate(Bundle savedInstanceState) { 44 super.onCreate(savedInstanceState); 45 setContentView(R.layout.activity_main); 46 47 initView(); 48 49 50 51 try { 52 list = ParserTool.PullParser(this); 53 54 ArrayAdapter<Province> ada_province = new ArrayAdapter<Province>(this, android.R.layout.simple_list_item_1,list); 55 spinner_province.setAdapter(ada_province); 56 57 ArrayAdapter<City> ada_city = new ArrayAdapter<City>(this, android.R.layout.simple_list_item_1,list.get(0).getCitys()); 58 spinner_city.setAdapter(ada_city); 59 60 ArrayAdapter<District> ada_districy = new ArrayAdapter<District>(this, android.R.layout.simple_list_item_1,list.get(0).getCitys().get(0).getDistricts()); 61 spinner_district.setAdapter(ada_districy); 62 63 spinner_province.setOnItemSelectedListener(new OnItemSelectedListener() { 64 65 @Override 66 public void onItemSelected(AdapterView<?> arg0, View arg1, 67 int arg2, long arg3) { 68 // TODO Auto-generated method stub 69 province = arg2; 70 ArrayAdapter<City> ada_city = new ArrayAdapter<City>(MainActivity.this, android.R.layout.simple_list_item_1,list.get(province).getCitys()); 71 spinner_city.setAdapter(ada_city); 72 73 } 74 75 @Override 76 public void onNothingSelected(AdapterView<?> arg0) { 77 // TODO Auto-generated method stub 78 79 } 80 }); 81 82 spinner_city.setOnItemSelectedListener(new OnItemSelectedListener() { 83 84 @Override 85 public void onItemSelected(AdapterView<?> arg0, View arg1, 86 int arg2, long arg3) { 87 // TODO Auto-generated method stub 88 city = arg2; 89 ArrayAdapter<District> ada_district = new ArrayAdapter<District>(MainActivity.this, android.R.layout.simple_list_item_1,list.get(province).getCitys().get(city).getDistricts()); 90 spinner_district.setAdapter(ada_district); 91 } 92 93 @Override 94 public void onNothingSelected(AdapterView<?> arg0) { 95 // TODO Auto-generated method stub 96 97 } 98 }); 99 100 spinner_district.setOnItemSelectedListener(new OnItemSelectedListener() { 101 102 @Override 103 public void onItemSelected(AdapterView<?> arg0, View arg1, 104 int arg2, long arg3) { 105 // TODO Auto-generated method stub 106 district = arg2; 107 } 108 109 @Override 110 public void onNothingSelected(AdapterView<?> arg0) { 111 // TODO Auto-generated method stub 112 113 } 114 }); 115 116 btn_submit.setOnClickListener(new OnClickListener() { 117 118 @Override 119 public void onClick(View v) { 120 // TODO Auto-generated method stub 121 String id = list.get(province).getCitys().get(city).getDistricts().get(district).getId(); 122 String path = "http://weather.xcyh.org/"+id+"/json/6"; 123 new AsynchTaskWeather(MainActivity.this, listview).execute(path); 124 125 } 126 }); 127 128 } catch (XmlPullParserException e) { 129 // TODO Auto-generated catch block 130 e.printStackTrace(); 131 } catch (IOException e) { 132 // TODO Auto-generated catch block 133 e.printStackTrace(); 134 } 135 136 137 } 138 private void initView() { 139 spinner_province = (Spinner) findViewById(R.id.province); 140 spinner_city = (Spinner) findViewById(R.id.city); 141 spinner_district = (Spinner) findViewById(R.id.district); 142 btn_submit = (Button) findViewById(R.id.submit); 143 listview = (ListView) findViewById(R.id.id_listview); 144 } 145 146 147 148 }
时间: 2024-10-21 03:16:49