Android天气开发详解(1.数据库和遍历省市县)

一 使用平台:

使用和风天气提供的接口来查询天气。

全国的省市数据:会返回一段json格式的数据。

http://guolin.tech/api/china

二 创建数据库和表

先在com.Mask weather.android包下新建几个包,用来进行存储。

其中db用来存放数据库模型相关的代码,gson用于存放GSON模型相关的代码,service包用于存放服务相关diamante,util用于存放工具相关的代码。

1.添加依赖库的声明

dependencies {
    compile 'org.litepal.android:core:1.4.1'
    compile 'com.squareup.okhttp3:okhttp:3.10.0'
    compile 'com.google.code.gson:gson:2.7'
    compile 'com.github.bumptech.glide:glide:3.7.0'
}

其中包括litepal来对数据库进行操作,okhttp对网络请求进行操作,gson对json数据进行解析,glide用于加载展示图片。

2.添加表对应的三个类:

在db下简历三个类,对应数据库中的三张表。而litepal中的每一个映射的实体类都要继承自DataSupport类。

 

省表:对应province类。

 1 public class Province extends DataSupport {
 2 
 3     private int id;
 4     private String provinceName;
 5     private int provinceCode;
 6 
 7     public int getId() {
 8         return id;
 9     }
10 
11     public void setId(int id) {
12         this.id = id;
13     }
14 
15     public String getProvinceName() {
16         return provinceName;
17     }
18 
19     public void setProvinceName(String provinceName) {
20         this.provinceName = provinceName;
21     }
22 
23     public int getProvinceCode() {
24         return provinceCode;
25     }
26 
27     public void setProvinceCode(int provinceCode) {
28         this.provinceCode = provinceCode;
29     }
30 }

市表:city类

 1 public class City extends DataSupport {
 2     private int id;
 3     private String cityName;
 4     private int cityCode;
 5     private int provinceId;
 6 
 7     public int getId() {
 8         return id;
 9     }
10 
11     public void setId(int id) {
12         this.id = id;
13     }
14 
15     public String getCityName() {
16         return cityName;
17     }
18 
19     public void setCityName(String cityName) {
20         this.cityName = cityName;
21     }
22 
23     public int getCityCode() {
24         return cityCode;
25     }
26 
27     public void setCityCode(int cityCode) {
28         this.cityCode = cityCode;
29     }
30 
31     public int getProvinceId() {
32         return provinceId;
33     }
34 
35     public void setProvinceId(int provinceId) {
36         this.provinceId = provinceId;
37     }
38 }

县表:county类

 1 public class County extends DataSupport {
 2 
 3     private int id;
 4     private String countyName;
 5     private String weatherId;
 6     private int cityId;
 7 
 8     public int getId() {
 9         return id;
10     }
11 
12     public void setId(int id) {
13         this.id = id;
14     }
15 
16     public String getCountyName() {
17         return countyName;
18     }
19 
20     public void setCountyName(String countyName) {
21         this.countyName = countyName;
22     }
23 
24     public String getWeatherId() {
25         return weatherId;
26     }
27 
28     public void setWeatherId(String weatherId) {
29         this.weatherId = weatherId;
30     }
31 
32     public int getCityId() {
33         return cityId;
34     }
35 
36     public void setCityId(int cityId) {
37         this.cityId = cityId;
38     }
39 }

3.配置litepal.xml文件

在app/src/main中new一个Directory,创建一个assets目录,新建一个litepal.xml文件。

 1 <litepal>
 2     <!--数据库名称和版本-->
 3     <dbname value="Mask_weather"/>
 4     <version value="1"/>
 5     <!--将三个实体类添加到映射的列表中-->
 6     <list>
 7         <mapping class="com.example.maskweather.db.City"/>
 8         <mapping class="com.example.maskweather.db.County"/>
 9         <mapping class="com.example.maskweather.db.Province"/>
10     </list>
11 
12 </litepal>

配置LitePalApplication。修改AndroidManifest文件如下:

<application
        android:name="org.litepal.LitePalApplication"

这样数据库就建立完成了。

 

