天气预报APP(2)

摘要:
使用Wind weather API查询天气信息。此API获得的天气信息采用JSON格式。然后是城市信息基本:{“基本”:{”城市“:”秦皇岛“,”id“:”CN101091101“,”更新“:”loc“:”2017-09-1014:46“,}},对应于应为映射定义的java类:publicclassBasic{@SerializedNamepublicStringcityName;@SerializedName publicStringweatherId;publicUpdateupdate;publicclassUpdate{@SerializedNamepublicStringupdateTime;}如果获得的数据变量名称设置了您的不喜欢,然后是天气预报每日_预报:“daily_forecast”:[{“cond”:{“txt_d”:“小雨”,},“date”:“2017-09-10”,“tmp”:“max”:“26”,“min”:“17”},},{“second”:{“txd_d”:”晴朗“,}”日期:“2017-05-11”,“temp”:”最大值:“25”,“min”:“12”}12”,“tmp”:{“max”:“26”,“min”:“15”},}],“[]”包括一个数组,即,当创建地图时,预测还应创建一个数组。

之前实现了能够罗列可以罗列出全国所有的省、市、县,然后就是查询全国任意城市的天气信息。查询天气信息使用的是和风天气的api,这个api获得的天气信息是JSON格式的。

使用GSON库解析JSON数据的第一步要先定义用于映照的类。

我对官方实例做了一下删减,然后可以看到这次我想要展示在这次这个项目中的信息:

天气预报APP(2)第1张天气预报APP(2)第2张
{
    "HeWeather5": [
        {
            "aqi": {
                "city": {
                    "aqi": "46", 
                    "pm25": "26", 
                }
            }, 
            "basic": {
                "city": "秦皇岛", 
                "id": "CN101091101", 
                "update": {
                    "loc": "2017-09-10 14:46", 
                }
            }, 
            "daily_forecast": [
                {
                    "cond": {

                        "txt_d": "小雨", 
                    }, 
                    "date": "2017-09-10",  
                    "tmp": {
                        "max": "26", 
                        "min": "17"
                    }, 
                }, 
                {
                    
                    "cond": {
                        "txt_d": "晴",   
                    }, 
                    "date": "2017-09-11", , 
                    "tmp": {
                        "max": "25", 
                        "min": "12"
                    },
                }, 
                {
                    "cond": {
                        "txt_d": "晴", 
                    }, 
                    "date": "2017-09-12", 
                    "tmp": {
                        "max": "26", 
                        "min": "15"
                    }, 

                }
            ], 
            "status": "ok", 
            "suggestion": {

                "comf": {
                    "brf": "较舒适", 
                    "txt": "白天有雨,从而使空气湿度加大,会使人们感觉有点儿闷热,但早晚的天气很凉爽、舒适。"
                }, 
                "cw": {
                    "brf": "不宜", 
                    "txt": "不宜洗车,未来24小时内有雨,如果在此期间洗车,雨水和路上的泥水可能会再次弄脏您的爱车。"
                }, 
                
                "sport": {
                    "brf": "较不宜", 
                    "txt": "有降水,推荐您在室内进行健身休闲运动;若坚持户外运动,须注意携带雨具并注意避雨防滑。"
                }, 
            }
        }
    ]
}
天气信息总

其中天气情况AQI:

  {
      "aqi": {
      "city": {
          "aqi": "46", 
          "pm25": "26", 
                }
            }
  }

定义的AQI类代码为:

public class AQI {

    public AQIcity city;

    public class AQIcity{

        public String aqi;

        public String pm25;
    }
}

 这里要说的就是“{}”包括一个类要用一个类去映照。

