您的位置:首页 > 移动开发 > Android开发

Android天气预报程序(四)

2016-04-16 10:24 489 查看
现在我们可以开始写界面了

在res/layout目录中新建choose_area.xml布局,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns: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_content"
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>


我们先是定义了一个50dp高的头布局,在里面放置了一个TextView用于显示标题内容
然后在头布局下面定义了一个ListView,省市县的数据就将显示在这里

接下来就要编写用于遍历省市县数据的活动了

在activity包下新建ChooseAreaActivity继承自Activity,代码如下所示:

public class ChooseAreaActivity extends Activity {

public static final int LEVEL_PROVINCE = 0;

public static final int LEVEL_CITY = 1;

public static final int LEVEL_COUNTY = 2;

private ProgressDialog progressDialog;

private TextView titleText;

private ListView listView;

private ArrayAdapter<String> adapter;

private CoolWeatherDB coolWeatherDB;

private List<String> dataList = new ArrayList<String>();

/**
* 	省列表
*/
private List<Province> provinceList;

/**
* 	市列表
*/
private List<City> cityList;

/**
* 	县列表
*/
private List<County> countyList;

/**
* 	选中的省份
*/
private Province selectedProvince;

/**
* 	选中的城市
*/
private City selectedCity;

/**
* 	当前选中的级别
*/
private int currentLevel;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
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(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View view, int index, long arg3) {
if (currentLevel == LEVEL_PROVINCE) {
selectedProvince = provinceList.get(index);
queryCities();
} else if (currentLevel == LEVEL_CITY) {
selectedCity = cityList.get(index);
queryCounties();
}
}
});
queryProvinces(); // 加载省级数据
}

/**
* 	查询全国所有的省,优先从数据库查询,如果没有查询到再去服务器上查询
*/
private void queryProvinces() {
provinceList = coolWeatherDB.loadProvinces();
if (provinceList.size() > 0) {
dataList.clear();
for (Province province : provinceList) {
dataList.add(province.getProvinceName());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText("中国");
currentLevel = LEVEL_PROVINCE;
} else {
queryFromServer(null, "province");
}
}

/**
* 	查询选中省内所有的市,优先从数据库查询,如果没有查询到再去服务器上查询
*/
private void queryCities() {
cityList = coolWeatherDB.loadCities(selectedProvince.getId());
if (cityList.size() > 0) {
dataList.clear();
for (City city : cityList) {
dataList.add(city.getCityName());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText(selectedProvince.getProvinceName());
currentLevel = LEVEL_CITY;
} else {
queryFromServer(selectedProvince.getProvinceCode(), "city");
}
}

/**
* 	查询选中市内所有的县,优先从数据库查询,如果没有查询到再去服务器上查询
*/
private void queryCounties() {
countyList = coolWeatherDB.loadCounties(selectedCity.getId());
if (countyList.size() > 0) {
dataList.clear();
for (County county : countyList) {
dataList.add(county.getCountyName());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText(selectedCity.getCityName());
currentLevel = LEVEL_COUNTY;
} else {
queryFromServer(selectedCity.getCityCode(), "county");
}
}

/**
* 	根据传入的代号和类型从服务器上查询省市县数据
*/
private void queryFromServer(final String code, final String type) {
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";
}
showProgressDialog();
HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
@Override
public void onFinish(String response) {
boolean result = 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(new Runnable() {
@Override
public void run() {
closeProgressDialog();
if ("province".equals(type)) {
queryProvinces();
} else if ("city".equals(type)) {
queryCities();
} else if ("county".equals(type)) {
queryCounties();
}
}
});
}
}
@Override
public void onError(Exception e) {
// 通过runOnUiThread()方法回到主线程处理逻辑
runOnUiThread(new Runnable() {
@Override
public void run() {
closeProgressDialog();
Toast.makeText(ChooseAreaActivity.this, "加载失败", Toast.LENGTH_SHORT).show();
}
});
}
});
}

/**
* 	显示进度对话框
*/
private void showProgressDialog() {
if (progressDialog == null) {
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("正在加载...");
progressDialog.setCanceledOnTouchOutside(false);
}
progressDialog.show();
}

/**
* 	关闭进度对话框
*/
private void closeProgressDialog() {
if (progressDialog != null) {
progressDialog.dismiss();
}
}

/**
* 	捕获Back按键,根据当前的级别来判断,此时应该返回市列表、省列表、还是直接退出
*/
@Override
public void onBackPressed() {
if (currentLevel == LEVEL_COUNTY) {
queryCities();
} else if ( currentLevel == LEVEL_CITY) {
queryProvinces();
} else {
finish();
}
}

}


queryProvince()方法的内部会首先调用CoolWeatherDB的loadProvince()方法来从数据库中读取省级数据,如果读取到了就直接将数据显示到界面上,如果没有就调用queryFromServer()方法来从服务器上查询数据。

queryFromServer()方法会先根据传入的参数来拼装查询地址,具体可见Android天气预报程序(一)

确定了查询地址之后,接下来就调用HttpUtil的sendHttpRequest()方法来向服务器发送请求,响应的数据会回调到onFinish()方法中,然后我们在这里去调用handleProvinceResponse()方法来解析和处理服务器返回的数据,并存储到数据库中。

接下来这一步很关键,在解析和处理完数据之后,我们再次调用了queryProvince()方法来重新加载省级数据,由于queryProvince()方法牵扯到了UI操作,因此必须要在主线程中调用,这里借助了runOnUiThread()方法来实现从子线程切换到主线程,它的实现原理其实也是基于异步消息处理机制的。

现在数据库中已经存在了数据,因此调用queryProvince()就会直接将数据显示到界面了。

当你点击了某个省的时候会进入到ListView的onItemClick()方法中,这个时候会根据当前的级别来判断是去调用queryCities()方法还是queryCounties()方法。

我们重写了onBackPressed()方法来覆盖默认Back键的行为,这里会根据当前的级别来判断是返回市级列表、省级列表、还是直接退出。

接下来就是配置AndroidManifest.xml文件了

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.coolweather.app"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.coolweather.app.activity.ChooseAreaActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


主要就修改了两点,第一是添加了访问网络的权限,第二是将ChooseAreaActivity配置成主活动,这样一旦打开程序就会直接进入ChooseAreaActivity了。

现在可以运行一下程序了

可以看到,全国所有省级单位都显示出来了

我们还可以继续查看市级单位,比如点击广东省

然后再点击广州市
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: