使用Google Weather API 制作天气预报应用
2012-08-04 13:12
330 查看
大家在使用android手机的时候,肯定都是用过天气预报的应用,market上面已经有了不少很成熟的产品.当然,作为开发者而言,一定会对这种应用的开发很感兴趣,我们自己来写一款类似的应用.
首先,要开发一款天气预报应用,一定要有一个web服务端来提供数据,这个数据源我们自己肯定是没办法弄的,所以就需要一个第三方机构为我们提供天气数据.这种机构其实有很多,不过大多数都是收费的,当然这些收费的数据源提供的数据会更加丰富详细.如果不想花钱去购买这些收费的数据服务,我们还有另一种替代方案-就是使用免费的天气数据,这篇文章了为大家介绍一个Google 提供的天气API,通过浏览器访问下面的链接
http://www.google.com/ig/api?hl=zh-cn&weather=Beijing
如果你的浏览器可以直接显示XML文档,那么就会得到类似下面这样的数据:
当然,这里只给大家列出一个片断,完整的数据大家可以自己用浏览器来查看.上面这段数据给我们提供了气温的数字和文字描述,还给我们提供了一幅表示当天天气状况的图片。对于我们这个简单的天气应用,这些数据已经足够了。
有了数据之后,我们就开始开发吧,怎么建项目就不用我说了吧,呵呵。虽然这个应用很简单,但我们还需要把结构稍微整理一下,我们需要用一个实体类来表示天气数据:
public class Weather {
private String day;
private String lowTemp;
private String highTemp;
private String imageUrl;
private String condition;
}
我们通过XML文档提供的数据格式来定义我们实体类,这里面包含了,当天是周几,最低气温,最高气温,天气图片的地址,和天气状况的文字描述.为了节省篇幅 getter和setter方法就省略了,现在我们已经把我们需要的数据封装好了.
接下来我们需要解析XML数据,将服务器返回给我们的XML格式的数据,转换成程序比较好操作的对象,我们可以使用SAX来解析XML文档,关于SAX的更多细节,不是本篇文章要讨论的内容,不过为了让大家好理解,还是简单的叙述一下.
SAX其实是解析XML文档的一种方法,一般处理XML数据有两种方法,一种是将数据先解析为一种树形结构,然后我们再来在这个结构上访问数据,这种方法是我们通常会直接想到的,而SAX则采用了另外一种方法,这种方法简单来说就是,当解析器遍历XML文档的时候,会给提供我们一些回调函数,比如遇到起始标签,遇到结束标签,或是遇到标签中的文字等等,这是一种基于事件的解析方式,所以我们需要一个类来处理这些事件,并且将需要的数据保存下来,就产生了下面这段代码:
---------------------------------------------------
public class XmlHandler extends DefaultHandler {
private List<Weather> weatherList;
private boolean inForcast;
private Weather currentWeather;
public List<Weather> getWeatherList() {
return weatherList;
}
public void setWeatherList(List<Weather> weatherList) {
this.weatherList = weatherList;
}
public XmlHandler() {
weatherList = new ArrayList<Weather>();
inForcast = false;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
String tagName = localName.length() != 0 ? localName : qName;
tagName = tagName.toLowerCase();
if(tagName.equals("forecast_conditions")) {
inForcast = true;
currentWeather = new Weather();
}
if(inForcast) {
if(tagName.equals("day_of_week")) {
currentWeather.setDay(attributes.getValue("data"));
}else if(tagName.equals("low")) {
currentWeather.setLowTemp(attributes.getValue("data"));
}else if(tagName.equals("high")) {
currentWeather.setHighTemp(attributes.getValue("data"));
}else if(tagName.equals("icon")) {
currentWeather.setImageUrl(attributes.getValue("data"));
}else if(tagName.equals("condition")) {
currentWeather.setCondition(attributes.getValue("data"));
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
String tagName = localName.length() != 0 ? localName : qName;
tagName = tagName.toLowerCase();
if(tagName.equals("forecast_conditions")) {
inForcast = false;
weatherList.add(currentWeather);
}
}
}
--------------------------------------------------------
startElement方法,代表遇到起始标签,我们在这里得到了标签名,如果遇到forecast_conditions标签,我们就会标记一下,并且创建一个天气实体对象,下面的if语句中,判断了是否在forecast_conditions标签内,如果在的话,就把它里面相应的属性提取出来。
endElement 方法,代表遇到结束标签,我们的代码里,如果遇到forecast_conditions标签,那么就证明当前这条天气数据已经解析完成,所以我们将该实体对象保存到List列表中,以便以后使用。
现在终于处理完数据了,其实这个程序本身并不是很复杂,大半的代码都用在了解析数据上面。下面开始进入我们的主程序,首先来看看我们的布局文件
---------------------------------------------------------
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/txCity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="9"
/>
<Button
android:id="@+id/btnSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="查询"
/>
</LinearLayout>
<TableLayout
android:id="@+id/table"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1,2,3,4"
>
</TableLayout>
</LinearLayout>
--------------------------------------------------------------------------
顶部定义了一个文本框,和一个查询按钮,下面是一个表格布局,这个非常简单.
下面就到了最后一个部分,也是程序中主要的部分,我们的Activity代码,首先,我们需要定义一个查询天气的方法:
--------------------------------------------------------------------------
private void searchWeather(String city) {
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
SAXParser sp = spf.newSAXParser();
XMLReader reader = sp.getXMLReader();
XmlHandler handler = new XmlHandler();
reader.setContentHandler(handler);
URL url = new URL("http://www.google.com/ig/api?hl=zh-cn&weather=" + URLEncoder.encode(city));
InputStream is = url.openStream();
InputStreamReader isr = new InputStreamReader(is,"GBK");
InputSource source = new InputSource(isr);
reader.parse(source);
List<Weather> weatherList = handler.getWeatherList();
TableLayout table = (TableLayout)findViewById(R.id.table);
table.removeAllViews();
for(Weather weather : weatherList) {
TableRow row = new TableRow(this);
row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
row.setGravity(Gravity.CENTER_VERTICAL);
ImageView img = new ImageView(this);
img.setImageDrawable(loadImage(weather.getImageUrl()));
img.setMinimumHeight(80);
row.addView(img);
TextView day = new TextView(this);
day.setText(weather.getDay());
day.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(day);
TextView temp = new TextView(this);
temp.setText(weather.getLowTemp() + "℃ - " + weather.getHighTemp() + "℃");
temp.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(temp);
TextView condition = new TextView(this);
condition.setText(weather.getCondition());
condition.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(condition);
table.addView(row);
}
} catch (Exception e) {
new AlertDialog.Builder(this)
.setTitle("解析错误")
.setMessage("获取天气数据失败,请稍候再试。")
.setNegativeButton("确定", null)
.show();
}
}
-------------------------------------------------------------
大家看看代码应该就差不多都明白了,这个方法开始的部分,我们使用SAX相关的API来处理XML数据,有几处地方需要说明一下:
InputStreamReader isr = new InputStreamReader(is,"GBK");
由于API返回给我们的中文是国标编码的,而SAX默认会以UTF-8来处理得到的数据,所以我们要在输入流中指定一下编码格式。接下来调用reader.parse(source);方法来解析我们的输入源,这里的一连串SAX方法调用,表达的目的应该很清楚了,相信以大家的水平,即使以前没有用过,也能很容易看明白.
接下来的代码应该就比较简单了,都是一些控件的操作,当我们解析完数据,得到对象集合之后,我们就能够遍历这个集合,然后将每条记录,用一个TableRow来包含上。在异常处理中,我们弹出一个对话框,来告诉用户本次请求中出现了问题。注意到我们在处理图片的时候用到了一个loadImage方法,这个是我们自己定义的工具方法,用来通过图片的url来加载相应图片:
private Drawable loadImage(String url) {
try {
return Drawable.createFromStream((InputStream) new URL("http://www.google.com/" + url).getContent(), "test");
} catch (MalformedURLException e) {
Log.e("exception",e.getMessage());
} catch (IOException e) {
Log.e("exception",e.getMessage());
}
return null;
}
-----------------------------------------------------------------
这个方法做的事情就是将google 返回给我们的url,转换为android中的Drawable对象,仔细观察的人在刚才看xml数据的时候可能注意到了,google给我们提供的图片地址是相对于它的站点根目录的相对路径,所以我们在请求图片的时候,还需要加上google站点的前缀。这样,我们获取天气数据的逻辑就彻底完成了。
当然,基本功能虽然实现了,但作为一个应用,我们是不是应该把它的体验做的更好呢,如果我们在应用主线程中调用这个方法,就会造成同步网络通信,这个可是客户端应用程序最忌讳的东西,在通信过程中用户的界面会被完全阻塞住,非常影响体验。所以我们一定需要一个异步的通信机制来完成请求数据的过程。异步操作的话,就需要另外一个线程来获取数据并且更新视图。而在android中,处于安全方面的原因,非GUI线程是不能操作用户的界面控件的。也就是说我们没有办法在另外一个单独的线程中直接给我们的Table增加子控件。
但这并不代表我们就没有办法了,android为我们提供了一种叫做Handler的机制来异步更新我们的界面元素,与线程不同的是,它需要一个Message来激活它,当然,这个听起来好像挺复杂的,不过使用起来真的很简单,就来看看下面的代码吧:
private TextView txCity;
private Button btnSearch;
private Handler weatherHandler;
private Dialog progressDialog;
private Timer timer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
timer = new Timer();
txCity = (TextView)findViewById(R.id.txCity);
btnSearch = (Button)findViewById(R.id.btnSearch);
progressDialog = new AlertDialog.Builder(this)
.setTitle("读取数据中")
.setMessage("正在加载数据,请稍等")
.create();
weatherHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
final String cityName = txCity.getText().toString();
searchWeather(cityName);
progressDialog.hide();
}
};
btnSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
progressDialog.show();
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.setTarget(weatherHandler);
msg.sendToTarget();
}
},100);
}
});
}
---------------------------------------------------------------------
我们定义了几个私有成员,这其中有TextView,Button,Handler,Dialog和Timer。在onCreate方法开始时,我们做了一些初始化操作,下面对需要讲解的地方简单说明一下:
progressDialog = new AlertDialog.Builder(this)
.setTitle("读取数据中")
.setMessage("正在加载数据,请稍等")
.create();
这段代码定义了一个对话框,用来提示用户程序正在请求天气数据,这里使用里Builder方式来构建对话框,到这里只是将这个对话框构造出来,但并没有显示给用户.
weatherHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
final String cityName = txCity.getText().toString();
searchWeather(cityName);
progressDialog.hide();
}
};
------------------------------------------------------
这里定义了前面提到的Handler,注意到我们继承了这个类,并且实现了handleMessage方法,这是一个回调方法,需要有一个Message来激发它,当Message到来的时候,就会执行这个方法中的代码,这里面的代码是指我们主线程之外执行的,所以不必担心会阻塞用户界面,方法的实现也很简单,我们获取了文本框中输入的城市,然后调用了前面定义好的searchWeather方法来获取天气数据,当获取到数据之后,就会调用hide方法来隐藏提示退化框。
我们定义好了消息的接收者和具体处理方式,接下来就需要调用它了,大家可能已经想到了,那就是在我们前面定义的Button中来给Handler发送消息,如下代码:
btnSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
progressDialog.show();
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.setTarget(weatherHandler);
msg.sendToTarget();
}
},100);
}
});
首先,要开发一款天气预报应用,一定要有一个web服务端来提供数据,这个数据源我们自己肯定是没办法弄的,所以就需要一个第三方机构为我们提供天气数据.这种机构其实有很多,不过大多数都是收费的,当然这些收费的数据源提供的数据会更加丰富详细.如果不想花钱去购买这些收费的数据服务,我们还有另一种替代方案-就是使用免费的天气数据,这篇文章了为大家介绍一个Google 提供的天气API,通过浏览器访问下面的链接
http://www.google.com/ig/api?hl=zh-cn&weather=Beijing
如果你的浏览器可以直接显示XML文档,那么就会得到类似下面这样的数据:
当然,这里只给大家列出一个片断,完整的数据大家可以自己用浏览器来查看.上面这段数据给我们提供了气温的数字和文字描述,还给我们提供了一幅表示当天天气状况的图片。对于我们这个简单的天气应用,这些数据已经足够了。
有了数据之后,我们就开始开发吧,怎么建项目就不用我说了吧,呵呵。虽然这个应用很简单,但我们还需要把结构稍微整理一下,我们需要用一个实体类来表示天气数据:
public class Weather {
private String day;
private String lowTemp;
private String highTemp;
private String imageUrl;
private String condition;
}
我们通过XML文档提供的数据格式来定义我们实体类,这里面包含了,当天是周几,最低气温,最高气温,天气图片的地址,和天气状况的文字描述.为了节省篇幅 getter和setter方法就省略了,现在我们已经把我们需要的数据封装好了.
接下来我们需要解析XML数据,将服务器返回给我们的XML格式的数据,转换成程序比较好操作的对象,我们可以使用SAX来解析XML文档,关于SAX的更多细节,不是本篇文章要讨论的内容,不过为了让大家好理解,还是简单的叙述一下.
SAX其实是解析XML文档的一种方法,一般处理XML数据有两种方法,一种是将数据先解析为一种树形结构,然后我们再来在这个结构上访问数据,这种方法是我们通常会直接想到的,而SAX则采用了另外一种方法,这种方法简单来说就是,当解析器遍历XML文档的时候,会给提供我们一些回调函数,比如遇到起始标签,遇到结束标签,或是遇到标签中的文字等等,这是一种基于事件的解析方式,所以我们需要一个类来处理这些事件,并且将需要的数据保存下来,就产生了下面这段代码:
---------------------------------------------------
public class XmlHandler extends DefaultHandler {
private List<Weather> weatherList;
private boolean inForcast;
private Weather currentWeather;
public List<Weather> getWeatherList() {
return weatherList;
}
public void setWeatherList(List<Weather> weatherList) {
this.weatherList = weatherList;
}
public XmlHandler() {
weatherList = new ArrayList<Weather>();
inForcast = false;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
String tagName = localName.length() != 0 ? localName : qName;
tagName = tagName.toLowerCase();
if(tagName.equals("forecast_conditions")) {
inForcast = true;
currentWeather = new Weather();
}
if(inForcast) {
if(tagName.equals("day_of_week")) {
currentWeather.setDay(attributes.getValue("data"));
}else if(tagName.equals("low")) {
currentWeather.setLowTemp(attributes.getValue("data"));
}else if(tagName.equals("high")) {
currentWeather.setHighTemp(attributes.getValue("data"));
}else if(tagName.equals("icon")) {
currentWeather.setImageUrl(attributes.getValue("data"));
}else if(tagName.equals("condition")) {
currentWeather.setCondition(attributes.getValue("data"));
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
String tagName = localName.length() != 0 ? localName : qName;
tagName = tagName.toLowerCase();
if(tagName.equals("forecast_conditions")) {
inForcast = false;
weatherList.add(currentWeather);
}
}
}
--------------------------------------------------------
startElement方法,代表遇到起始标签,我们在这里得到了标签名,如果遇到forecast_conditions标签,我们就会标记一下,并且创建一个天气实体对象,下面的if语句中,判断了是否在forecast_conditions标签内,如果在的话,就把它里面相应的属性提取出来。
endElement 方法,代表遇到结束标签,我们的代码里,如果遇到forecast_conditions标签,那么就证明当前这条天气数据已经解析完成,所以我们将该实体对象保存到List列表中,以便以后使用。
现在终于处理完数据了,其实这个程序本身并不是很复杂,大半的代码都用在了解析数据上面。下面开始进入我们的主程序,首先来看看我们的布局文件
---------------------------------------------------------
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/txCity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="9"
/>
<Button
android:id="@+id/btnSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="查询"
/>
</LinearLayout>
<TableLayout
android:id="@+id/table"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1,2,3,4"
>
</TableLayout>
</LinearLayout>
--------------------------------------------------------------------------
顶部定义了一个文本框,和一个查询按钮,下面是一个表格布局,这个非常简单.
下面就到了最后一个部分,也是程序中主要的部分,我们的Activity代码,首先,我们需要定义一个查询天气的方法:
--------------------------------------------------------------------------
private void searchWeather(String city) {
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
SAXParser sp = spf.newSAXParser();
XMLReader reader = sp.getXMLReader();
XmlHandler handler = new XmlHandler();
reader.setContentHandler(handler);
URL url = new URL("http://www.google.com/ig/api?hl=zh-cn&weather=" + URLEncoder.encode(city));
InputStream is = url.openStream();
InputStreamReader isr = new InputStreamReader(is,"GBK");
InputSource source = new InputSource(isr);
reader.parse(source);
List<Weather> weatherList = handler.getWeatherList();
TableLayout table = (TableLayout)findViewById(R.id.table);
table.removeAllViews();
for(Weather weather : weatherList) {
TableRow row = new TableRow(this);
row.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
row.setGravity(Gravity.CENTER_VERTICAL);
ImageView img = new ImageView(this);
img.setImageDrawable(loadImage(weather.getImageUrl()));
img.setMinimumHeight(80);
row.addView(img);
TextView day = new TextView(this);
day.setText(weather.getDay());
day.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(day);
TextView temp = new TextView(this);
temp.setText(weather.getLowTemp() + "℃ - " + weather.getHighTemp() + "℃");
temp.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(temp);
TextView condition = new TextView(this);
condition.setText(weather.getCondition());
condition.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(condition);
table.addView(row);
}
} catch (Exception e) {
new AlertDialog.Builder(this)
.setTitle("解析错误")
.setMessage("获取天气数据失败,请稍候再试。")
.setNegativeButton("确定", null)
.show();
}
}
-------------------------------------------------------------
大家看看代码应该就差不多都明白了,这个方法开始的部分,我们使用SAX相关的API来处理XML数据,有几处地方需要说明一下:
InputStreamReader isr = new InputStreamReader(is,"GBK");
由于API返回给我们的中文是国标编码的,而SAX默认会以UTF-8来处理得到的数据,所以我们要在输入流中指定一下编码格式。接下来调用reader.parse(source);方法来解析我们的输入源,这里的一连串SAX方法调用,表达的目的应该很清楚了,相信以大家的水平,即使以前没有用过,也能很容易看明白.
接下来的代码应该就比较简单了,都是一些控件的操作,当我们解析完数据,得到对象集合之后,我们就能够遍历这个集合,然后将每条记录,用一个TableRow来包含上。在异常处理中,我们弹出一个对话框,来告诉用户本次请求中出现了问题。注意到我们在处理图片的时候用到了一个loadImage方法,这个是我们自己定义的工具方法,用来通过图片的url来加载相应图片:
private Drawable loadImage(String url) {
try {
return Drawable.createFromStream((InputStream) new URL("http://www.google.com/" + url).getContent(), "test");
} catch (MalformedURLException e) {
Log.e("exception",e.getMessage());
} catch (IOException e) {
Log.e("exception",e.getMessage());
}
return null;
}
-----------------------------------------------------------------
这个方法做的事情就是将google 返回给我们的url,转换为android中的Drawable对象,仔细观察的人在刚才看xml数据的时候可能注意到了,google给我们提供的图片地址是相对于它的站点根目录的相对路径,所以我们在请求图片的时候,还需要加上google站点的前缀。这样,我们获取天气数据的逻辑就彻底完成了。
当然,基本功能虽然实现了,但作为一个应用,我们是不是应该把它的体验做的更好呢,如果我们在应用主线程中调用这个方法,就会造成同步网络通信,这个可是客户端应用程序最忌讳的东西,在通信过程中用户的界面会被完全阻塞住,非常影响体验。所以我们一定需要一个异步的通信机制来完成请求数据的过程。异步操作的话,就需要另外一个线程来获取数据并且更新视图。而在android中,处于安全方面的原因,非GUI线程是不能操作用户的界面控件的。也就是说我们没有办法在另外一个单独的线程中直接给我们的Table增加子控件。
但这并不代表我们就没有办法了,android为我们提供了一种叫做Handler的机制来异步更新我们的界面元素,与线程不同的是,它需要一个Message来激活它,当然,这个听起来好像挺复杂的,不过使用起来真的很简单,就来看看下面的代码吧:
private TextView txCity;
private Button btnSearch;
private Handler weatherHandler;
private Dialog progressDialog;
private Timer timer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
timer = new Timer();
txCity = (TextView)findViewById(R.id.txCity);
btnSearch = (Button)findViewById(R.id.btnSearch);
progressDialog = new AlertDialog.Builder(this)
.setTitle("读取数据中")
.setMessage("正在加载数据,请稍等")
.create();
weatherHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
final String cityName = txCity.getText().toString();
searchWeather(cityName);
progressDialog.hide();
}
};
btnSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
progressDialog.show();
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.setTarget(weatherHandler);
msg.sendToTarget();
}
},100);
}
});
}
---------------------------------------------------------------------
我们定义了几个私有成员,这其中有TextView,Button,Handler,Dialog和Timer。在onCreate方法开始时,我们做了一些初始化操作,下面对需要讲解的地方简单说明一下:
progressDialog = new AlertDialog.Builder(this)
.setTitle("读取数据中")
.setMessage("正在加载数据,请稍等")
.create();
这段代码定义了一个对话框,用来提示用户程序正在请求天气数据,这里使用里Builder方式来构建对话框,到这里只是将这个对话框构造出来,但并没有显示给用户.
weatherHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
final String cityName = txCity.getText().toString();
searchWeather(cityName);
progressDialog.hide();
}
};
------------------------------------------------------
这里定义了前面提到的Handler,注意到我们继承了这个类,并且实现了handleMessage方法,这是一个回调方法,需要有一个Message来激发它,当Message到来的时候,就会执行这个方法中的代码,这里面的代码是指我们主线程之外执行的,所以不必担心会阻塞用户界面,方法的实现也很简单,我们获取了文本框中输入的城市,然后调用了前面定义好的searchWeather方法来获取天气数据,当获取到数据之后,就会调用hide方法来隐藏提示退化框。
我们定义好了消息的接收者和具体处理方式,接下来就需要调用它了,大家可能已经想到了,那就是在我们前面定义的Button中来给Handler发送消息,如下代码:
btnSearch.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
progressDialog.show();
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.setTarget(weatherHandler);
msg.sendToTarget();
}
},100);
}
});
相关文章推荐
- 使用jQuery、Yahoo API和HTML5的geolocation来开发一个天气预报web应用
- 使用jQuery、Yahoo API和HTML5的geolocation来开发一个天气预报web应用
- 树梅派应用30:使用树莓派+GPS制作行车记录
- Android使用XmlPullParser解析XML以及天气预报信息api使用
- Android应用开发中如何使用隐藏的API
- 使用Google Weather API查询天气预报
- 使用 UDDI V3 API 构建安全的 UDDI 应用(
- 如何在 Swift 语言下使用 iOS Charts API 制作漂亮图表?
- Flex中利用ExternalInterface API从JavaScript中获取内容并在Flex应用中使用的例子
- 使用OLAMI自然语言开放平台提供的API接口制作自己的语音助手
- 在Mac下面使用rebar3制作应用,发布到CentOS7
- C#.NET使用Window API 制作淡入淡出特殊效果
- JavaEE Tutorials (15) - 对Java持久化API应用使用二级缓存
- 在企业应用中使用Java数据挖掘API
- 在Bluemix 使用OpenWhisk and AlchemyAPI 开发人脸辨识应用系统
- 如何使用Google Map API开发Android地图应用
- 使用Google Weather的API
- C#开发微信门户及应用(32)--微信支付接入和API封装使用
- 使用Google Map Api在Android平台上开发地图应用3
- KnockoutJS 3.X API 第五章 高级应用(5) 使用预处理扩展Knockout绑定语法