admin 管理员组

文章数量: 887007

安卓学习专栏——实战项目酷欧天气(5)手动更新天气和切换城市

步骤

  • 系列文章
  • 前言
    • 实现效果
    • 项目结构
    • 1.实现下拉刷新
      • 1.1修改修改activity_weather.xml
      • 1.2修改WeatherActivity
      • 1.3目前的效果
    • 2.切换城市
      • 2.1修改WeatherActivity
      • 2.2修改title.xml
      • 2.2修改activity_weather.xml
      • 2.4修改WeatherActivity
      • 2.5修改ChooseAreaFragment
      • 2.6实现效果
    • 附录.参考资料
    • 下载资源
  • 总结

系列文章

提示:转到安卓学习专栏,观看更多内容!
点我直达–>安卓学习专栏
本项目注意包名前缀的修改,改成你自己的,我的包名是:
com.example.coolweather,不然会报错。


前言

本次主题:手动更新天气和切换城市
项目实战继承前面的文章:
安卓学习专栏——实战项目酷欧天气(4)给天气页面加上背景图片
传送门:



实现效果

手动更新天气

切换城市


项目结构

在com.coolweather.android包下几个包

  1. db包用于存放数据库模型相关的代码
  2. gson包用于存放GSON模型相关的代码
  3. service包用于存放服务相关的代码
  4. util包用于存放工具相 关的代码。


1.实现下拉刷新

目前选中了一个城市之后,没法查看其他城市的天气了,即使退出程序,因为我们设置了缓存的原因,下次进来的时候还会直接跳转到WeatherActivity这样明显是很不合理的,所以要能够手动更新天气和切换城市。

1.1修改修改activity_weather.xml

在ScrollView的外面又嵌套了一层SwipeRefreshLayout,这样ScrollView就自动拥有下拉刷新功能了。

在这个过程中,可能会飘红报错

参考博文添加依赖安卓报错android.support.v4.widget.SwipeRefreshLayout飘红
原来的“<ScrollView”外面添加代码

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayoutandroid:id="@+id/swipe_refresh"android:layout_width="match_parent"android:layout_height="match_parent"><ScrollView//省略···</ScrollView></androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

完整代码

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android=""android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/colorPrimary"><ImageViewandroid:id="@+id/bing_pic_img"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop" /><androidx.swiperefreshlayout.widget.SwipeRefreshLayoutandroid:id="@+id/swipe_refresh"android:layout_width="match_parent"android:layout_height="match_parent"><ScrollViewandroid:id="@+id/weather_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:scrollbars="none"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true"android:orientation="vertical"><include layout="@layout/title" /><include layout="@layout/now" /><include layout="@layout/forecast" /><include layout="@layout/aqi" /><include layout="@layout/suggestion" /></LinearLayout></ScrollView></androidx.swiperefreshlayout.widget.SwipeRefreshLayout></FrameLayout>

1.2修改WeatherActivity

修改WeatherActivity中的代码,加入更新天气的处理逻辑。
先在onCreate() 方法中获取到了SwipeRefreshLayout的实例,然后setColorSchemeResources()方法来设置下拉刷新进度条的颜色,这里我们就使用主题中的colorPrimary作为进度条的颜色了。

接着定义了一个mWeatherId 变量,用于记录城市的天气id,然后调用setOnRefreshListener() 方法来设置一个下拉刷新的监听器,当触发了下拉刷新操作的时候,就会回调这个监听器的onRefresh() 方法,我们在这里去调用requestWeather()方法请求天气信息就可以了。

当请求结束后,还需要调用SwipeRefreshLayout的setRefreshing() 方法并传入false ,用于表示刷新事件结束,并隐藏刷新进度条。

完整代码

