DogWeather(一)

来源:互联网 发布:sonyhdr as50软件 编辑:程序博客网 时间:2024/05/16 18:56

我写的是一个名叫DogWeather的天气查询APP,当然这只是我的一种自娱自乐。这个APP有手动更新、后台启动更新和指定城市查询天气的功能。不过页面很丑,确实不擅长做页面。废话不多说直接开始。

我觉得做一个APP的最主要的事情就是要先布好局,要不然就会事倍功半。首先我将程序分为这几个模块,Activity模块、网络信息获取和解析模块、信息存储模块、后台更新模块。

Activity模块

在这个模块中我设计了这么几个ActivityBaseActivity是用来作为我的其他的Activity的父类来使用的,他不实现具体的功能,但是他和ActivityCollector结合起来使用就可以来管理我的Activity(这个技巧是我在《第一行代码》上看到的,还有后面的MyLog。这确实是一本很好的书,学到很多)。

他的具体功能是通过一个List来管理Activity,并且提供一个随时退出程序的静态方法。

package com.peter.dogweather.activity;import android.app.Activity;import android.os.Bundle;public class BaseActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// Log.d(tag, msg)ActivityCollector.addActivity(this);}@Overrideprotected void onDestroy() {super.onDestroy();ActivityCollector.removeActivity(this);}}
package com.peter.dogweather.activity;import java.util.ArrayList;import java.util.List;import android.app.Activity;/** * 用于管理应用程序的退出 *  * @author Administrator *  */public class ActivityCollector {public static List<Activity> activities = new ArrayList<Activity>();public static void addActivity(Activity activity) {activities.add(activity);}public static void removeActivity(Activity activity) {activities.remove(activity);}public static void finishAll() {for (Activity activity : activities) {if (!activity.isFinishing()) {activity.finish();}}}}
ChooseActivity是选择城市的活动,优先从SQLite数据库中读取数据,如果没有则从网络上获取

