Android第一行代码 CoolWeather综合练习

一:概述

项目思路基本参照guolin大神《Android第一行代码》第二版的CoolWeather源码。不过对部分内容进行了改动,并且引入了定位之类的功能。

二:主要改动部分的图览

1项目第一次安装运行的时候会请求获取位置信息,并且根据当前的省份,直接给出所在省会城市的天气。见下图

ps:

(1):本想直接具体到区县的天气。但是因为guolin大神给出的服务器反馈的数据不全,作者所在的市区就不在服务器返回的数据之列,只能直接具体到省会城市了。

(2):因为项目使用BD(百度地图)的定位功能,所以无法在模拟器上成功运行,均用手机截图


2 选择城市列表进行了改动。见下图

透明背景更加美观,给出了各级城市范围和列出用户之前的选项


三:源码改动部分

1,统一接口封装。 对JSON,OKHTTP3,NETWORK封装处理

      在第一行代码中,guolin大神在几个handle方法中用的JSONArray JSONObject的方法解析,这里作者统一的用封装GSON来处理JSON数据。

     在第一行代码中,没有对NetWork进行判断,因为用户可能需要访问服务器,需要网络支持,这里作者将网络的状态进行了封装和调用处理

public class Utils {

    /*
      通用的网络访问回馈接口
     */
    public static void sendOkHttpRequest(String address , okhttp3.Callback callback)
    {
        OkHttpClient client = new OkHttpClient() ;
        Request request = new Request.Builder()
                .url(address)
                .build() ;
        client.newCall(request).enqueue(callback);
    }

    /*
     通用的JSONOBJECT解析接口
     */
    public static <T> T parseJsonObjectWithGson(String jsonData , Class<T> type)
    {
        Gson gson = new Gson() ;
        T result = gson.fromJson(jsonData , type) ;
        return result ;
    }

    /*
      通用的JSONARRAY解析接口
     */
    public static <T>List<T> parseJsonArrayWithGson (String jsonData , Class<T[]> type)
    {
        Gson gson = new Gson() ;
        T[] result = gson.fromJson(jsonData , type) ;
        return(List<T>)  Arrays.asList(result) ;
    }
    /*
       判断网络是否可用
     */
    public static boolean JudgeNetState(Context mContext){
        if(mContext != null)
        {
            //获取ConnectivityManager对象
            Context context =  mContext ;
            ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE) ;
            //获取NetwORKInfo状态
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo() ;
            if (networkInfo!=null){

                return networkInfo.isAvailable() ;
            }
            return false ;
        }
        return false ;


    }

    /*
       获取网络连接的类型:wifi  mobile之类
     */
    public static int JudgeNetType(Context context){
        if (context != null){

            //虎丘手机的连接管理对象
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
            //获取NetInfo的信息
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo() ;
            //判断NetWorkInfo对象是否为null  并且判断状态是否为wifi状态
            if (networkInfo != null && networkInfo.isAvailable())
            {
                return  networkInfo.getType() ;
            }
            return -1 ;
        }
        return -1 ;
    }

}

2,多级城市分隔

其实也很简单,就是在XML中添加两个横向的LinearLayout,在其中分别添加TextView和View,用weight字段来分段。

在处理的时候需要定义三个ArrayAdapter ,listview ,list<String>来分别处理省会,市,区县的数据,而不是像第一行代码中通过一个ArrayAdapter,listView,list<String>就实现。

详情可以参见代码

3,定位处理


 /*
      根据传入的地址和类型从服务器上查询省市县的数据
     */
    private void queryFromServer(String address , final String type)
    {
//        Log.i(TAG , "QUERY FROM SERVICE") ;
        showProgressDialog();
        Utils.sendOkHttpRequest(address, new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        closeProgressDialog();
                        Toast.makeText(MainActivity.this , "加载失败",Toast.LENGTH_SHORT).show();
                    }
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                String responseText = response.body().string() ;
                boolean result = false ;
                if ("province".equals(type)){

                   // result = JsonUtils.handleProvinceResponse(responseText) ;
                    Log.i(TAG , "on main response") ;
                    currentProvince = LitePal.where("provinceName = ? " , LOCATION).find(Province.class).get(0) ;

                    String address = "http://guolin.tech/api/china/" + currentProvince.getId() ;
                    //从服务器查询数据
                    queryFromServer(address , "city");
                    return ;

                }else if ("city".equals(type)){
                    result = JsonUtils.handleCityResponse(responseText , currentProvince.getId()) ;

                    cityList = LitePal.where("provinceid = ? " , String.valueOf(currentProvince.getId())).find(City.class) ;
                    if (cityList.size() > 0 ) {
                        currentCity = cityList.get(0);
                        int provinceCode = currentProvince.getId() ;
                        int cityCode = currentCity.getCityCode() ;
                        String address = "http://guolin.tech/api/china/" + provinceCode +"/" +cityCode ;
                        //从服务器查询数据
                        queryFromServer(address , "county");
                        closeProgressDialog();
                        return ;

                    }else {
                        Toast.makeText(MainActivity.this , "获取位置出现错误" , Toast.LENGTH_SHORT).show();
                        closeProgressDialog();

                        return ;
                    }

                }else if ("county".equals(type)){
                    result = JsonUtils.handleCountyResponse(responseText , currentCity.getId()) ;
                    countyList = LitePal.where("cityid = ?" ,String.valueOf(currentCity.getId())).find(County.class) ;
                    if (countyList.size() > 0 )
                    {
                        weatherId = countyList.get(0).getWeatherId() ;
                        requestWeather(weatherId);
                        Log.i(TAG , "获取位置成功 " + LOCATION) ;
                    }
                }


            }
        });
    }

获取地理位置的部分很简单,完全用第一行代码中LOCATION部分的操作实现,但主要的部分是对获取到城市的处理

简单写一下部分坑:

(1)通过百度获取的省会,夹带了“省”,“市”这个字段,比如“重庆市”。但是服务器中反馈的数据没有“省”,“市”字段,substr来截取。

(2)从服务器中获取当前省中的所有市级城市,所以需要访问服务器,再把所有省加载到数据库,然后查询匹配当前省。依次重复,直到区县选取得到weatherId。最后根据weatherId再去访问服务器,得到城市的天气数据并且接收后完成布局。

这里最大的坑在于:

  // result = JsonUtils.handleProvinceResponse(responseText) ;

这行代码的意思是:向数据库添加从服务器接收到的省级城市列表。

为什么这里注释掉了这行代码?如果不注释掉,作者发现数据库Province中所有省级城市出现了两次。然后又只有

JsonUtils.handleProvinceResponse(responseText) ;

这段代码会向数据库添加省级城市。后来作者在ChooserAreaFragment中发现了:

在OnActivityCreated方法中有个:queryProvince();

queryProvince()中又有:

String address = "http://guolin.tech/api/china" ;
//从服务器查询数据
queryFromServer(address , "province");

。也就意味着这里也调用了handleProvinceResponse方法。并且先于Activity之中的方法调用,所以避免重复和冲突,注释掉了Activity中的方法。

三:源码地址:

https://github.com/547291213/CoolWeather


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值