package com.example.coolweather;import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;import com.bumptech.glide.Glide;
import com.example.coolweather.gson.Forecast;
import com.example.coolweather.gson.Weather;
import com.example.coolweather.util.HttpUtil;
import com.example.coolweather.util.Utility;import java.io.IOException;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;public class WeatherActivity extends AppCompatActivity {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;private ImageView bingPicImg;public SwipeRefreshLayout swipeRefresh;private String mWeatherId;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_weather);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);}// 初始化各控件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.idfort_text);carWashText = (TextView) findViewById(R.id.car_wash_text);sportText = (TextView) findViewById(R.id.sport_text);SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);String weatherString = prefs.getString("weather", null);swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);swipeRefresh.setColorSchemeResources(R.color.colorPrimary);if (weatherString != null) {// 有缓存时直接解析天气数据Weather weather = Utility.handleWeatherResponse(weatherString);mWeatherId = weather.basic.weatherId;showWeatherInfo(weather);} else {// 无缓存时去服务器查询天气mWeatherId = getIntent().getStringExtra("weather_id");weatherLayout.setVisibility(View.INVISIBLE);requestWeather(mWeatherId);}swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {@Overridepublic void onRefresh() {requestWeather(mWeatherId);}});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();}}/*** 根据天气id请求城市天气信息*/public void requestWeather(final String weatherId) {String weatherUrl = "/api/weather?cityid=" +weatherId + "&key=bc0418b57b2d4918819d3974ac1285d9";HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {final String responseText = response.body().string();final Weather weather = Utility.handleWeatherResponse(responseText);runOnUiThread(new Runnable() {@Overridepublic void run() {if (weather != null && "ok".equals(weather.status)) {SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();editor.putString("weather", responseText);editor.apply();mWeatherId = weather.basic.weatherId;showWeatherInfo(weather);} else {Toast.makeText(WeatherActivity.this, "获取天气信息失败",Toast.LENGTH_SHORT).show();}swipeRefresh.setRefreshing(false);}});}@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(WeatherActivity.this, "获取天气信息失败",Toast.LENGTH_SHORT).show();swipeRefresh.setRefreshing(false);}});}});}/*** 加载必应每日一图*/private void loadBingPic() {String requestBingPic = "/api/bing_pic";HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {final String bingPic = response.body().string();SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();editor.putString("bing_pic", bingPic);editor.apply();runOnUiThread(new Runnable() {@Overridepublic void run() {Glide.with(WeatherActivity.this).load(bingPic).into(bingPicImg);}});}@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();}});}/*** 处理并展示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 dateText = (TextView) view.findViewById(R.id.date_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);dateText.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.suggestionfort.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);}
}

1.3目前的效果


2.切换城市

当时为了方便后面的复用,特意选择了在碎片当中实现。现在只需要在天气界面的布局中引入这个碎片,就可以快速集成切换城市功能了

2.1修改WeatherActivity

修改WeatherActivity,滑动菜单功能。
将碎片放入到滑动菜单中,正常情况下它不占据主界面的任何空间,想要切换城市的时候只需要通过滑动的方式将菜单显示出来就可以了。

2.2修改title.xml

按照Material Design的建议,我们需要在头布局中加入一个切换城市的按钮,不然的话用户可能根本就不知道屏幕的左侧边缘是可以拖动的。

在res/drawable文件夹下添加图片ic_home.png


添加了一个Button作为切换城市的按钮,并且让它居左显示。图片来作为按钮的背景图

添加代码

    <Buttonandroid:id="@+id/nav_button"android:layout_width="30dp"android:layout_height="30dp"android:layout_marginLeft="10dp"android:layout_alignParentLeft="true"android:layout_centerVertical="true"android:background="@drawable/ic_home" />

完整代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android=""android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"><Buttonandroid:id="@+id/nav_button"android:layout_width="30dp"android:layout_height="30dp"android:layout_marginLeft="10dp"android:layout_alignParentLeft="true"android:layout_centerVertical="true"android:background="@drawable/ic_home" /><TextViewandroid:id="@+id/title_city"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textColor="#fff"android:textSize="20sp" /><TextViewandroid:id="@+id/title_update_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="10dp"android:textColor="#fff"android:textSize="16sp" />
</RelativeLayout>

2.2修改activity_weather.xml

修改activity_weather.xml布局来加入滑动菜单功能

在SwipeRefreshLayout的外面又嵌套了一层DrawerLayout。DrawerLayout中的第一个子控件用于作为主屏幕中显示的内容,第二个子控件用于作为滑动菜单中显示的内容,因此这里我们在第二个子控件的位置添加了用于遍历省市县数据的碎片。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android=""android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/colorPrimary"><ImageViewandroid:id="@+id/bing_pic_img"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop" /><androidx.drawerlayout.widget.DrawerLayoutandroid:id="@+id/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.swiperefreshlayout.widget.SwipeRefreshLayoutandroid:id="@+id/swipe_refresh"android:layout_width="match_parent"android:layout_height="match_parent"><ScrollViewandroid:id="@+id/weather_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:scrollbars="none"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:fitsSystemWindows="true"android:orientation="vertical"><include layout="@layout/title" /><include layout="@layout/now" /><include layout="@layout/forecast" /><include layout="@layout/aqi" /><include layout="@layout/suggestion" /></LinearLayout></ScrollView></androidx.swiperefreshlayout.widget.SwipeRefreshLayout><fragmentandroid:id="@+id/choose_area_fragment"android:name="com.example.coolweather.ChooseAreaFragment"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="start" /></androidx.drawerlayout.widget.DrawerLayout></FrameLayout>

