遍历全国省市县数据
新建布局choose_area.xml文件
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#484E61" > <TextView android:id="@+id/title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="#fff" android:textSize="24sp" /> </RelativeLayout> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" > </ListView> </LinearLayout>
省市县的数据就将显示在ListView里。
接着新建ChooseAreaActivity继承自Activity,用于遍历各省市县的数据的活动。
定义成员变量:
public static final int LEVEL_PROVINCE = 0; publicstatic final int LEVEL_CITY = 1; publicstatic final int LEVEL_COUNTY = 2; privateProgressDialog progressDialog; privateTextView titleText; privateListView listView; privateArrayAdapter<String> adapter; privateCoolWeatherDB coolWeatherDB; privateList<String> dataList = new ArrayList<String>(); /** * 省列表 */ privateList<Province> provinceList; /** * 市列表 */ privateList<City> cityList; /** * 县列表 */ privateList<County> countyList; /** * 选中的省份 */ privateProvince selectedProvince; /** * 选中的城市 */ privateCity selectedCity; /** * 当前选中的级别 */ privateint currentLevel; protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); isFromWeatherActivity= getIntent().getBooleanExtra("from_weather_activity", false); SharedPreferencesprefs = PreferenceManager.getDefaultSharedPreferences(this); if(prefs.getBoolean("city_selected", false) &&!isFromWeatherActivity) { Intentintent = new Intent(this, WeatherActivity.class); startActivity(intent); finish(); return; } requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.choose_area); listView= (ListView) findViewById(R.id.list_view); titleText= (TextView) findViewById(R.id.title_text); adapter= new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,dataList); listView.setAdapter(adapter); coolWeatherDB= CoolWeatherDB.getInstance(this); listView.setOnItemClickListener(newOnItemClickListener() { @Override publicvoid onItemClick(AdapterView<?> arg0, View view, int index, longarg3) { if(currentLevel == LEVEL_PROVINCE) { selectedProvince= provinceList.get(index); queryCities(); }else if (currentLevel == LEVEL_CITY) { selectedCity= cityList.get(index); queryCounties(); }else if (currentLevel == LEVEL_COUNTY) { StringcountyCode = countyList.get(index).getCountyCode(); Intentintent = new Intent(ChooseAreaActivity.this, WeatherActivity.class); intent.putExtra("county_code",countyCode); startActivity(intent); finish(); } } }); queryProvinces(); // 加载省级数据 } /** * 查询全国所有的省,优先从数据库查询,如果没有查询到再去服务器上查询。 */ privatevoid queryProvinces() { provinceList= coolWeatherDB.loadProvinces(); if(provinceList.size() > 0) { dataList.clear();//防止之前的dataList携带数据 for(Province province : provinceList) { dataList.add(province.getProvinceName()); } adapter.notifyDataSetChanged(); listView.setSelection(0);//实现第一行居顶 titleText.setText("中国"); currentLevel= LEVEL_PROVINCE; }else { queryFromServer(null,"province"); } }
在onCreate方法中显示获取到了一些控件的实例,然后去初始化了ArrayAdapter,将它设置为ListView的适配器。之后又去获取到了 CoolWeatherDB 的实例,并给 ListView设置了点击事件,到这里我们的初始化工作就算是完成了。在 onCreate()方法的最后,调用了 queryProvinces()方法,也就是从这里开始加载省级数据的。queryProvinces()方法的内部会首先调用 CoolWeatherDB的 loadProvinces()方法来从数据库中读取省级数据,如果读取到了就直接将数据显示到界面上,如果没有读取到就调用queryFromServer()方法来从服务器上查询数据。
根据传入的代号和类型从服务器上查询省市县数据。
private void queryFromServer(final Stringcode, final String type) { Stringaddress; 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"; } showProgressDialog(); HttpUtil.sendHttpRequest(address,new HttpCallbackListener() { @Override publicvoid onFinish(String response) { booleanresult = false; if("province".equals(type)) { result= Utility.handleProvincesResponse(coolWeatherDB, response); }else if ("city".equals(type)) { result= Utility.handleCitiesResponse(coolWeatherDB, response,selectedProvince.getId()); }else if ("county".equals(type)) { result= Utility.handleCountiesResponse(coolWeatherDB, response,selectedCity.getId()); } if(result) { //通过runOnUiThread()方法回到主线程处理逻辑 runOnUiThread(newRunnable() { @Override publicvoid run() { closeProgressDialog(); if("province".equals(type)) { queryProvinces(); }else if ("city".equals(type)) { queryCities(); }else if ("county".equals(type)) { queryCounties(); } } }); } } @Override publicvoid onError(Exception e) { //通过runOnUiThread()方法回到主线程处理逻辑 runOnUiThread(newRunnable() { @Override publicvoid run() { closeProgressDialog(); Toast.makeText(ChooseAreaActivity.this, "加载失败",Toast.LENGTH_SHORT).show(); } }); } }); }
queryFromServer()方法会先根据传入的参数来拼装查询地址,确定了查询地址之后,接下来就调用 HttpUtil 的 sendHttpRequest()方法来向服务器发送请求,响应的数据会回调到 onFinish()方法中,然后我们在这里去调用 Utility 的handleProvincesResponse()方法来解析和处理服务器返回的数据,并存储到数据库中。接下来的一步很关键, 在解析和处理完数据之后, 我们再次调用了queryProvinces()方法来重新加载省级数据,由于 queryProvinces()方法牵扯到了 UI操作,因此必须要在主线程中调用,这里借助了 runOnUiThread()方法来实现从子线程切换到主线程,它的实现原理其实也是基于异步消息处理机制的。现在数据库中已经存在了数据,因此调用 queryProvinces()就会直接将数据显示到界面上了。当你点击了某个省的时候会进入到 ListView的 onItemClick()方法中,这个时候会根据当前的级别来判断是去调用 queryCities()方法还是 queryCounties()方法,queryCities()方法是去查询市级数据,而 queryCounties()方法是去查询县级数据,这两个方法内部的流程和queryProvinces()方法基本相同,这里就不重复讲解了。
配置 AndroidManifest.xml 文件:
<uses-permissionandroid:name="android.permission.INTERNET" /> android:name="com.coolweather.app.activity.ChooseAreaActivity"