三 遍历全国省市县数据

因为在服务器中可以获取这些数据。服务器:

http://guolin.tech/api/china

1.发送获取服务器数据的网络请求

所以和服务器的交互必不可少,所以在util包中增加一个HttpUtil类用来发送网络请求。

1 /*用来发送http请求*/
2 public class HttpUtil {
3     public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
4         OkHttpClient client = new OkHttpClient();
5         Request request = new Request.Builder().url(address).build();
6         client.newCall(request).enqueue(callback);
7     }
8 }

2.解析json格式的工具类Utility

解析数据的工具类中存放了三种方法,分别用来解析省级数据、市级数据和县级数据。都是布尔型的方法,如果解析成功,返回true。解析成功数据使用save方法保存在数据库中。

 1 public class Utility {
 2     /*
 3     * 解析和处理服务器返回的省级数据
 4     * */
 5     public static boolean handleProvinceResponse(String response) {
 6         if (!TextUtils.isEmpty(response)) {
 7             try {
 8                 /*使用JSONArray和JSONObject来解析json数据
 9                 * 传入的是一个json数组,存放在JSONArray中,依次遍历放在JSONObject中
10                 * 创建一个province实例,取出JSONObject中数据存放*/
11                 JSONArray allProvinces = new JSONArray(response);
12                 for (int i = 0; i < allProvinces.length(); i++) {
13                     JSONObject provinceObject = allProvinces.getJSONObject(i);
14                     Province province = new Province();
15                     province.setProvinceName(provinceObject.getString("name"));
16                     province.setProvinceCode(provinceObject.getInt("id"));
17                     province.save();
18                 }
19                 return true;
20             } catch (JSONException e) {
21                 e.printStackTrace();
22             }
23         }
24         return false;
25     }
26 
27     /*
28     * 解析和处理服务器返回的市级数据
29     * */
30     public static boolean handleCityResponse(String response, int provinceId) {
31         if (!TextUtils.isEmpty(response)) {
32             try {
33                 JSONArray allCities = new JSONArray(response);
34                 for (int i = 0; i < allCities.length(); i++) {
35                     JSONObject cityObject = allCities.getJSONObject(i);
36                     City city = new City();
37                     city.setCityName(cityObject.getString("name"));
38                     city.setCityCode(cityObject.getInt("id"));
39                     city.setProvinceId(provinceId);
40                     city.save();
41                 }
42                 return true;
43             } catch (JSONException e) {
44                 e.printStackTrace();
45             }
46         }
47         return false;
48     }
49 
50     /*
51     * 解析和处理服务器返回的县级数据
52     * */
53     public static boolean handleCountyResponse(String response,int cityId){
54         if(!TextUtils.isEmpty(response)){
55             try {
56                 JSONArray allCounties = new JSONArray(response);
57                 for (int i=0;i<allCounties.length();i++){
58                     JSONObject countyObject = allCounties.getJSONObject(i);
59                     County county = new County();
60                     county.setCountyName(countyObject.getString("name"));
61                     county.setWeatherId(countyObject.getString("weather_id"));
62                     county.setCityId(cityId);
63                     county.save();
64                 }
65                 return true;
66             } catch (JSONException e) {
67                 e.printStackTrace();
68             }
69         }
70         return false;
71     }
72 }

以上就完成了两个工具类的编写。

 

3.使用碎片写choose_area,xml布局

在这个碎片布局中,定义了一个头布局作为标题栏,将高度设为actionBar的高度,颜色设为colorPrimary。在头布局中放了一个Testview和一个后退的button。

在标题栏下面放了一个listview用来存放

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:background="#ffffff"
 5     android:orientation="vertical">
 6 
 7     <!--头布局作为标题栏 包括一个文本和一个返回按键-->
 8     <RelativeLayout
 9         android:layout_width="match_parent"
