当点击搜索按钮时,跳到->SearchCityActivity,在搜索页面搜索完成,返回->mainActivity,这时mainActivity需要知道SearchCityActivity的查询结果,用反向传值来实现。
mainActivity->(1)SearchCityActivity->(2)mainActivity,在(2)处的传值称为反向传值, mainActivity->BMIResultActivity 即是正向传值。反向传值启动intent的方式不同
通过把用户搜索到的结果存到本地,可以实现下次登录还是用户搜索的城市。把数据保存到SharedPreferences,SharedPreferences是Android APP 的一个保存用户信息的轻量级文件,用于报讯少量的用户信息。
存储格式:键值对的形式保存数据。当app中没有SharedPreferences文件时,getSharedPreferences()会创建一个名为weather的SharedPreferences文件,并设置文件读取权限为该应用私有。当APP中存在SharedPreferences文件,getSharedPreferences()就会读取文件,生成对象。
一、声明变量
在变量中new Handler,并重写handleMessage(Message msg),用handlerMessage先区分不同消息。
- 当网络请求结束时,停止动画。
- 如果网络请求出现异常
- 如果网络请求正常,数据解析完成,将msg的信息封装进一个weatherBean。并取出个字段赋给各textView用于显示.
根据getWeatherFromNetWork()中的判断分别调用getWeatherDateSuccess(WeatherBean weatherBean)和netWorkRequestError(String errorString)方法 ,赋给message不同值并调用 netWorkFinishHandler.sendMessage(message),将message传回主线程。
public void handleMessage(Message msg) {
refreshAnimationStop();
if (msg.what == 404) {
netWorkErrorTextView.setText((String) msg.obj);
return
}
if (msg.what == 100) { // 网络请求成功,数据解析完成。
WeatherBean weatherBean = (WeatherBean) msg.obj;
cityTextView.setText(weatherBean.getCityName());
setPmcolor(weatherBean.getPmLevel());
setFutureDayWeather(weatherBean.getFutureWeatherList());
Editor editor = sharePreferences.edit();//获取sharePreferences的编辑
editor.putInt("cityCode", cityCode).commit();//向编辑中添加一个键为cityCode的键值对并调用commit()方法写入文件中
}
}
二、private void setFutureDayWeatherArrayList<FutureWeatherBean> futureWeatherList)
把一个布局代码转换为view控件:通过布局转换器LayoutInflater对象的inflate(R.layout.futureday_layout, null)方法。获取LayoutInflater的对象用LayoutInflater的from(getApplicationContext())静态方法获取
for (int i = 0; i < futureWeatherList.size(); i++) {// 在向容器中添加布局时,要先清空容器型布局
FutureWeatherBean futureWeatherBean = futureWeatherList.get(i);// 创建小部件显示未来天气的布局
View futureDayLayout = LayoutInflater.from(
getApplicationContext()).inflate(
R.layout.futureday_layout, null);
TextView futureWeekTextView = (TextView) futureDayLayout
.findViewById(R.id.future_week_tv);// 从futureDayLayout找到控件
TextView futureWeatherTextView = (TextView) futureDayLayout
.findViewById(R.id.future_weather_tv);
TextView futureTempertureTextView = (TextView) futureDayLayout
.findViewById(R.id.future_temperture_tv);
futureTempertureTextView.setText(futureWeatherBean
.getTemperture());// 给相关控件赋值
futureWeatherTextView.setText(futureWeatherBean.getWeather()
+ futureWeatherBean.getWind());
futureWeekTextView.setText(futureWeatherBean.getWeek());
futureDayWeatherListLayout.addView(futureDayLayout);// 把赋值完成的布局加载到横向ScrollView的布局中去
}
三、配置显示污染程度的颜色条
1.配置color文件:在res文件夹下的values文件夹中新建一个名为color的AndroidXML文件
2.在Strings文件中配置pmLevel.(values文件夹里) 从res文件夹下的values文件夹中读取 文字/颜色常量,通过getResources()获取资源目录,再调用getString(R.string.best)/getColor(R.color.yellow) 取出常量
<color name="green">#00EE00</color>
<color name="yellow">#EEEE00</color>
<color name="orange">#EEAD0E</color>
<color name="red">#FF0000</color>
<color name="violet">#EE00EE</color>
<color name="brown">#8B6914</color>
<string name="best">优</string>
<string name="better">良</string>
<string name="pollution">轻度污染</string>
<string name="mpollution">中度污染</string>
<string name="spollution">严重污染</string>
<string name="hpollution">重度污染</string>
</resources>
**3.private void setPmcolor(String pmLevel) **
if (pmLevel.contains(getResources().getString(R.string.best))) {
pmStateColorView.setBackgroundColor(getResources().getColor(R.color.green));
}
else if (pmLevel.contains(getResources().getString(R.string.better))) {
pmStateColorView.setBackgroundColor(getResources().getColor(R.color.yellow));
四、protected void onCreate(Bundle savedInstanceState)
sharePreferences = getSharedPreferences("weather", Context.MODE_PRIVATE);
cityCode = sharePreferences.getInt("cityCode", 101010100);
findViews();
getWeatherDateFromNetwork();
setListener();
getSharedPreferences(String name, int mode):从sharePreferences取出key为cityCode的值,如果sharePreferences文件中没有这个键值,参数二为默认值,设置访问权限。
SharedPreferences: 用来存储轻量级数据,存储格式为“键值对”。
- 保存:
SharedPreferences mySharedPreferences= getSharedPreferences("test",Activity.MODE_PRIVATE);//实例化
SharedPreferences.Editor editor = mySharedPreferences.edit();//实例化editor
//用putString的方法保存数据
editor.putString("name", "Karl");//保存数据
editor.commit(); //提交当前数据
- 读取
SharedPreferences sharedPreferences= getSharedPreferences("test",Activity.MODE_PRIVATE);//实例化
String name =sharedPreferences.getString("name", "");// 获得value,参数2是默认值
Toast.makeText(this, "读取数据如下:"+"\n"+"name:" + name ,Toast.LENGTH_LONG).show(); //toast显示信息
五、@Override protected void onActivityResult(int requestCode, int resultCode, Intent data)
反向传值后会调用的方法。用if语句先区分是哪个页面的返回值。
- 参数1:用于区分不同的Activity的返回值;
- 参数2:返回值内容;
- 参数3:返回页面的Intent。
if (requestCode == 300) {
cityCode = resultCode;// 保存resultCode的值,resultCode即搜索到的城市ID。
getWeatherDateFromNetwork();
}
六、private void setListener()
refreshImageView响应方法里添加方法getWeatherDateFromNetwork()
searchImageView响应方法里添加反向传值的接收语句。反向传值调用的启动activity的方法。参数2用于区分不同activity的返回值结果。
Intent intent = new Intent(MainActivity.this,SearchCityCodeActivity.class);//跳转
startActivityForResult(intent, 300);
七、findViews() 略
八、private void getWeatherDateFromNetwork()
获取网络必须要申请获取网络状态的用户权限 ACCESS_NETWORK_STATE
1.添加用户权限:打开Mamifest文件,选取permission标签
先获取网络状态:用连接管理类ConnectivityManager的对象去获取网络连接 netWorkInfo的对象判断netWorkInfo有无,确定网络有无。此时要申请Users Permission。
- 处理异常
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netWorkInfo = manager.getActiveNetworkInfo();
if (netWorkInfo == null) {
netWorkErrorTextView.setText("网络异常,请检查网络3");
return;
}
申请网络连接是耗时操作,在子线程中操作。新建一个线程,如果线程的开启方式调用.run(),线程的Runnable()的run()方法还是在主线程中执行。调用start(),线程的Runnable的run()方法才会在新建的后台线程中执行。 给网址建立网络连接的路径。"+ cityCode + " 则显示行对应的城市,如果为0则显示本地天气。并把代码封装成getWeatherDateSuccess(WeatherBean weatherBean)和netWorkRequestError(String errorString)方法。 新建message,根据if判断赋给message What标签和内容Obj。
refreshAnimationStart();// 不能放在Thread里,要放在UI主线程里。
new Thread(new Runnable() {
public void run() {
String urlString = "http://weather.123.duba.net/static/weather_info/"+ cityCode + ".html";
StringBuffer stringBuffer = new StringBuffer(); //保存网络请求的结果
try {
String resultString =NetWorkUtils.doGet(urlString);//新建NetWorkUtils类,将代码封装成其中的一个方法
if (TextUtils.isEmpty(resultString)) { // 异常处理
netWorkRequestError("网络加载异常,请重新加载2");
return;
}
if (!resultString.contains("weather_callback")) { //异常处理
return;
}
WeatherBean weatherBean = new WeatherBean(resultString);
getWeatherDateSuccess(weatherBean);
} catch (Exception e) { // 异常捕获:把catch中的异常放大到所有异常
e.printStackTrace();
netWorkRequestError("网络加载异常,请重新加载1");
}
}
- 创建通知的消息,message.what是给这个消息设置唯一的标识,用于handlerMessage方法中区分不同的消息;message.obj保存要展示的数据对象,用于主线程刷新UI;通过Handler对象的sendMessage方法发送消息,通知主线程
private void getWeatherDateSuccess(WeatherBean weatherBean) {
Message message = new Message();
message.what = 100;
message.obj = weatherBean;
netWorkFinishHandler.sendMessage(message);
}
}).start();// 启动线程
九、private void netWorkRequestError(String errorString)
网络加载数据失败时,通知UI线程去显示提示。message.what为message的标签。动画为帧动画。
Message message = new Message();
message.what = 404;
message.obj = errorString;
netWorkFinishHandler.sendMessage(message);
十、private void refreshAnimationStart()
把动画资源设为refreshImage的背景,获取资源。 启动动画资源,当动画开启时,refreshImageView设为不可点击状态。
refreshImageView.setBackgroundResource(R.drawable.pb_bg);
refreshAnimation = (AnimationDrawable) refreshImageView.getBackground();
refreshAnimation.start();
refreshImageView.setEnabled(false);
十一、private void refreshAnimationStop()
把刷新按钮图片放到refreshImageView上,并将refreshImageView设置为可以点击
refreshAnimation.stop();
refreshImageView.setBackgroundResource(R.drawable.refresh);
refreshImageView.setEnabled(true);