Android天气预报app改进版

作者:new_one_object 时间:2023-12-04 05:54:07 

最近总是有人来和我说我以前写的一个小app无法正常获取数据~Android简易版天气预报app
今天就又运行了下来查找问题,发现或许是接口有限制吧,不能在多台手机使用同个apikey
然后,发现了我写的代码实在乱七八糟,界面也实在不好看,就又重写了一遍,小小地修改了一遍,开发环境改为了Android Studio

最终效果图如下

Android天气预报app改进版 

工程图如下

Android天气预报app改进版

一、获取地区信息

做这么一个天气预报app,首先就要获取到国内地区列表
(在我的另一篇博客有介绍:向任意网址发起数据请求)
中国天气网开放有天气预报接口,访问“http://www.weather.com.cn/data/list3/city.xml”就可以获取到国内省份列表以及其代号了

Android天气预报app改进版

如果想要获取广东省下的城市列表,由上图可知广东省的代号为28,则接口地址是 “http://www.weather.com.cn/data/list3/city28.xml”,获取到的城市列表及代号如下:

Android天气预报app改进版 

依次类推还可以获取到更加详细的地区信息,这样就完成了开头部分

二、天气信息的获取

百度的APIStore拥有丰富的接口,涵盖了生活的许多方面。例如,我们就可以通过APIStore的某个接口获取到含有天气信息的JSON数据,从而实现天气预报功能
(在我的另一篇博客有介绍:获取含天气信息的JSON数据)
首先,使用者要有一个百度账号,然后登陆以下网址:中国和世界天气预报
该接口是免费的,不过因此也就不够稳定,我在调试的时候就经常出错
然后在API选项下点击“您自己的apikey”,查看自己的apikey。该值是每个开发者和app的唯一标识,需要妥善保管,有了apikey才可以进行下一步的操作

Android天气预报app改进版

获取到的天气信息是JSON格式的,需要在程序中再来解析

 Android天气预报app改进版

三、数据库的设计

地区列表这些信息一般都是固定不变的,所以我们可以把第一次联网获取到的数据存进数据库里,下次再次访问时就从数据库里读取即可
首先要设定四个Model,包括:省份、城市、县、每小时天气预测,用来承载数据
每个Model包括几个属性以及相应的get和set方法
例如,省份Province的设计如下所示,城市City和县County的设计类似


/**
* 省份
*/
public class Province {
//省份名
private String provinceName;
//省份ID
private String provinceId;

public String getProvinceId() {
 return provinceId;
}

public String getProvinceName() {
 return provinceName;
}

public void setProvinceId(String provinceId) {
 this.provinceId = provinceId;
}

public void setProvinceName(String provinceName) {
 this.provinceName = provinceName;
}
}

每小时天气预测HourlyWeather的设计如下:


/**
* Created by ZY on 2016/7/21.
*/
public class HourlyWeather {

//预测时间
private String time;
//温度
private String temp;
//降水概率
private String pop;
//风力
private String wind;

public HourlyWeather(String time, String temp, String pop, String wind) {
 this.time = time;
 this.temp = temp;
 this.pop = pop;
 this.wind = wind;
}

public String getTime() {
 return time;
}

public String getTemp() {
 return temp;
}

public String getPop() {
 return pop;
}

public String getWind() {
 return wind;
}
}

然后,新建一个DatabaseHelper类继承于SQLiteOpenHelper,用来建立三个数据库表