private void queryProvinces() {provinceList = dogWeatherDB.getProvinceInfo();if (provinceList.size() > 0) {dataList.clear();// 清除dataList的数据for (Province province : provinceList) {// MyLog.d("ChooseActivity",province.getProvinceName());dataList.add(province.getProvinceName());}// 通知适配器数据已改变adapter.notifyDataSetChanged();lv_choose_area.setSelection(0);tv_title_select.setText("中国");LEVEL_CURRENT = LEVEL_PROVINCE;} else {queryFromServer(null, "Province");}}

private void queryFromServer(final String code, final String level) {String httpUrl;if (TextUtils.isEmpty(code)) {httpUrl = "http://www.weather.com.cn/data/list3/city.xml";} else {httpUrl = "http://www.weather.com.cn/data/list3/city" + code+ ".xml";}Utility.sendRequest4AreaInfo(httpUrl, new HttpResponseListener() {@Overridepublic void onFinish(String response) {boolean result = false;if ("Province".equals(level)) {result = Utility.handleProvinceInfo(dogWeatherDB, response);MyLog.d("ChooseActivity", "解析省份信息完毕");// queryProvinces();} else if ("City".equals(level)) {result = Utility.handleCityInfo(dogWeatherDB, response,selectProvince.getId());MyLog.d("ChooseActivity", "解析市级信息完毕");} else if ("County".equals(level)) {result = Utility.handleCountyInfo(dogWeatherDB, response,selectCity.getId());MyLog.d("ChooseActivity", "解析县级信息完毕");}if (result) {runOnUiThread(new Runnable() {@Overridepublic void run() {if ("Province".equals(level)) {queryProvinces();} else if ("City".equals(level)) {queryCitys();} else if ("County".equals(level)) {queryCountys();}}});}}@Overridepublic void onError(Exception e) {Toast.makeText(ChooseActivity.this, "网络请求失败,请检查你的网络!",Toast.LENGTH_SHORT).show();}});}
这里在网络请求模块开启线程而不是让调用者去开启,为了读取线程中返回的结果信息,这里使用了Java的回调机制。

WeatherActivity是用将信息显示到页面上的,具体你需要什么信息你自己去设置。哦,对了,我使用的接口是和风天气,这个可以在API store中找到。

private void showWeather() {MyLog.d("WeatherActivity", "开始显示数据");if (weatherData != null) {MyLog.d("WeatherActivity", "开始解析天气字符串数据");heWeatherData = Utility.handleWeatherInfo(weatherData);if(heWeatherData == null){return;}if (heWeatherData == null) {MyLog.d("WeatherActivity", "传递对象失败");}} else {MyLog.d("WeatherActivity", "查询天气数据");queryWeather(selectName);return;// 避免堆栈}}
weatherData中我存储的是从网络获取的天气信息,每当我要使用天气信息的时候我就会调用Utility中的解析JSON数据的方法来解析这个字符串。我是通过GSON方式来解析的数据,使用GSON数据你要先往你的项目中加入gson的jar包,然后你需要构建好Bean对象,使用GSON的方法就可以很简便的方式来解析他,当然你也可以使用JSONObject来解析他。
private void queryWeather(final String selectName) {String httpUrl = "http://apis.baidu.com/heweather/weather/free?city=";try {MyLog.d("WeatherActivity", "" + selectName);String temp = URLEncoder.encode(selectName, "utf-8");Utility.sendRequest4WeatherInfo(httpUrl + temp,new HttpResponseListener() {@Overridepublic void onFinish(String response) {if(!response.contains("ok")){weatherData = null;Toast.makeText(WeatherActivity.this, "请切换城市", Toast.LENGTH_SHORT).show();return;}weatherData = response;SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();editor.putString("weatherData", response);editor.putBoolean("isSelected", true);editor.commit();runOnUiThread(new Runnable() {@Overridepublic void run() {showWeather();}});}@Overridepublic void onError(Exception e) {Toast.makeText(WeatherActivity.this,"网络请求失败,请检查你的网络!", Toast.LENGTH_SHORT).show();}});} catch (UnsupportedEncodingException e) {e.printStackTrace();}}
WelcomeActivity就是一个欢迎页,不赘述。
Model,这里存放了我的Bean,天气对象和省市区对象。Bean对象其实也就是GETSET方法。

后台启动更新,通过服务和广播结合的形式来完成。这里需要注意的是在service中接收Activity发送的数据

public int onStartCommand(Intent intent, int flags, int startId) {selectName = intent.getExtras().getString("selectName");MyLog.d("AutoRefreshService", selectName + "-->自动更新");new Thread() {public void run() {MyLog.d("AutoRefreshService","后台更新天气");updateWeather();};}.start();// 后台自动更新天气,三个小时更新一次Intent autoRefreshIntent = new Intent(this, AutoRefreshReceiver.class);autoRefreshIntent.putExtra("selectName", selectName);AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,autoRefreshIntent, 0);long triggerAtMillis = SystemClock.elapsedRealtime() +  3 * 60 * 60 * 1000;alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtMillis,pendingIntent);return super.onStartCommand(intent, flags, startId);}
在广播中重新启动service
@Overridepublic void onReceive(Context context, Intent intent) {//System.out.println("广播"+intent.getStringExtra("selectName"));Intent autoRefreshIntent = new Intent(context,AutoRefreshService.class);autoRefreshIntent.putExtra("selectName", intent.getStringExtra("selectName"));context.startService(autoRefreshIntent);}
当然你需要在Activity中启动service
// 启动后台更新服务Intent intent = new Intent(WeatherActivity.this,AutoRefreshService.class);intent.putExtra("selectName", tv_select_area.getText().toString().trim());startService(intent);
信息解析模块,最要的一个文件是Utility,这里面包含获取天气信息,获取城市信息,解析天气信息,解析城市信息的方法。代码太长我就不贴出来,而且这些方法对不同的数据不同的解析方法。

我会把我这个项目方法Github上点击打开链接,博客写的不好,主要还是为了巩固自己知识。

0 0
原创粉丝点击