快捷查询工具的开发
生活中,我们经常会对天气、快递、号码归属地以及火车票进行查询,虽然这些功能都有相对应的应用,但是将这些功能放在一起,岂不更加方便快捷!我们第一步给软件起一个简单明了的名字,就叫它快捷查询工具,英文名叫做QuickSearch,下面就是开始实战操作吧!
1 功能需求及技术可行性分析
在开始编码之前,我们首先对程序进行需求分析,思考快捷查询工具都具备哪些查询功能。将这些功能一一都整理出来,我们才好各个击破。在这里我认为,快捷查询工具应具备以下查询功能。
1. 可以查询全国任意城市的天气信息。
2. 可以查看一些快递单号的信息。
3. 可以对手机号码归属地查询。
4. 可以对火车票信息进行查询。
这个简单的应用虽然看上去只有四个主要功能特点,但如果达到预期的查询效果却需要用到UI、网络、服务等技术,这也是非常考验综合应用能力的。涉及到的这些功能我们在前面都一一实现过,用心仔细的做,相信你会成功的。
分析完功能需求之后,我们就要进行技术可行性分析了。首先我们需要考虑如何获得全国各个城市的数据信息和各个城市的天气情况。通过前面的学习,我们已经知道,我们可以通过网上免费的天气预报接口来实现。在这里我们准备使用雅虎天气来实现这个功能。
比如要想得到各个城市的天气信息,只需要访问如下地址:
http://weather.yahooapis.com/forecastrss
此时服务器会返还一些文本信息,这些数据到底以什么样的格式在网络上传输呢?一般网络上传输的格式化后数据会有一定的结构规格和语义,网络上数据传输时最常用的格式有XML和JSON两种格式,这里我们就接收XML格式的,并采用Pull方式便可解析出来我们需要的数据信息。
确定了技术可行之后,接下来就可以开始编码了。在此之前,我们要让快捷查询工具成为一个开源软件,使用GitHub进行代码托管。
2 Git时间,将代码托管到GitHub上
经过前面几章的学习,相信你已经可以非常熟练地使用Git了,这次我们将会把快捷查询工具的代码托管到GitHub上面。
GitHub是全球最大的代码托管网站,主要是借助Git来进行版本控制的。任何开源软件都可以免费地将代码提交到GitHub上,以零成本的代价进行代码托管。
由于前面的学习,我们已熟练掌握代码托管的问题,在这里不做详细介绍。
3 创建资源
从这里开始,我们就要真正的开始编写代码了,为了使项目让人看起来有简单明了的结构,需要在src文件夹下新建几个包,如图1所示:
图1
其中search包用于存放于查询活动相关的代码,common包用于存放与各种查询有关的工具代码(比如网络访问、适配器等),ems包用于存放快递查询的相关代码,ip用于存放IP地址查询相关的代码,telephone包用于存放电话归属地查询相关的代码,train包用于存放火车票查询相关的代码,weather用于存放天气查询相关的代码。
3.1主页面UI设计
根据第1节进行的技术可行性分析,首先第一阶段我们要做的就是设计好主页面,这样才能进行各种点击事件的查询。
修改activity_main.xml中的代码文件,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/bg"
android:orientation="vertical">
<!-- title栏 -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/title_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="100dp"
android:maxHeight="30dp"
android:src="@drawable/logo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="5dp"
android:textSize="18sp"
android:textColor="@color/white"
android:textStyle="bold"
android:text="@string/app_name"/>
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:maxWidth="190dp"
android:maxHeight="45dp"
android:src="@drawable/quick"/>
<!-- content栏 -->
<ListView
android:id="@android:id/list"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="10dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/shape_block"/>
</LinearLayout>
在这个布局文件中,我们用到了基本的ImageView、TextView控件来显示信息,然后嵌套多层LinearLayout用于控制控件的显示位置,最后又在LinearLayout布局中加入了ListView,用于显示各种查询工具的点击事件。
接下来修改MainActivity中的代码,如下所示:
public class MainActivity extends ListActivity{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setContentView(R.layout.main);
List<Map<String, Object>> datas = this.getDatas();
ImageAdapter adapter = new ImageAdapter(this, datas);
this.getListView().setAdapter(adapter);
}
public void onListItemClick(ListView l, View v, int position, long id){
Intent intent = new Intent();
switch(position){
case 0:
//号码归属地查询
intent.setClass(this, TelephoneSearch.class);
startActivity(intent);
break;
case 1:
//天气查询
intent.setClass(this, WeatherSearch.class);
startActivity(intent);
break;
case 2:
//快递查询
intent.setClass(this, EmsSearch.class);
startActivity(intent);
break;
case 3:
//火车查询
intent.setClass(this, TrainSearch.class);
startActivity(intent);
break;
case 4:
//IP查询
intent.setClass(this, IpSearch.class);
startActivity(intent);
break;
}
}
public List<Map<String, Object>> getDatas(){
List<Map<String, Object>> results = new ArrayList<Map<String,Object>>();
String[] items = this.getResources().getStringArray(R.array.menu);
for(int i=0; i<items.length; i++){
Map<String, Object> item = new HashMap<String, Object>();
item.put("left", R.drawable.item_left);
item.put("text",items[i]);
item.put("right", R.drawable.item_right);
results.add(item);
}
return results;
}
}
不过,数据是无法直接传递给ListView的,我们还需要借助适配器来完成。这里由于我们提供的是字符串,因此在构造函数中依次传入当前上下文和适配的数据即可。最后调用ListView的setAdapter()方法,将构建好的适配器对象传递进去,这样ListVie和数据之间的关联就建立完成了。
在com.wyd.search.common包中新建类ImageAdapter.java,构造适配器如下:
public class ImageAdapter extends BaseAdapter {
private List<Map<String, Object>> datas;
private Context context;
public ImageAdapter(Context context, List<Map<String, Object>> datas){
this.context = context;
this.datas = datas;
}
虽然ListView可用于展示大量数据,但仅仅只能满足我们视觉上的满足,我们也希望它能响应用户的点击事件,进入相应的查询输入界面。从上面可以看到,我们使用了onListItemClick()方法,在这个方法中使用position参数判断用户点击的是哪一个子项,然后使用Intent进入相应的界面。