public class DatabaseHelper extends SQLiteOpenHelper {

private final String CREATE_PROVINCE = "create table Province ("
  + "provinceName text," + "provinceId text )";

private final String CREATE_CITY = "create table City("
  + "cityName text," + "cityId text," + "provinceId text)";

private final String CREATE_COUNTY = "create table County("
  + "countyName text," + "countyId text," + "cityId text)";

public DatabaseHelper(Context context, String DbName,
      CursorFactory factory, int version) {
 super(context, DbName, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
 db.execSQL(CREATE_PROVINCE);
 db.execSQL(CREATE_CITY);
 db.execSQL(CREATE_COUNTY);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

然后,再建立一个WeatherDB类,用来进行实际的数据库操作,包括存取省份信息、城市信息、县信息等
需要注意的是,因为每个城市都是包含在某个省份下的,所以查询某个省份下的所有城市列表,需要将省份的ID传入作为唯一标识


public class WeatherDB {

private final String DataBaseName = "ZyWeather";

private final int VERSION = 1;

private SQLiteDatabase database;

private static WeatherDB weatherDB;

private WeatherDB(Context context) {
 DatabaseHelper dataBaseHelper = new DatabaseHelper(context,
   DataBaseName, null, VERSION);
 database = dataBaseHelper.getWritableDatabase();
}

//获取实例
public static WeatherDB getInstance(Context context) {
 if (weatherDB == null) {
  weatherDB = new WeatherDB(context);
 }
 return weatherDB;
}

//保存省份信息
public void saveProvinces(List<Province> provinceList) {
 if (provinceList != null && provinceList.size() > 0) {
  ContentValues values = new ContentValues();
  for (int i = 0; i < provinceList.size(); i++) {
   values.put("provinceName", provinceList.get(i).getProvinceName());
   values.put("provinceId", provinceList.get(i).getProvinceId());
   database.insert("Province", null, values);
   values.clear();
  }
 }
}

//保存城市信息
public void saveCities(List<City> cityList) {
 if (cityList != null && cityList.size() > 0) {
  ContentValues values = new ContentValues();
  for (int i = 0; i < cityList.size(); i++) {
   values.put("cityName", cityList.get(i).getCityName());
   values.put("cityId", cityList.get(i).getCityId());
   values.put("provinceId", cityList.get(i).getProvinceId());
   database.insert("City", null, values);
   values.clear();
  }
 }
}

//保存乡村信息
public void saveCounties(List<County> countyList) {
 if (countyList != null && countyList.size() > 0) {
  ContentValues values = new ContentValues();
  for (int i = 0; i < countyList.size(); i++) {
   values.put("countyName", countyList.get(i).getCountyName());
   values.put("countyId", countyList.get(i).getCountyId());
   values.put("cityId", countyList.get(i).getCityId());
   database.insert("County", null, values);
   values.clear();
  }
 }
}

//返回所有省份信息
public List<Province> getAllProvince() {
 Cursor cursor = database.query("Province", null, null, null, null, null, null);
 List<Province> list = new ArrayList<>();
 Province province;
 if (cursor.moveToFirst()) {
  do {
   province = new Province();
   province.setProvinceName(cursor.getString(cursor.getColumnIndex("provinceName")));
   province.setProvinceId(cursor.getString(cursor.getColumnIndex("provinceId")));
   list.add(province);
  } while (cursor.moveToNext());
 }
 return list;
}

//返回指定省份下的所有城市
public List<City> getAllCity(String provinceId) {
 List<City> list = new ArrayList<>();
 City city;
 Cursor cursor = database.query("City", null, "provinceId = ?", new String[]{provinceId}, null, null, null);
 if (cursor.moveToFirst()) {
  do {
   city = new City();
   city.setCityName(cursor.getString(cursor.getColumnIndex("cityName")));
   city.setCityId(cursor.getString(cursor.getColumnIndex("cityId")));
   city.setProvinceId(provinceId);
   list.add(city);
  } while (cursor.moveToNext());
 }
 return list;
}

//返回指定城市下的所有乡村
public List<County> getAllCountry(String cityId) {
 List<County> list = new ArrayList<>();
 Cursor cursor = database.query("County", null, "cityId=?", new String[]{cityId}, null, null, null);
 County county;
 if (cursor.moveToFirst()) {
  do {
   county = new County();
   county.setCountyName(cursor.getString(cursor.getColumnIndex("countyName")));
   county.setCountyId(cursor.getString(cursor.getColumnIndex("countyId")));
   county.setCityId(cityId);
   list.add(county);
  } while (cursor.moveToNext());
 }
 return list;
}

}

四、联网操作

整个app用同一个函数来完成各种数据数据操作,该函数包含在HttpUtil类下,为静态函数
当中需要填入自己申请的apikey,该key仅在获取天气信息时有用,在获取地区信息时是不需要的,这里只是为了简便,所以就一起写上了


public class HttpUtil {

public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
 new Thread(new Runnable() {
  public void run() {
   HttpURLConnection connection = null;
   try {
    URL url = new URL(address);
    connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    connection.setConnectTimeout(8000);
    connection.setReadTimeout(8000);
    connection.setRequestProperty("apikey", "填入自己的apikey");
    connection.connect();
    InputStream inputStream = connection.getInputStream();
    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
    StringBuilder response = new StringBuilder();
    String line;
    while ((line = bufferedReader.readLine()) != null) {
     response.append(line);
    }
    if (listener != null) {
     listener.onFinish(response.toString());
    }
   } catch (Exception e) {
    if (listener != null) {
     listener.onError(e);
    }
   } finally {
    if (connection != null) {
     connection.disconnect();
    }
   }
  }
 }).start();
}
}

五、工具类

在联网访问数据成功或失败后,都需要通过回调方法进行数据处理,所以需要设定一个接口HttpCallbackListener


public interface HttpCallbackListener {

void onFinish(String response);

void onError(Exception e);

}

此外,使用HttpUtil 类获取到地区信息后,因为数据包含一些分隔符,无法直接存入数据库,而且获取到的天气信息也是JSON格式的,也需要进行数据解析,所以还需要有一个Utility类用来进行数据处理


public class Utility {

// 保存服务器返回的省级数据
public static boolean saveProvincesResponse(WeatherDB weatherDB, String response) {
 if (!TextUtils.isEmpty(response)) {
  String[] allProvinces = response.split(",");
  if (allProvinces != null && allProvinces.length > 0) {
   Province province;
   List<Province> provinceList = new ArrayList<>();
   for (String p : allProvinces) {
    String[] array = p.split("\\|");
    province = new Province();
    province.setProvinceId(array[0]);
    province.setProvinceName(array[1]);
    provinceList.add(province);
   }
   weatherDB.saveProvinces(provinceList);
   return true;
  }
 }
 return false;
}

// 保存服务器返回的市级数据
public static boolean saveCitiesResponse(WeatherDB weatherDB, String response, String provinceId) {
 if (!TextUtils.isEmpty(response)) {
  String[] allCities = response.split(",");
  if (allCities != null && allCities.length > 0) {
   City city;
   List<City> cityList = new ArrayList<>();
   for (String c : allCities) {
    String[] array = c.split("\\|");
    city = new City();
    city.setCityId(array[0]);
    city.setCityName(array[1]);
    city.setProvinceId(provinceId);
    cityList.add(city);
   }
   weatherDB.saveCities(cityList);
   return true;
  }
 }
 return false;
}

// 保存服务器返回的县级数据
public static boolean saveCountiesResponse(WeatherDB weatherDB, String response, String cityId) {
 if (!TextUtils.isEmpty(response)) {
  String[] allCounties = response.split(",");
  if (allCounties != null && allCounties.length > 0) {
   County county;
   List<County> countyList = new ArrayList<>();
   for (String c : allCounties) {
    String[] array = c.split("\\|");
    county = new County();
    county.setCountyId(array[0]);
    county.setCountyName(array[1]);
    county.setCityId(cityId);
    countyList.add(county);
   }
   weatherDB.saveCounties(countyList);
   return true;
  }
 }
 return false;
}

// 处理服务器返回的json数据
public static void handleWeatherResponse(Context context, String response) {
 try {
  JSONObject jsonobject = new JSONObject(response);
  JSONArray title = jsonobject.getJSONArray("HeWeather data service 3.0");
  JSONObject first_object = (JSONObject) title.get(0);

JSONObject basic = (JSONObject) first_object.get("basic");

//更新时间
  JSONObject update = (JSONObject) basic.get("update");
  JSONArray daily_forecast = (JSONArray) first_object.get("daily_forecast");
  JSONObject daily_forecast_first = (JSONObject) daily_forecast.get(0);
  JSONObject cond = (JSONObject) daily_forecast_first.get("cond");
  //温度
  JSONObject temp = (JSONObject) daily_forecast_first.get("tmp");

JSONObject astro = (JSONObject) daily_forecast_first.get("astro");

JSONObject wind = (JSONObject) daily_forecast_first.get("wind");

JSONArray hourly_forecast = (JSONArray) first_object.get("hourly_forecast");

WeatherActivity.weatherList.clear();

for (int i = 0; i < hourly_forecast.length(); i++) {
   JSONObject json = hourly_forecast.getJSONObject(i);
   JSONObject json_wind = (JSONObject) json.get("wind");
   String date = json.getString("date");
   String[] array = date.split(" ");
   String dir = json_wind.getString("dir");
   String sc = json_wind.getString("sc");
   String hourly_clock = array[1];
   String hourly_temp = "温度:" + json.getString("tmp") + "℃";
   String hourly_pop = "降水概率:" + json.getString("pop");
   String hourly_wind = "风力:" + dir + " " + sc + "级";
   HourlyWeather weather = new HourlyWeather(hourly_clock, hourly_temp, hourly_pop, hourly_wind);
   WeatherActivity.weatherList.add(weather);
  }
  //日出
  String sunriseTime = astro.getString("sr");
  //日落
  String sunsetTime = astro.getString("ss");
  //白天天气
  String dayWeather = cond.getString("txt_d");
  //夜晚天气
  String nightWeather = cond.getString("txt_n");
  //风力
  String windText = wind.getString("dir") + " " + wind.getString("sc") + "级";
  //降水概率
  String pop = daily_forecast_first.getString("pop");
  //温度
  String tempText = temp.getString("min") + "℃~" + temp.getString("max") + "℃";
  //更新时间
  String updateTime = update.getString("loc");
  //城市名
  String cityName = basic.getString("city");
  saveWeatherInfo(context, cityName, sunriseTime, sunsetTime, dayWeather, nightWeather, windText, pop, tempText, updateTime);
 } catch (Exception e) {
  e.printStackTrace();
 }
}

private static void saveWeatherInfo(Context context, String cityName,
         String sunriseTime, String sunsetTime, String dayWeather, String nightWeather,
         String windText, String pop, String tempText, String updateTime) {
 SharedPreferences.Editor editor = context.getSharedPreferences("Weather", Context.MODE_PRIVATE).edit();
 editor.putString("cityName", cityName);
 editor.putString("sunriseTime", sunriseTime);
 editor.putString("sunsetTime", sunsetTime);
 editor.putString("dayWeather", dayWeather);
 editor.putString("nightWeather", nightWeather);
 editor.putString("wind", windText);
 editor.putString("pop", pop);
 editor.putString("temp", tempText);
 editor.putString("updateTime", updateTime);
 editor.commit();
}
}

 六、适配器
由上边的动态图可以看到每小时的天气预测信息,那是使用ListView呈现的,这就要为其提供一个适配器了
ListView使用的布局文件如下:


<?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="horizontal">

<!-- 时间 -->

<TextView
 android:id="@+id/forecastTime"
 android:layout_width="0dp"
 android:layout_height="match_parent"
 android:layout_weight="2"
 android:gravity="center"
 android:textSize="20sp"
 android:textStyle="bold" />

<LinearLayout
 android:layout_width="0dp"
 android:layout_height="match_parent"
 android:layout_weight="5"
 android:orientation="vertical">

<!-- 温度 降水概率 -->

<LinearLayout
  android:layout_width="match_parent"
  android:layout_height="0dp"
  android:layout_weight="1"
  android:gravity="center"
  android:orientation="horizontal">

<!-- 温度 -->

<TextView
   android:id="@+id/forecastTemp"
   android:layout_width="0dp"
   android:layout_height="match_parent"
   android:layout_weight="1"
   android:gravity="center" />

<!-- 下雨概率 -->

<TextView
   android:id="@+id/forecastPop"
   android:layout_width="0dp"
   android:layout_height="match_parent"
   android:layout_weight="1"
   android:gravity="center" />
 </LinearLayout>

<!-- 风力 -->

<TextView
  android:id="@+id/forecastWind"
  android:layout_width="match_parent"
  android:layout_height="0dp"
  android:layout_weight="1"
  android:gravity="center" />
</LinearLayout>

</LinearLayout>

然后新建一个WeatherAdapter继承于ArrayAdapter< HourlyWeather>
只要重写getView(int position, View convertView, ViewGroup parent)方法即可


public class WeatherAdapter extends ArrayAdapter<HourlyWeather> {

private int resourceId;

private Context context;

public WeatherAdapter(Context context, int textViewResourceId, List<HourlyWeather> objects) {
 super(context, textViewResourceId, objects);
 this.context = context;
 this.resourceId = textViewResourceId;
}

public View getView(int position, View convertView, ViewGroup parent) {
 HourlyWeather weather = getItem(position);
 View view = LayoutInflater.from(context).inflate(resourceId, null);

TextView forecastTime = (TextView) view.findViewById(R.id.forecastTime);
 TextView forecastTemp = (TextView) view.findViewById(R.id.forecastTemp);
 TextView forecastPop = (TextView) view.findViewById(R.id.forecastPop);
 TextView forecastWind = (TextView) view.findViewById(R.id.forecastWind);

forecastTime.setText(weather.getTime());
 forecastTemp.setText(weather.getTemp());
 forecastPop.setText(weather.getPop());
 forecastWind.setText(weather.getWind());
 return view;
}

}

七、Activity的编写
首先要完成地区选择界面ChooseAreaActivity
ChooseAreaActivity的界面仅包括一个居中的TextView和一个ListView
布局文件如下:


<?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_parent"
 android:layout_height="50dp">

<TextView
  android:id="@+id/title"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerInParent="true"
  android:textSize="24sp" />
</RelativeLayout>

<ListView
 android:id="@+id/listView"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />

</LinearLayout>

ChooseAreaActivity 需要完成的操作有:完成地区列表的加载、将选择的County名传递给WeatherActivity
此外,当中使用了showProgressDialog()来呈现一个进度对话框,也设为无法通过返回键关闭,而我又没有在弱网环境下调试过,每次加载都是很快,也没见到对话框出来过,所以也不知道showProgressDialog()到底有没有bug啥的~


public class ChooseAreaActivity extends AppCompatActivity {

// 标记当前列表为省份
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 WeatherDB weatherDB;

private List<String> dataList;

private List<Province> provinceList;

private List<City> cityList;

private List<County> countyList;
//选择的省份
private Province selectedProvince;
//选择的城市
private City selectedCity;
//当前选择的列表类型
private int currentLevel;
//标记是否从WeatherActivity跳转而来的
private boolean isFromWeatherActivity;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 isFromWeatherActivity = getIntent().getBooleanExtra("ChooseArea", false);
 SharedPreferences sharedPreferences = getSharedPreferences("Weather", Context.MODE_PRIVATE);

// 如果country已选择且本Activity不是从天气界面启动而来的,则直接跳转到WeatherActivity

if (!TextUtils.isEmpty(sharedPreferences.getString("CountyName", "")) && !isFromWeatherActivity) {
  Intent intent = new Intent(this, WeatherActivity.class);
  startActivity(intent);
  finish();
  return;
 }
 setContentView(R.layout.activity_choose_area);
 if (getSupportActionBar() != null) {
  getSupportActionBar().hide();
 }
 listView = (ListView) findViewById(R.id.listView);
 titleText = (TextView) findViewById(R.id.title);
 dataList = new ArrayList<>();
 adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, dataList);
 listView.setAdapter(adapter);
 weatherDB = WeatherDB.getInstance(this);
 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
   if (currentLevel == LEVEL_PROVINCE) {
    selectedProvince = provinceList.get(index);
    queryCities();
   } else if (currentLevel == LEVEL_CITY) {
    selectedCity = cityList.get(index);
    queryCounties();
   } else if (currentLevel == LEVEL_COUNTY) {
    //当点击到县列表时,就利用Intent跳转到天气信息界面
    String countyName = countyList.get(index).getCountyName();
    Intent intent = new Intent(ChooseAreaActivity.this, WeatherActivity.class);
    intent.putExtra("CountyName", countyName);
    startActivity(intent);
    finish();
   }
  }
 });
 queryProvinces();
}