2.4修改WeatherActivity

在WeatherActivity中加入滑动菜单的逻辑处理

在onCreate() 方法中获取到新增的DrawerLayout和Button的实例,然后在Button的点击事件中调用DrawerLayout的openDrawer() 方法来打开滑动菜单

package com.example.coolweather;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;import com.bumptech.glide.Glide;
import com.example.coolweather.gson.Forecast;
import com.example.coolweather.gson.Weather;
import com.example.coolweather.util.HttpUtil;
import com.example.coolweather.util.Utility;import java.io.IOException;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;public class WeatherActivity extends AppCompatActivity {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;private ImageView bingPicImg;public SwipeRefreshLayout swipeRefresh;private String mWeatherId;// 要在WeatherActivity中加入滑动菜单的逻辑处理public DrawerLayout drawerLayout;private Button navButton;@Overrideprotected 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.idfort_text);carWashText = (TextView) findViewById(R.id.car_wash_text);sportText = (TextView) findViewById(R.id.sport_text);SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);String weatherString = prefs.getString("weather", null);drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);navButton = (Button) findViewById(R.id.nav_button);swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);swipeRefresh.setColorSchemeResources(R.color.colorPrimary);if (weatherString != null) {// 有缓存时直接解析天气数据Weather weather = Utility.handleWeatherResponse(weatherString);mWeatherId = weather.basic.weatherId;showWeatherInfo(weather);} else {// 无缓存时去服务器查询天气mWeatherId = getIntent().getStringExtra("weather_id");weatherLayout.setVisibility(View.INVISIBLE);requestWeather(mWeatherId);}swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {@Overridepublic void onRefresh() {requestWeather(mWeatherId);}});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() {@Overridepublic void onClick(View v) {drawerLayout.openDrawer(GravityCompat.START);}});}/*** 根据天气id请求城市天气信息*/public void requestWeather(final String weatherId) {String weatherUrl = "/api/weather?cityid=" +weatherId + "&key=bc0418b57b2d4918819d3974ac1285d9";HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {final String responseText = response.body().string();final Weather weather = Utility.handleWeatherResponse(responseText);runOnUiThread(new Runnable() {@Overridepublic void run() {if (weather != null && "ok".equals(weather.status)) {SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();editor.putString("weather", responseText);editor.apply();mWeatherId = weather.basic.weatherId;showWeatherInfo(weather);} else {Toast.makeText(WeatherActivity.this, "获取天气信息失败",Toast.LENGTH_SHORT).show();}swipeRefresh.setRefreshing(false);}});}@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(WeatherActivity.this, "获取天气信息失败",Toast.LENGTH_SHORT).show();swipeRefresh.setRefreshing(false);}});}});}/*** 加载必应每日一图*/private void loadBingPic() {String requestBingPic = "/api/bing_pic";HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {final String bingPic = response.body().string();SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();editor.putString("bing_pic", bingPic);editor.apply();runOnUiThread(new Runnable() {@Overridepublic void run() {Glide.with(WeatherActivity.this).load(bingPic).into(bingPicImg);}});}@Overridepublic void onFailure(Call call, IOException e) {e.printStackTrace();}});}/*** 处理并展示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 dateText = (TextView) view.findViewById(R.id.date_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);dateText.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.suggestionfort.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);}
}

2.5修改ChooseAreaFragment

根据ChooseAreaFragment的不同状态来进行不同的逻辑处理。

instanceof 关键字可以用来判断一个对象是否属于某个类的实例。我们在碎片中调用getActivity()
方法,然后配合instanceof 关键字,就能轻松判断出该碎片是在MainActivity当中,还是WeatherActivity当中。如果是在MainActivity当中,那么处理逻辑不变。如果是在WeatherActivity当中,那么就关闭滑动菜单,显示下拉刷新进度条,然后请求新城市的天气信息。