然后是城市的信息Basic:

  { 
      "basic": {
          "city": "秦皇岛", 
          "id": "CN101091101", 
          "update": {
              "loc": "2017-09-10 14:46", 
                 }
            }, 

 对应应该定义映照的java类:

public class Basic {

    @SerializedName("city")
    public String cityName;

    @SerializedName("id")
    public String weatherId;

    public Update update;

    public class Update{

        @SerializedName("loc")
        public String updateTime;
    }
}

如果获得的数据的变量名设置自己不喜欢,可以用@SerializedName("loc")去映照,

然后是天气预测情况daily_forecast:

"daily_forecast": [
                {
                    "cond": {

                        "txt_d": "小雨", 
                    }, 
                    "date": "2017-09-10",  
                    "tmp": {
                        "max": "26", 
                        "min": "17"
                    }, 
                }, 
                {
                    
                    "cond": {
                        "txt_d": "晴",   
                    }, 
                    "date": "2017-09-11", , 
                    "tmp": {
                        "max": "25", 
                        "min": "12"
                    },
                }, 
                {
                    "cond": {
                        "txt_d": "晴", 
                    }, 
                    "date": "2017-09-12", 
                    "tmp": {
                        "max": "26", 
                        "min": "15"
                    }, 

                }
            ], 

 用“[]”包括的是数组,也就是说这个daily_forecast在建立映照的时候,应该也建立一个数组。不过这里先定义数组的成员:

public class Forecast {

    public String date;

    @SerializedName("tmp")
    public Temperature temperature;

    @SerializedName("cond")
    public More more;

    public class Temperature{

        public String max;

        public String min;
    }

    public class More{

        @SerializedName("txt_d")
        public String info;

    }
}

 然后是其他就没什么特殊的了:

天气预报APP(2)第3张天气预报APP(2)第4张
public class Now {

    @SerializedName("tmp")
    public String temperature;

    @SerializedName("cond")
    public More more;

    public class More{

        @SerializedName("txt")
        public String info;
    }

}
public class Suggestion {

    @SerializedName("comf")
    public Comfort comfort;

    @SerializedName("cw")
    public CarWash carWash;

    public Sport sport;

    public class Comfort {

        @SerializedName("txt")
        public String info;

    }

    public class CarWash {

        @SerializedName("txt")
        public String info;

    }

    public class Sport {

        @SerializedName("txt")
        public String info;

    }
}
其他信息

最后要合在一起,因为对于整个天气信息来说,上面的都是用“{}”包括的一个类,所以:

public class Weather {

    public String status;

    public Basic basic;

    public AQI aqi;

    public Now now;

    public Suggestion suggestion;

    @SerializedName("daily_forecast")
    public List<Forecast> forecastList;
}

对于[]数组就是在这里定义。

然后就是具体的解析代码:

public class Utility {
    /**
     * 将返回的JSON数据解析成Weather类
     */
    public static Weather handleWeatherResponse(String response){
        try {
            JSONObject jsonObject = new JSONObject(response);
            JSONArray jsonArray = jsonObject.getJSONArray("HeWeather");
            String weatherContent = jsonArray.getJSONObject(0).toString();
            return new Gson().fromJson(weatherContent,Weather.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

这样就解析完毕了。

然后是界面的布局代码编写了,

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary">

    <ImageView
        android:id="@+id/bing_pic_img"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>

    <ScrollView
        android:id="@+id/weather_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none"
        android:overScrollMode="never">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <include layout="@layout/title"/>

        <include layout="@layout/now"/>

        <include layout="@layout/forecast"/>

        <include layout="@layout/aqi"/>

        <include layout="@layout/suggestion"/>
    </LinearLayout>
    </ScrollView>

</RelativeLayout>

这是整个活动布局,其中正文部分使用的是子项布局,因为内容比较多,这样显得条理一些。

layout/title:

天气预报APP(2)第5张天气预报APP(2)第6张
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize">

    <Button
        android: 
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginLeft="15dp"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:background="@drawable/ic_home"/>

    <TextView
        android: 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textColor="#fff"
        android:textSize="20sp"/>

    <TextView
        android: 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:textColor="#fff"
        android:textSize="16sp"/>

</RelativeLayout>
title

layout/now:

天气预报APP(2)第7张天气预报APP(2)第8张
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp">

    <TextView
        android:id="@+id/degree_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:textColor="#fff"
        android:textSize="60sp" />

    <TextView
        android:id="@+id/weather_info_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:textAlignment="textEnd"
        android:textColor="#fff"
        android:textSize="20sp" />

</LinearLayout>
now

layout/forecast:

天气预报APP(2)第9张天气预报APP(2)第10张
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="15dp"
    android:background="#8000">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="预报"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="15dp"
        android:textColor="#fff"
        android:textSize="20sp"/>

    <LinearLayout
        android:id="@+id/forecast_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    </LinearLayout>
</LinearLayout>
forecast

layout/forecast_item:

天气预报APP(2)第11张天气预报APP(2)第12张
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="15dp">

    <TextView
        android:id="@+id/data_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_weight="2"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/info_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/max_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="1"
        android:gravity="right"
        android:textColor="#fff"/>

    <TextView
        android:id="@+id/min_text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="1"
        android:gravity="right"
        android:textColor="#fff" />
</LinearLayout>
forcast_item

layout/aqi:

天气预报APP(2)第13张天气预报APP(2)第14张
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="15dp"
    android:background="#8000">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="空气质量"
        android:textColor="#fff"
        android:textSize="20sp"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="15dp">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_centerVertical="true">

                <TextView
                    android:id="@+id/aqi_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:textColor="#fff"
                    android:textSize="40sp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:text="AQI指数"
                    android:textColor="#fff"/>

            </LinearLayout>
        </RelativeLayout>

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:layout_centerVertical="true">

                <TextView
                    android:id="@+id/pm25_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:textColor="#fff"
                    android:textSize="40sp"/>

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:text="PM2.5指数"
                    android:textColor="#fff"/>

            </LinearLayout>

        </RelativeLayout>

    </LinearLayout>

</LinearLayout>
aqi

layout/suggestion:

天气预报APP(2)第15张天气预报APP(2)第16张
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="15dp"
    android:background="#8000">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="生活建议"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="15dp"
        android:textColor="#fff"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/comfort_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#fff"
        android:layout_margin="15dp"/>

    <TextView
        android:id="@+id/car_wash_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#fff"
        android:layout_margin="15dp"/>

    <TextView
        android:id="@+id/sport_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#fff"
        android:layout_margin="15dp" />
</LinearLayout>
suggestion

然后是活动的java代码:

天气预报APP(2)第17张天气预报APP(2)第18张
public class WeatherActivity extends AppCompatActivity {

    public SwipeRefreshLayout swipeRefreshLayout;

    private ImageView bingPicImg;

    private ScrollView weatherLayout;

    private TextView titleCity;

    private TextView titleUpdateTime;

    private TextView degreeText;

    private TextView weatherInfoText;

    private LinearLayout forecastLayout;

    private TextView aqiText;

    private TextView pm25Text;

    private TextView comfortText;

    private TextView carWashText;

    private TextView sportText;

    public DrawerLayout drawerLayout;

    public Button navbutton;

    String weatherId;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //使状态栏和背景图融合在一块
        if(Build.VERSION.SDK_INT >= 21){
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);//设置为全屏模式
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
        setContentView(R.layout.activity_weather);

        //初始化各个控件
        weatherLayout = (ScrollView) findViewById(R.id.weather_layout);
        titleCity = (TextView) findViewById(R.id.title_city);
        titleUpdateTime = (TextView) findViewById(R.id.title_update_time);
        degreeText = (TextView) findViewById(R.id.degree_text);
        weatherInfoText = (TextView) findViewById(R.id.weather_info_text);
        forecastLayout = (LinearLayout) findViewById(R.id.forecast_layout);
        aqiText = (TextView) findViewById(R.id.aqi_text);
        pm25Text = (TextView) findViewById(R.id.pm25_text);
        comfortText = (TextView) findViewById(R.id.comfort_text);
        carWashText = (TextView) findViewById(R.id.car_wash_text);
        sportText = (TextView) findViewById(R.id.sport_text);
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        navbutton = (Button) findViewById(R.id.nav_button);

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        String weatherString = prefs.getString("weather",null);
        if(weatherString != null){
            //有缓存时直接解析天气数据
            Weather weather = Utility.handleWeatherResponse(weatherString);
            weatherId = weather.basic.weatherId;
            showWeatherInfo(weather);
        }else {
            //无缓存时直接去服务器查询天气
            weatherId = getIntent().getStringExtra("weather_id");
            weatherLayout.setVisibility(View.INVISIBLE);
            requestWeather(weatherId);
        }

        //向下滑动刷新天气
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
        swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent);
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
            @Override
            public void onRefresh() {
                requestWeather(weatherId);
            }
        });

        //背景图片
        bingPicImg = (ImageView) findViewById(R.id.bing_pic_img);
        String bingpic = prefs.getString("bing_pic",null);
        if(bingpic != null){
            Glide.with(this).load(bingpic).into(bingPicImg);
        }else {
            loadBingPic();
        }

        //顶部按钮打开侧边栏
        navbutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                drawerLayout.openDrawer(GravityCompat.START);
            }
        });

    }

    /**
     * 根据天气ID请求城市天气信息
     */
    public void requestWeather(final String weatherId){
        String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId +"&key=32d1c829ed7d483086f4f5b4d5947cef";
        HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseText = response.body().string();
                final Weather weather = Utility.handleWeatherResponse(responseText);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(weather != null && "ok".equals(weather.status)){
                            SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();
                            editor.putString("weather", responseText);
                            editor.apply();
                            showWeatherInfo(weather);
                            Toast.makeText(WeatherActivity.this, "天气获取成功", Toast.LENGTH_SHORT).show();
                        }else {
                            Toast.makeText(WeatherActivity.this, "天气获取失败", Toast.LENGTH_SHORT).show();
                        }
                        swipeRefreshLayout.setRefreshing(false);//传入false表示刷新事件结束
                    }
                });
            }

            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(WeatherActivity.this, "天气获取失败", Toast.LENGTH_SHORT).show();
                        swipeRefreshLayout.setRefreshing(false);//传入false表示刷新事件结束
                    }
                });
            }

        });
    }

    /**
     * 处理展示Weather实体类中的数据
     */
    private void showWeatherInfo(Weather weather){
        String cityName = weather.basic.cityName;
        String updateTime = weather.basic.update.updateTime.split(" ")[1];
        String degree = weather.now.temperature + "℃";
        String weatherInfo = weather.now.more.info;
        titleCity.setText(cityName);
        titleUpdateTime.setText(updateTime);
        degreeText.setText(degree);
        weatherInfoText.setText(weatherInfo);
        forecastLayout.removeAllViews();
        for(Forecast forecast: weather.forecastList){
            View view = LayoutInflater.from(this).inflate(R.layout.forecast_item, forecastLayout, false);
            TextView dataText = (TextView) view.findViewById(R.id.data_text);
            TextView infoText = (TextView) view.findViewById(R.id.info_text);
            TextView maxText = (TextView) view.findViewById(R.id.max_text);
            TextView minText = (TextView) view.findViewById(R.id.min_text);
            dataText.setText(forecast.date);
            infoText.setText(forecast.more.info);
            maxText.setText(forecast.temperature.max);
            minText.setText(forecast.temperature.min);
            forecastLayout.addView(view);
        }
        if(weather.aqi != null){
            aqiText.setText(weather.aqi.city.aqi);
            pm25Text.setText(weather.aqi.city.pm25);
        }

        String comfort = "舒适度:" + weather.suggestion.comfort.info;
        String carWash = "洗车指数:" + weather.suggestion.carWash.info;
        String sport = "运动建议:" + weather.suggestion.sport.info;

        comfortText.setText(comfort);
        carWashText.setText(carWash);
        sportText.setText(sport);
        weatherLayout.setVisibility(View.VISIBLE);

    }

    private void loadBingPic(){
            String Url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US";
            HttpUtil.sendOkHttpRequest(Url, new Callback() {
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    String responseText = response.body().string();
                    final Images images = Utility.handleImagesrResponse(responseText);
                    final String url = "http://s.cn.bing.net"+ images.url;
                    try {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Glide.with(WeatherActivity.this).load(url).into(bingPicImg);
                            }
                        });
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(WeatherActivity.this, "图片获取失败", Toast.LENGTH_SHORT).show();
                        }
                    });
                }

            });
        }
}
WeatherActivity