private void queryProvinces() {
 showProgressDialog();
 provinceList = weatherDB.getAllProvince();
 if (provinceList.size() > 0) {
  dataList.clear();
  for (Province province : provinceList) {
   dataList.add(province.getProvinceName());
  }
  adapter.notifyDataSetChanged();
  listView.setSelection(0);
  titleText.setText("中国");
  currentLevel = LEVEL_PROVINCE;
  closeProgressDialog();
 } else {
  queryFromServer(null, "province");
 }
}

private void queryCities() {
 showProgressDialog();
 cityList = weatherDB.getAllCity(selectedProvince.getProvinceId());
 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;
  closeProgressDialog();
 } else {
  queryFromServer(selectedProvince.getProvinceId(), "city");
 }
}

private void queryCounties() {
 showProgressDialog();
 countyList = weatherDB.getAllCountry(selectedCity.getCityId());
 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;
  closeProgressDialog();
 } else {
  queryFromServer(selectedCity.getCityId(), "county");
 }
}

private void queryFromServer(final String code, final String type) {
 String address;
 // code不为空
 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";
 }
 HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
  @Override
  public void onFinish(String response) {
   boolean result = false;
   if ("province".equals(type)) {
    result = Utility.saveProvincesResponse(weatherDB, response);
   } else if ("city".equals(type)) {
    result = Utility.saveCitiesResponse(weatherDB, response, selectedProvince.getProvinceId());
   } else if ("county".equals(type)) {
    result = Utility.saveCountiesResponse(weatherDB, response, selectedCity.getCityId());
   }
   if (result) {
    runOnUiThread(new Runnable() {
     @Override
     public void run() {
      if ("province".equals(type)) {
       queryProvinces();
      } else if ("city".equals(type)) {
       queryCities();
      } else if ("county".equals(type)) {
       queryCounties();
      }
     }
    });
   }
  }

