(1)增、删、查信息

在搜索结束后,用户点击搜索结果会回到城市管理界面,搜索结果被添加在其中作为收藏城市,之后再打开软件收藏的城市也依然存在,用户可通过右下角“删除”按键移除收藏。这一项通过建立数据库实现。新建一个类DBHelper继承于SQLiteOpenHelper,代码如图3-15所示。

java开发如何实现天气 android开发天气预报_数据库

图 3- 15数据库设计

在定义声明需要使用的变量之后,先实现SQLiteOpenHelper子类中需要实现的三个方法:1、构造函数DBHelper()。在其中用super()重写父类SQLiteOpenHelper的构造函数,初始化context;2、onCreate()。在其中调用定义的createDBSql来创建数据库db;3、onUpgrage()方法。其把数据库从旧模型转为新模型。如图3-16。

java开发如何实现天气 android开发天气预报_搜索_02

图 3- 16 DBHelper()、onCreate()、onUpgrage()

之后设置数据库中信息存储方式为懒汉式单例模式,将信息存入dbHelper中。与饿汉式单例模式相比,这种模式在类加载时不会创建单例,只有调用到getInstance方法才会创建单例,这样可以节省资源防止访问冲突。如图3-17所示。

java开发如何实现天气 android开发天气预报_android studio_03

图 3- 17懒汉式单例模式

接着实现数据库信息插入功能。由于城市信息是多次查询才得到完整结果,所以在insertData()中采用ContentValues方式将信息传入数据库。先通过for循环将各次查询得到的键值对(即县、市、省)一一存入contentValues中,循环结束后进行组装得到完整信息,之后打开数据库将完整信息存入。如图3-18所示。

java开发如何实现天气 android开发天气预报_搜索_04

图 3- 18插入数据

将搜索到的信息添加到管理城市界面后,为方便用户使用,点击右下角“删除”按键可以将选择的城市信息从数据库中删除,更新数据库信息后重新显示在管理城市界面。删除功能的实现是根据传入的id找到对应城市信息之后移除。首先用String value0f()将传入的int数据转为字符串存入args中,之后以读写方式打开数据库,用delete()函数根据args寻找对应项进行删除。如图3-20所示。

java开发如何实现天气 android开发天气预报_android studio_05

图 3- 19删除数据

在界面显示信息前,应先将数据库信息遍历查询,从中选出需要显示的数据。因为在插入数据的时候使用的便是键值对形式,所以查询全部数据时创建一个List集合list用来存放各键值对(一个键值对是一个城市信息)。打开数据库,借助query()查询数据库并将各个查询结果赋给cursor,此时得到的结果包含有非需要显示的信息。之后使用moveToNext()方法对cursor中的信息进行遍历,从中提取需要的信息“id”、“cityname”信息,最后将提取信息与对应键关联后存入list中。

这里打开数据库的方式与增、删时候使用的方法不同。之前使用的getWritableDatabase()是以读写方式打开数据库,当数据库磁盘空间满后再使用其就会出错。而这里使用的getReadableDatabase()是先以读写方式打开数据库,数据库磁盘空间满后则以只读方式打开数据库,所以在查询数据时选用getReadableDatabase()打开方式更好。如图3-20所示。

java开发如何实现天气 android开发天气预报_搜索_06

图 3- 20查询信息

(2)利用数据库对界面信息更新

首先在CityActivity中声明三个变量:数据库工具(dbHelper),存储数据库中城市名称(name)和代码(ids)的两个数组。之后新建内部类MyAdater继承于BaseAdapter,该内部类中定义了一些内部属性,并有构造器MyAdater根据传入参数对这些属性进行赋值,具体代码如图3-21所示。

java开发如何实现天气 android开发天气预报_数据库_07

图 3- 21内部类MyAdapter

接着在onCreate()中实例化数据库工具(dbHelper),并根据数据库中的数据为ListView设置适配器changeAdapter()。其中用之前数据库中定义的getInstance()将dbHelper采用单例模式实例化,也用数据库中定义的查询方法queryAllCities()查询dbHelper中的信息,再将结果作为参数传给适配器changeAdapter(),用适配器达到更新界面效果。代码如图3-22所示。

java开发如何实现天气 android开发天气预报_搜索_08

图 3- 22实例化、适配器