这个活动实现的功能大概有:

  1、向下滑动刷新:  

布局代码这样编写。

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ScrollView...>

    </android.support.v4.widget.SwipeRefreshLayout>

  活动中的JAVA代码:

  public SwipeRefreshLayout swipeRefreshLayout;
 //向下滑动刷新天气
  swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
  swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent);
  swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener(){
   @Override
    public void onRefresh() {
      requestWeather(weatherId);//从服务器获取天气信息
      }
     });
    2、从必应api获得的每天一刷新的图片,使用Glide设置图片。  
      必应的图片api是http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US,获取到的数据也是JSON格式的,不过Glide设置图片只需要得到图片的uri即可所以,映射的类这样定义:
public class Images {

    public String url;
}

  然后解析java代码:

public class Utility {

    public static Images handleImagesrResponse(String response){
        try {
            JSONObject jsonObject = new JSONObject(response);
            JSONArray jsonArray = jsonObject.getJSONArray("images");
            String weatherContent = jsonArray.getJSONObject(0).toString();
            return new Gson().fromJson(weatherContent,Images.class);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

  活动中调用的代码:

    private void loadBingPic(){
            String Url = "http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=en-US";
            HttpUtil.sendOkHttpRequest(Url, new Callback() {
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    String responseText = response.body().string();
                    final Images images = Utility.handleImagesrResponse(responseText);
                    final String url = "http://s.cn.bing.net"+ images.url;
                    try {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Glide.with(WeatherActivity.this).load(url).into(bingPicImg);
                            }
                        });
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(WeatherActivity.this, "图片获取失败", Toast.LENGTH_SHORT).show();
                        }
                    });
                }

            });
        }

  3、侧边栏切换城市:

  布局:

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v4.widget.SwipeRefreshLayout...>

    <fragment
            android:id="@+id/choose_area_fragment"
            android:name="xbt.exp20.ChooseAreaFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start" />
    </android.support.v4.widget.DrawerLayout>

  之前的省市县列表作为侧边栏,

  然后有一个按钮打开侧边栏:

  //顶部按钮打开侧边栏
  navbutton.setOnClickListener(new View.OnClickListener() {
     @Override
       public void onClick(View view) {
          drawerLayout.openDrawer(GravityCompat.START);
      }
  });

  这里打开侧边栏选中某个城市之后要自动把侧边栏关闭,以及刷新天气信息,所以需要修改碎片的列表点击响应:

        //列表的点击事件响应
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                //如果当前级别是省,那点击选取的就是某个省,而想要查询的是选中省有那些城市,市同理 ,想要查询这个城市有那些县
                if(currentLevel == LEVEL_PROVINCE){
                    selectedProvince = provinceList.get(position);
                    queryCities();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询
                }else if(currentLevel == LEVEL_CITY){
                    selectedCity = cityList.get(position);
                    queryCounties();//查询全国所有的省,优先从数据库查询,如果没有查到再去服务器上查询
                }else if(currentLevel == LEVEL_COUNTY){
                    String weatherId = countyList.get(position).getWeatherId();
                    if(getActivity() instanceof MainActivity) {
                        Intent intent = new Intent(getActivity(), WeatherActivity.class);
                        intent.putExtra("weather_id", weatherId);
                        startActivity(intent);
                        getActivity().finish();
                    }else if(getActivity() instanceof WeatherActivity){
                        WeatherActivity activity = (WeatherActivity) getActivity();
                        activity.drawerLayout.closeDrawers();
                        activity.swipeRefreshLayout.setRefreshing(true);
                        activity.requestWeather(weatherId);
                    }
                }
            }
        });