@Override
  public void onError(Exception e) {
   runOnUiThread(new Runnable() {
    @Override
    public void run() {
     Toast.makeText(ChooseAreaActivity.this, "加载失败", Toast.LENGTH_SHORT).show();
    }
   });
  }
 });
 closeProgressDialog();
}

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();
 }
}

@Override
public void onBackPressed() {
 if (currentLevel == LEVEL_COUNTY) {
  queryCities();
 } else if (currentLevel == LEVEL_CITY) {
  queryProvinces();
 } else {
  if (isFromWeatherActivity) {
   Intent intent = new Intent(this, WeatherActivity.class);
   startActivity(intent);
  }
  finish();
 }
}
}

WeatherActivity的布局相对复杂些,包含了许多个TextView,我也只是想着简单就好,就简单地把数据用文本呈现出来


// 城市切换按钮
private Button citySwitch;
// 刷新数据按钮
private Button weatherRefresh;
// 城市名
private TextView cityName;
// 白天夜晚天气描叙
private TextView DayNightWeather;
// 温度
private TextView temp;
// 日出时间
private TextView sunriseTime;
// 日落时间
private TextView sunsetTime;
// 风力
private TextView wind;
// 降水概率
private TextView pop;
// 发布时间
private TextView updateTime;
// 今日天气预测列表
private ListView listview;