10         android:layout_height="?attr/actionBarSize"
11         android:background="?attr/colorPrimary">
12 
13         <TextView
14             android:id="@+id/title_text"
15             android:layout_width="wrap_content"
16             android:layout_height="wrap_content"
17             android:layout_centerInParent="true"
18             android:textColor="#fff"
19             android:textSize="20sp" />
20 
21         <Button
22             android:id="@+id/back_button"
23             android:layout_width="25dp"
24             android:layout_height="25dp"
25             android:layout_alignParentLeft="true"
26             android:layout_centerVertical="true"
27             android:layout_marginLeft="10dp"
28             android:background="@drawable/ic_back" />
29 
30     </RelativeLayout>
31 
32     <ListView
33         android:id="@+id/list_view"
34         android:layout_width="match_parent"
35         android:layout_height="match_parent" />
36 </LinearLayout>

 

4.编写遍历省市县数据的碎片

 在编写碎片时,首先声明一系列元素。其中包括三个省市县登记、进度框、Testview、button、和listview原件。列表适配器和数据列表。

省市县列表以及选中的省市。以及当前选中的级别。

 1 public class ChooseAreaFragment extends Fragment {
 2     public static final int LEVEL_PROVINCE = 0;
 3     public static final int LEVEL_CITY = 1;
 4     public static final int LEVEL_COUNTY = 2;
 5 
 6     private ProgressDialog progressDialog;
 7 
 8     private TextView titleText;
 9     private Button backButton;
10     private ListView listView;
11 
12     private ArrayAdapter<String> adapter;
13     private List<String> dataList = new ArrayList<>();
14 
15     /*省列表*/
16     private List<Province> provincesList;
17 
18     /*市列表*/
19     private List<City> cityList;
20 
21     /*县列表*/
22     private List<County> countyList;
23 
24     /*选中的省份*/
25     private Province selectProvince;
26 
27     /*选中的城市*/
28     private City selectCity;
29 
30     /*当前选中的级别*/
31     private int currentLevel;

碎片初始化,并实例化各种控件。同时创造一个listview的适配器用来给listview传送数据。

 1     /*碎片初始化,将各种控件实例化
 2     * 创建一个listView的适配器,将适配器与listview绑定*/
 3     @Override
 4     public View onCreateView(LayoutInflater inflater, ViewGroup container,
 5                              Bundle savedInstanceState) {
 6         View view = inflater.inflate(R.layout.choose_area, container, false);
 7         titleText = (TextView) view.findViewById(R.id.title_text);
 8         backButton = (Button) view.findViewById(R.id.back_button);
 9         listView = (ListView) view.findViewById(R.id.list_view);
10         adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, dataList);
11         listView.setAdapter(adapter);
12         return view;
13     }

为listview和button添加点击事件,currentLevel表示现在的级别。通过点击事件,调用相应的方法,来查询相关的省市县。

 1     /*为listview和button设置了点击事件,currentLevel表示现在处于的级别*/
 2     @Override
 3     public void onActivityCreated(Bundle saveInstanceState) {
 4         super.onActivityCreated(saveInstanceState);
 5         listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
 6             @Override
 7             public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
 8                 if (currentLevel == LEVEL_PROVINCE) {
 9                     selectProvince = provincesList.get(position);
10                     queryCities();
11                 } else if (currentLevel == LEVEL_CITY) {
12                     selectCity = cityList.get(position);
13                     queryCounties();
14                 }
15             }
16         });
17         backButton.setOnClickListener(new View.OnClickListener() {
18             @Override
19             public void onClick(View view) {
20                 if (currentLevel == LEVEL_COUNTY) {
21                     queryCities();
22                 } else if (currentLevel == LEVEL_CITY) {
23                     queryProvinces();
24                 }
25             }
26         });
27         queryProvinces();
28     }

然后是查询省市县的具体方法,三个大体流程差不多,都是先设置标题栏的文字和后退按键。

然后在省市县列表先将数据库中的相应数据加入到列表中。

判断列表是否为空,如果不为空的话,说明在数据库中有相关的数据,将适配器的数据datalist清空,然后遍历这个列表,将列表中的数据都添加到datalist中。

遍历结束后,更新listview的数据对其进行通知,并将选择移动到首位。然后改相关的等级。