在适配器changeAdapter()中先用size()获取列表中城市个数作为之前定义的ida、name两个数组的长度,之后用for循环遍历列表,将各城市Id、城市名分别存入数组ids、name中。然后将数组信息作为参数传给内部类MyAdapter,最后将内部类中被赋值的属性传给myAdapter,再用调用setAdapter()从myAdapter中读取信息传到listView,从而实现更新listView。具体代码如图3-23所示。

java开发如何实现天气 android开发天气预报_数据_09

图 3- 23适配器changeAdapter()

上述适配器的参数来源于onActivityResult()。在开发当中,有时需要从当前界面(管理城市界面)跳转到其他界面(搜索城市界面)执行操作,操作结束后又从其他界面(搜索界面)带着返回得到的数据(城市信息)一起跳转回当前界面(管理城市界面),从而实现界面间的数据交流,这种情况便采用回调函数onActivityResult()实现。

在CityActivity中的回调函数onActivityResult()代码如图3-24所示。回调函数的调用需要三个参数:第一个是requestCode。它与对应事件监听中的startActivityForResult中的requestCode相对应,设计中是和“添加”按键(addButton)中的相对应;第二个是resultCode;第三个是Intent。其中resultCode、Intent均是由子Activity(SearchActivity)通过setResult()方式将数据返回得到。也就是说是依靠这两个参数接收从搜索界面得到的搜索结果。得到参数后,先用if语句进行条件判断:

1、requestCode是否等于0。这个判断是为了确保得到的数据是来自SearchActivity。不同的监听中该判断条件会改变,此处是因为对应监听中设置为0而已;

2、resultCode是否与SearchActivity中的listView监听中设置的一致。这个是为了确保数据来自listView监听,而不是SearchActivity中其他监听。

满足这两个条件后说明数据是需要的信息,之后便用getExtras()读取信息以键值对方式存入bundle,再调用数据库insertData()方法将信息插入数据库。最后查询数据库信息作为参数传给适配器changeAdapter()并调用。

java开发如何实现天气 android开发天气预报_搜索_10

图 3- 24回调函数onActivityResult()

如果说回调函数是向管理城市界面的数据库添加信息,那么该界面的“删除”按键(deleteButton)就是从数据库中移除对应信息的操作。如图3-25所示,对删除按键设置的监听中先调用用于获取勾选城市代码的getCheckedCities()方法,将选择的城市代码全存入result,之后for循环遍历result中存的信息,根据其中的城市代码调用数据库删除函数deleteDateById()将对应城市从数据库删除。最后又将数据库剩余信息传给适配器对界面信息进行更新。

java开发如何实现天气 android开发天气预报_java开发如何实现天气_11

图 3- 25“删除”按键(deleteButton)的监听

总的来说,在数据库搭建完成之后放入CityActivity中使用,利用回调函数onActivityResult()获取SearchActivity中搜索得到的城市信息传入CityActivity的数据库。用户也可以通过对“删除”按键(deleteButton)设置的监听将被勾选的城市从数据库中删除。无论增加信息还是移除信息,最后都要查询数据库信息作为参数传给适配器changeAdapter(),从而更新listView,也就是管理城市界面的信息。

上文有提到,开始时候显示的是默认地区的天气情况,是为了可以修改显示地区才实现城市搜索和数据库两个功能,所以设计到此最后需要做的便是将管理城市界面用户点击的城市名传给主界面,之后主界面再调用天气查询功能即可。

同搜索界面传递信息给管理界面一样,管理界面传递信息给主界面使用的也是回调函数,该回调函数设置在MainActivity中,具体实现方式同之前的相似,具体代码如图3-26所示。最后一步获取城市名需要“params.length – 1”是因为得到的城市信息以空格进行分割,分割结果中的都会先有一个空格,接下来才是城市信息,所以传递城市名时需要将空格去掉。例如:传入的是“江西 九江 永修县”,分割之后的结果是“江西”、“ 九江”、“ 永修县”,若不进行“params.length – 1”操作,传给defaultName的城市名会是“ 永修县”,这会影响该地区的天气查询。

java开发如何实现天气 android开发天气预报_搜索_12

图 3- 26主界面从管理界面获取信息的回调函数

由于极速数据接口使用次数限制,设计中让接口24小时调用更新信息一次,所以主界面得到新城市名字后并不会立刻改变界面信息,用户需要点击左上角刷新按键(new_button)调用Getweather()开启网络访问活动之后界面才会更新为新城市的天气信息。这用到的是按键监听。