public static List<HourlyWeather> weatherList = new ArrayList<>();

private SharedPreferences sharedPreferences;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.weather);
 if (getSupportActionBar() != null) {
  getSupportActionBar().hide();
 }
 init();
}

private void init() {
 citySwitch = (Button) findViewById(R.id.citySwitch);
 weatherRefresh = (Button) findViewById(R.id.weatherRefresh);
 citySwitch.setOnClickListener(this);
 weatherRefresh.setOnClickListener(this);
 cityName = (TextView) findViewById(R.id.cityName);
 DayNightWeather = (TextView) findViewById(R.id.DayNightWeather);
 temp = (TextView) findViewById(R.id.temp);
 sunriseTime = (TextView) findViewById(R.id.sunriseTime);
 sunsetTime = (TextView) findViewById(R.id.sunsetTime);
 wind = (TextView) findViewById(R.id.wind);
 pop = (TextView) findViewById(R.id.pop);
 updateTime = (TextView) findViewById(R.id.updateTime);
 listview = (ListView) findViewById(R.id.hourlyForecast);
 sharedPreferences = getSharedPreferences("Weather", Context.MODE_PRIVATE);

String countyName = getIntent().getStringExtra("CountyName");
 // 当countyName不为空
 if (!TextUtils.isEmpty(countyName)) {
  SharedPreferences.Editor editor = sharedPreferences.edit();
  editor.putString("CountyName", countyName);
  editor.commit();
 } else {
  countyName = sharedPreferences.getString("CountyName", "");
 }
 weatherRefresh.setText("同步中……");
 queryFromServer(countyName);
}