如果列表为空,调用queryFromService方法,传入地址和类型,进行对服务器数据的访问请求。

 1     /*
 2     * 查询全国所有的省,先从数据库查,没有的话从服务器上查询
 3     * */
 4     private void queryProvinces() {
 5         titleText.setText("中国");
 6         backButton.setVisibility(View.GONE);//在最初设为不可见
 7         provincesList = DataSupport.findAll(Province.class);
 8         if (provincesList.size() > 0) {
 9             dataList.clear();
10             for (Province province : provincesList) {
11                 dataList.add(province.getProvinceName());
12             }
13             adapter.notifyDataSetChanged(); //更新了listview中数据,对其进行通知
14             listView.setSelection(0);  //将选择移到列表开始
15             currentLevel = LEVEL_PROVINCE;
16         } else {
17             String address = "http://guolin.tech/api/china";
18             queryFromServer(address, "province");
19         }
20     }
21 
22     /*
23     * 查询选中省内全部的市 优先从数据库查询,没有就从网上查询
24     * */
25     private void queryCities() {
26         titleText.setText(selectProvince.getProvinceName());
27         backButton.setVisibility(View.VISIBLE);
28         cityList = DataSupport.where("provinceid=?",
29                 String.valueOf(selectProvince.getId())).find(City.class);
30         if (cityList.size() > 0) {
31             dataList.clear();
32             for (City city : cityList) {
33                 dataList.add(city.getCityName());
34             }
35             adapter.notifyDataSetChanged();
36             listView.setSelection(0);
37             currentLevel = LEVEL_CITY;
38         } else {
39             int provinceCode = selectProvince.getProvinceCode();
40             String address = "http://guolin.tech/api/china/" + provinceCode;
41             queryFromServer(address, "city");
42         }
43     }
44 
45     /*
46     * 查询选中市内所有的县 优先从数据库查询,其次从服务器查询
47     * */
48     private void queryCounties() {
49         titleText.setText(selectCity.getCityName());
50         backButton.setVisibility(View.VISIBLE);
51         countyList = DataSupport.where("cityid=?",
52                 String.valueOf(selectCity.getCityCode())).find(County.class);
53         if (countyList.size() > 0) {
54             dataList.clear();
55             for (County county : countyList) {
56                 dataList.add(county.getCountyName());
57             }
58             adapter.notifyDataSetChanged();
59             listView.setSelection(0);
60             currentLevel = LEVEL_COUNTY;
61         }else{
62             int provinceCode = selectProvince.getProvinceCode();
63             int cityCode = selectCity.getCityCode();
64             String address = "http://guolin.tech/api/china/"+provinceCode+"/"+cityCode;
65             queryFromServer(address,"country");
66         }
67     }

queryFromService()方法对服务器进行数据查询,首先调出进度加载框。然后调用HttpUil的发送网络请求,并传入地址。

如果加载服务器数据失败,则调用返回主线程处理逻辑,关闭进度框,并发送提示加载失败。

如果加载服务器数据成功,先初始化返回数据,布尔型result,result用来判断是否查询成功。

判断查询数据类型,然后进行json数据解析(在utility中解析相关类型数据)解析出对应的数据。

如果查询成功,返回主线程进行ui修改,关闭进度框,并再次执行相关等级的查询(此时就在数据库中查询,然后加入到listview的datalist中显示出来。)。

 

 1     /*
 2     * 显示进度对话框
 3     * */
 4     private void showProgressDialog() {
 5         if (progressDialog == null) {
 6             progressDialog = new ProgressDialog(getActivity());
 7             progressDialog.setMessage("正在加载...");
 8             progressDialog.setCanceledOnTouchOutside(false);
 9         }
10         progressDialog.show();
11     }
12 
13     /*
14     * 关闭进度对话框
15     * */
16     private void closeProgressDialog() {
17         if (progressDialog != null) {
18             progressDialog.dismiss();
19         }
20     }
21 }

最后是两个具体方法,显示进度框和关闭进度框。

转载于:https://www.cnblogs.com/Mask-D/p/9646366.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值