package com.example.coolweather;import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import com.example.coolweather.R;
import com.example.coolweather.db.City;
import com.example.coolweather.db.County;
import com.example.coolweather.db.Province;
import com.example.coolweather.util.HttpUtil;
import com.example.coolweather.util.Utility;import org.litepal.crud.DataSupport;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import androidx.fragment.app.Fragment;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;public class ChooseAreaFragment extends Fragment {public static final int LEVEL_PROVINCE = 0;public static final int LEVEL_CITY = 1;public static final int LEVEL_COUNTY = 2;private ProgressDialog progressDialog;private TextView titleText;private Button backButton;private ListView listView;private ArrayAdapter<String> adapter;private List<String> dataList = new ArrayList<>();/*** 省列表*/private List<Province> provinceList;/*** 市列表*/private List<City> cityList;/*** 县列表*/private List<County> countyList;/*** 选中的省份*/private Province selectedProvince;/*** 选中的城市*/private City selectedCity;/*** 当前选中的级别*/private int currentLevel;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View view = inflater.inflate(R.layout.choose_area, container, false);titleText = (TextView) view.findViewById(R.id.title_text);backButton = (Button) view.findViewById(R.id.back_button);listView = (ListView) view.findViewById(R.id.list_view);adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, dataList);listView.setAdapter(adapter);return view;}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, 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.swipeRefresh.setRefreshing(true);activity.requestWeather(weatherId);}}}});backButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (currentLevel == LEVEL_COUNTY) {queryCities();} else if (currentLevel == LEVEL_CITY) {queryProvinces();}}});queryProvinces();}/*** 查询全国所有的省,优先从数据库查询,如果没有查询到再去服务器上查询*/private void queryProvinces() {titleText.setText("中国");backButton.setVisibility(View.GONE);provinceList = DataSupport.findAll(Province.class);if (provinceList.size() > 0) {dataList.clear();for (Province province : provinceList) {dataList.add(province.getProvinceName());}adapter.notifyDataSetChanged();listView.setSelection(0);currentLevel = LEVEL_PROVINCE;} else {String address = "/api/china";queryFromServer(address, "province");}}/*** 查询选中省内所有的市,优先从数据库查询,如果没有查询到再去服务器上查询*/private void queryCities() {titleText.setText(selectedProvince.getProvinceName());backButton.setVisibility(View.VISIBLE);cityList = DataSupport.where("provinceid = ?", String.valueOf(selectedProvince.getId())).find(City.class);if (cityList.size() > 0) {dataList.clear();for (City city : cityList) {dataList.add(city.getCityName());}adapter.notifyDataSetChanged();listView.setSelection(0);currentLevel = LEVEL_CITY;} else {int provinceCode = selectedProvince.getProvinceCode();String address = "/api/china/" + provinceCode;queryFromServer(address, "city");}}/*** 查询选中市内所有的县,优先从数据库查询,如果没有查询到再去服务器上查询*/private void queryCounties() {titleText.setText(selectedCity.getCityName());backButton.setVisibility(View.VISIBLE);countyList = DataSupport.where("cityid = ?", String.valueOf(selectedCity.getId())).find(County.class);if (countyList.size() > 0) {dataList.clear();for (County county : countyList) {dataList.add(county.getCountyName());}adapter.notifyDataSetChanged();listView.setSelection(0);currentLevel = LEVEL_COUNTY;} else {int provinceCode = selectedProvince.getProvinceCode();int cityCode = selectedCity.getCityCode();String address = "/api/china/" + provinceCode + "/" +cityCode;queryFromServer(address, "county");}}/*** 根据传入的地址和类型从服务器上查询省市县数据*/private void queryFromServer(String address, final String type) {showProgressDialog();HttpUtil.sendOkHttpRequest(address, new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {String responseText = response.body().string();boolean result = false;if ("province".equals(type)) {result = Utility.handleProvinceResponse(responseText);} else if ("city".equals(type)) {result = Utility.handleCityResponse(responseText,selectedProvince.getId());} else if ("county".equals(type)) {result = Utility.handleCountyResponse(responseText,selectedCity.getId());}if (result) {getActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {closeProgressDialog();if ("province".equals(type)) {queryProvinces();} else if ("city".equals(type)) {queryCities();} else if ("county".equals(type)) {queryCounties();}}});}}@Overridepublic void onFailure(Call call, IOException e) {
// 通过runOnUiThread()方法回到主线程处理逻辑getActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {closeProgressDialog();Toast.makeText(getContext(), "加载失败", Toast.LENGTH_SHORT).show();}});}});}/*** 显示进度对话框*/private void showProgressDialog() {if (progressDialog == null) {progressDialog = new ProgressDialog(getActivity());progressDialog.setMessage("正在加载...");progressDialog.setCanceledOnTouchOutside(false);}progressDialog.show();}/*** 关闭进度对话框*/private void closeProgressDialog() {if (progressDialog != null) {progressDialog.dismiss();}}
}

2.6实现效果


附录.参考资料

《第一行代码》14.6 手动更新天气和切换城市


下载资源

gitee地址


安卓学习者实战项目酷欧天气(5)手动更新天气和切换城市示例


总结

大家喜欢的话,给个👍,点个关注!继续跟大家分享敲代码过程中遇到的问题!


本文标签: 安卓学习专栏实战项目酷欧天气(5)手动更新天气和切换城市