@Override
public void onClick(View view) {
 switch (view.getId()) {
  case R.id.citySwitch:
   Intent intent = new Intent(this, ChooseAreaActivity.class);
   intent.putExtra("ChooseArea", true);
   startActivity(intent);
   finish();
   break;
  case R.id.weatherRefresh:
   weatherRefresh.setText("同步中……");
   String countyName = sharedPreferences.getString("CountyName", "");
   if (!TextUtils.isEmpty(countyName)) {
    queryFromServer(countyName);
   }
   break;
 }
}

private void queryFromServer(final String countyName) {
 try {
  String url = "http://apis.baidu.com/heweather/weather/free?city=";
  String name = new String(countyName.getBytes("UTF-8"), "iso-8859-1");
  HttpUtil.sendHttpRequest(url + name, new HttpCallbackListener() {
   @Override
   public void onFinish(String response) {
    Utility.handleWeatherResponse(WeatherActivity.this, response);
    runOnUiThread(new Runnable() {
     @Override
     public void run() {
      showWeather();
     }
    });
   }

@Override
   public void onError(Exception e) {
    runOnUiThread(new Runnable() {
     @Override
     public void run() {
      Toast.makeText(WeatherActivity.this, "同步失败", Toast.LENGTH_LONG).show();
      weatherRefresh.setText("更新数据");
     }
    });
   }
  });
 } catch (Exception e) {
  e.printStackTrace();
 }

}