使用instanceof关键字判断一个对象是否属于某个类的实例,判断当时碎片处于那个活动中,并设置相应的响应。

基础的根据城市ID获取天气信息,并展示在活动上,以及将获取过的天气缓存下来就不在赘述了

项目截图:

天气预报APP(2)第19张天气预报APP(2)第20张

免责声明:文章转载自《天气预报APP(2)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【模板】割点(洛谷P3388)SnpHub搭建(二) | 数据预处理与样本描述文件准备下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

elasticsearch 高级搜索示例 es7.0

1 基础数据 1.1 创建索引 PUT mytest { "mappings": { "properties": { "title": { "type": "text", "fields": { "keyword": { "type": "text",...

Android进入一个新页面,EditText失去焦点并禁止弹出键盘

android在进入一个新页面后,edittext会自动获取焦点并弹出软键盘,这样并不符合用户操作习惯。 在其父控件下,添加如下的属性,就可以完美解决,使其进入页面后不主动获取焦点,并且不弹出软键盘: android:focusable="true"   android:focusableInTouchMode="true" 代码如下: 1 <S...

neo4j查询语句

一:查询 比较操作: = <> < > <= >= 布尔操作: AND OR NOT XOR 1、把节点的前两个字为"提示"的节点去除"提示": match(l) where l.name=~'提示.*' with collect(l.name) as result unwind result as row ret...

mac everything的替代品——fzf使用,速度还是很快的!!!

fzf模糊搜索神器的安装和使用 fzf是一个通用的命令行模糊查找器, 通过输入模糊的关键词就可以定位文件或文件夹。结合其他工具(比如rg)可以完成非常多的工作,在工作中可以大幅提高你的工作效率。 fzf可以用于文件、命令历史记录、进程、主机名、书签、git提交等。 1. fzf使用 1.1 安装 Using Homebrew You can use...

android自定义控件概述

引子:   android SDK中会提供一些基础的控件以供开发。但是大多数情况下,这些基础的控件无法满足业务需求。本文主要说明自定义控件的分类,以及提供示例代码。   本文只做入门级选手阅读,或者 加深印象 或 温故而知新,大佬大神敬请绕道。 android控件的3种方式: 1)派生控件 : 从SDK已有的控件为基础,改变其部分特征,形成符合需求的自定...

Cygwin apt-cyg ”MD5 sum did not match”

直接编辑apt-cyg 文件,找到md5sum,替换修改成sha512sum。 # check the md5 digest=`cat "desc" | awk '/^install: / { print $4; exit }'` digactual=`sha512sum $file | awk '{print $1}'` if !...