最近总是有人来和我说我以前写的一个小app无法正常获取数据~Android简易版天气预报app

今天就又运行了下来查找问题,发现或许是接口有限制吧,不能在多台手机使用同个apikey

然后,发现了我写的代码实在乱七八糟,界面也实在不好看,就又重写了一遍,小小地修改了一遍,开发环境改为了Android Studio

最终效果图如下

工程图如下

一、获取地区信息

做这么一个天气预报app,首先就要获取到国内地区列表

(在我的另一篇博客有介绍:向任意网址发起数据请求)

中国天气网开放有天气预报接口,访问“http://www.weather.com.cn/data/list3/city.xml”就可以获取到国内省份列表以及其代号了

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

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

二、天气信息的获取

百度的APIStore拥有丰富的接口,涵盖了生活的许多方面。例如,我们就可以通过APIStore的某个接口获取到含有天气信息的JSON数据,从而实现天气预报功能

(在我的另一篇博客有介绍:获取含天气信息的JSON数据)

首先,使用者要有一个百度账号,然后登陆以下网址:中国和世界天气预报

该接口是免费的,不过因此也就不够稳定,我在调试的时候就经常出错

然后在API选项下点击“您自己的apikey”,查看自己的apikey。该值是每个开发者和app的唯一标识,需要妥善保管,有了apikey才可以进行下一步的操作

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

三、数据库的设计

地区列表这些信息一般都是固定不变的,所以我们可以把第一次联网获取到的数据存进数据库里,下次再次访问时就从数据库里读取即可

首先要设定四个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 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 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 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 getAllProvince() {

Cursor cursor = database.query("Province", null, null, null, null, null, null);

List 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 getAllCity(String provinceId) {

List 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 getAllCountry(String cityId) {

List 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 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 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 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使用的布局文件如下:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal">

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" />

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="5"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1"

android:gravity="center"

android:orientation="horizontal">

android:id="@+id/forecastTemp"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1"

android:gravity="center" />

android:id="@+id/forecastPop"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1"

android:gravity="center" />

android:id="@+id/forecastWind"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1"

android:gravity="center" />

然后新建一个WeatherAdapter继承于ArrayAdapter< HourlyWeather>

只要重写getView(int position, View convertView, ViewGroup parent)方法即可

public class WeatherAdapter extends ArrayAdapter {

private int resourceId;

private Context context;

public WeatherAdapter(Context context, int textViewResourceId, List 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

布局文件如下:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="50dp">

android:id="@+id/title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:textSize="24sp" />

android:id="@+id/listView"

android:layout_width="match_parent"

android:layout_height="match_parent" />

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 adapter;

// 数据库

private WeatherDB weatherDB;

private List dataList;

private List provinceList;

private List cityList;

private List 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 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改进版相关推荐

  1. Android 实战 - 天气(有缺陷)APP

    序言: 临近开学,这是假期最后一篇Android文章,也算是假期学习安卓的一个小小的成果吧. 第一次写Android应用,应用中的不足我会一 一列举出来,同时也希望与大家可以指出我的一些问题与不足,我 ...

  2. android app 退出功能,Android 应用技巧: 手把手教你 优雅实现 “一键退出 App”

    前言 在 Android开发中,会经常存在 "一键退出App" 的需求 但市面上流传着 太多不可用的"一键退出App"功能实现 本文将全面总结"一键退 ...

  3. android中英文切换功能,Android APP 中英文切换

    实习期间,师父要求做app的中英文切换,就顺便记录了下. 一.AndroidManifest.xml文件(清单文件) 在每个要切换语言的Activity下面添加: android:configChan ...

  4. android 选择答题功能,Android APP编写简单答题器

    本文为大家分享了Android APP编写的简单答题器,此答题器可以通过Next按钮选择下一题,新写题目的类Question,有两个成员变量. java代码: package com.android. ...

  5. android 本地提醒功能,android中的本地定时推送到通知栏

    一.使用系统定义的Notification 以下是使用示例代码: import android.app.Notification; import android.app.NotificationMan ...

  6. android的UDC功能,Android实现搜索历史功能

    本文实例为大家分享了Android实现搜索历史的具体代码,供大家参考,具体内容如下 SharedPreferences实现本地搜索历史功能,覆盖搜索重复的文本,可清空 1. 判断搜索内容是否含表情,不 ...

  7. android 添加附件功能,Android实现带附件的邮件发送功能

    本文实例讲解了基于基于jmail实现android邮件发送功能,分享给大家供大家参考,具体内容如下 在android上发送邮件方式: 第一种:借助gmail app客户端,缺点是必须使用gmail帐号 ...

  8. android系统应用功能,Android系统应用(12)

    如何成为系统应用 方法一:在Manifest中声明android:sharedUserId的值为:android.uid.system,android.uid.phone,android.uid.lo ...

  9. android相册幻灯片功能,Android实现幻灯片式图片浏览器

    我们来实现一个幻灯片式图片浏览器: 最下面一个画廊视图,选中画廊中的图片,会在上面的ImageSwitcher控件中显示大图. 效果图如图 实现方法: 在布局文件中添加图片切换控件ImageSwitc ...

最新文章

  1. linux c warning: implicit declaration of function 'strtok_r'解决方案
  2. linux ubuntu文件浏览器如何显示隐藏文件?(快捷键ctrl+h)
  3. Linux启动报错UNEXPECTED INCONSISTENCY解决方法
  4. 解密NTFS下经EFS加密的文件
  5. java8 streams_使用Java 8 Streams进行编程对算法性能的影响
  6. c#中的BeginInvoke和EndEndInvoke 摘要
  7. 激光slam_机器人主流定位技术,激光SLAM与视觉SLAM谁更胜一筹
  8. s8050三极管经典电路_电路板维修基本经验分享。
  9. 〖Linux〗Ubuntu设定Proxy及忽略Proxy
  10. WCF技术剖析之六:为什么在基于ASP.NET应用寄宿(Hosting)下配置的BaseAddress无效...
  11. iOS8中UITableVIew分割线短的问题
  12. paip.powerdesign cdm pdm文件 代码生成器 java web 页面 实现
  13. 关于VM14中安装win 10遇到的小问题
  14. 想在抖音上卖衣服不知道怎么入手,抖音小店改销量技术
  15. 使用selenium爬取百度文库文章(动态)
  16. 浅谈深度学习:LSTM对股票的收益进行预测(Sequential 序贯模型,Keras实现)
  17. java 定义一个rectangle类,Java定义一个Rectangle类
  18. VUE报错__Avoid mutating a prop directly since the value will be overwritten whenever the parent
  19. 孩子想养宠物,该不该同意?
  20. 微信小程序 云数据库使用(上)

热门文章

  1. php二进制应用位运算,【转】PHP 位运算应用口诀
  2. Linux环境的搭建
  3. mysql netcdf_gdal联合编译C++版本proj.4、geos、hdf4、hdf5、netcdf
  4. 详细介绍Java中的运算符
  5. vmware中ubuntu有线网络网速只有10Mb/s解决办法
  6. Opencascade源码学习之模型数据——TKGeomBase模块文件介绍
  7. OpenFOAM无反射边界条件源码学习
  8. MySQL 数据库中 in、some、any、all 的区别与使用
  9. Django搭建强大好用的文本编辑器
  10. ME21N 手工 采购申请转采购订单