private void showWeather() {
 cityName.setText(sharedPreferences.getString("cityName", "未知"));
 sunriseTime.setText("日出:" + sharedPreferences.getString("sunriseTime", "未知"));
 sunsetTime.setText("日落:" + sharedPreferences.getString("sunsetTime", "未知"));
 DayNightWeather.setText("日:" + sharedPreferences.getString("dayWeather", "未知") + " 夜:" + sharedPreferences.getString("nightWeather", "未知"));
 temp.setText("温度:" + sharedPreferences.getString("temp", "未知"));
 wind.setText("风力:" + sharedPreferences.getString("wind", "未知"));
 pop.setText("降水概率:" + sharedPreferences.getString("pop", "未知"));
 updateTime.setText("发布时间:" + sharedPreferences.getString("updateTime", "未知"));
 WeatherAdapter adapter = new WeatherAdapter(this, R.layout.hourly_weather, weatherList);
 listview.setAdapter(adapter);
 Toast.makeText(WeatherActivity.this, "已经是最新数据了", Toast.LENGTH_SHORT).show();
 weatherRefresh.setText("更新数据");
}

}

八、说明
很奇怪的是,这个小app在我的4.4版本的小米手机上运行无误,可在5.1系统的模拟器和华为手机上却提示无法获取到数据,返回的JSON数据提示说城市未知,查看了很久也没搞明白,只能作罢~~

代码下载地址:Android简易版天气预报app的实现(改进版)

标签:Android,天气预报,app
0
投稿

猜你喜欢

  • 解决本机安装的JDK8,启动IDEA2019没反应的问题(开发工具)

    2023-08-12 23:29:11
  • java 面试题闰年判断详解及实例

    2023-11-27 19:09:01
  • 详解Java包装类及自动装箱拆箱

    2023-11-14 21:13:23
  • java字符串常用操作方法(查找、截取、分割)

    2023-11-29 03:21:13
  • SpringBoot集成POI实现Excel导入导出的示例详解

    2022-12-05 19:09:10
  • Java 深入浅出掌握Collection单列集合Set

    2023-10-07 18:49:32
  • Android实用图文教程之代码混淆、第三方平台加固加密、渠道分发

    2022-06-23 18:12:44
  • 简单理解Java的垃圾回收机制与finalize方法的作用

    2023-02-04 01:49:37
  • JAVA中的final关键字用法实例详解

    2021-06-25 12:10:08
  • log4j配置失效日志中打印Debug信息问题

    2022-10-12 10:13:12
  • java 中链表的定义与使用方法

    2023-03-07 07:34:13
  • Mybatis-Plus字段策略FieldStrategy的使用

    2023-12-13 14:44:41
  • Spring实现动态切换多数据源的解决方案

    2023-05-21 13:07:15
  • Android Intent传递大量数据出现问题解决

    2021-11-07 10:16:13
  • 详解Java中的日期类

    2022-08-27 17:14:03
  • Mybatis执行流程、缓存原理及相关面试题汇总

    2022-10-15 23:30:28
  • C# 反射与dynamic最佳组合示例代码

    2022-01-18 02:29:53
  • Java Lambda表达式实例解析原理

    2022-11-02 08:11:02
  • 关于C# TabPage如何隐藏的问题

    2023-01-10 00:01:39
  • Java实现发红包功能

    2023-12-09 10:33:03
  • asp之家 软件编程 m.aspxhome.com