赞
踩
第一步,注册和风天气控制台 | 和风天气,申请key
08f828b5a3ec4905a29156bf5f29136f
查看郭林的后台天气pai接口
- /**
- * Description
- * <p>
- * id是每个实体该有的字段
- * provinceName记录省的名字
- * provinceCode记录省的代号
- * @author qricis on 2020/9/3 14:47
- * @version 1.0.0
- */
- public class Province extends DataSupport {
-
- private int id;
-
- private String provinceName;
-
- private int provinceCode;
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getProvinceName() {
- return provinceName;
- }
-
- public void setProvinceName(String provinceName) {
- this.provinceName = provinceName;
- }
-
- public int getProvinceCode() {
- return provinceCode;
- }
-
- public void setProvinceCode(int provinceCode) {
- this.provinceCode = provinceCode;
- }
- }
-
- /**
- * Description
- * <p>
- * id是每个实体类都应该有的字段
- * cityName记录市的名字
- * cityCode记录市的代码
- * provinceId记录当前市所属省的id值
- * @author qricis on 2020/9/3 14:47
- * @version 1.0.0
- */
- public class City extends DataSupport {
-
- private int id;
-
- private String cityName;
-
- private int citycode;
-
- private int provinceId;
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getCityName() {
- return cityName;
- }
-
- public void setCityName(String cityName) {
- this.cityName = cityName;
- }
-
- public int getCitycode() {
- return citycode;
- }
-
- public void setCitycode(int citycode) {
- this.citycode = citycode;
- }
-
- public int getProvinceId() {
- return provinceId;
- }
-
- public void setProvinceId(int provinceId) {
- this.provinceId = provinceId;
- }
- }
-
- /**
- * Description
- * <p>
- * id是每个实体类都应该有的字段
- * countyName记录县的名字
- * weatherId记录县的天气代码
- * cityId记录当前县所属市的id
- * @author qricis on 2020/9/3 14:47
- * @version 1.0.0
- */
- public class County extends DataSupport {
-
- private int id;
-
- private String countyName;
-
- private int countyCode;
-
- private int cityId;
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getCountyName() {
- return countyName;
- }
-
- public void setCountyName(String countyName) {
- this.countyName = countyName;
- }
-
- public int getCountyCode() {
- return countyCode;
- }
-
- public void setCountyCode(int countyCode) {
- this.countyCode = countyCode;
- }
-
- public int getCityId() {
- return cityId;
- }
-
- public void setCityId(int cityId) {
- this.cityId = cityId;
- }
- }
- <litepal>
-
- <!-- 设置数据库名为cool_weather,数据库版本1,并将三个实体类映射到列表当中 -->
- <dbname value="cool_weather" />
-
- <version value="1" />
-
- <list>
- <mapping class="com.coolweather.android.db.Province" />
- <mapping class="com.coolweather.android.db.City" />
- <mapping class="com.coolweather.android.db.County" />
- </list>
-
- </litepal>
- /**
- * Description
- * <p>
- * 与服务器进行交互
- * @author qricis on 2020/9/3 15:46
- * @version 1.0.0
- */
- public class HttpUtil {
-
- 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);
- }
-
- }
- /**
- * Description
- * <p>
- * 解析服务器返回的数据
- * @author qricis on 2020/9/3 15:53
- * @version 1.0.0
- */
- public class Utility {
-
- /**
- * 解析和处理服务器返回的省级数据
- * */
- public static boolean handleProvinceResponse(String response) {
- if (!TextUtils.isEmpty(response)) {
- try {
- JSONArray allProvinces = new JSONArray(response);
- for (int i = 0; i < allProvinces.length(); i++) {
- JSONObject provinceObject = allProvinces.getJSONObject(i);
- Province province = new Province();
- province.setProvinceName(provinceObject.getString("name"));
- province.setProvinceCode(provinceObject.getInt("id"));
- province.save();
- }
- return true;
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- return false;
- }
-
- /**
- * 解析和处理服务器返回的市级数据
- * */
- public static boolean handleCityResponse(String response, int provinceId) {
- if (!TextUtils.isEmpty(response)) {
- try {
- JSONArray allCities = new JSONArray(response);
- for (int i = 0; i < allCities.length(); i++) {
- JSONObject cityObject = allCities.getJSONObject(i);
- City city = new City();
- city.setCityName(cityObject.getString("name"));
- city.setCitycode(cityObject.getInt("id"));
- city.setProvinceId(provinceId);
- city.save();
- }
- return true;
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- return false;
- }
-
- /**
- * 解析和处理服务器返回的县级数据
- * */
- public static boolean handleCountyResponse(String response, int cityId) {
- if (!TextUtils.isEmpty(response)) {
- try {
- JSONArray allCounties = new JSONArray(response);
- for (int i = 0; i < allCounties.length(); i++) {
- JSONObject countyObject = allCounties.getJSONObject(i);
- County county = new County();
- county.setCountyName(countyObject.getString("name"));
- county.setCountyCode(countyObject.getInt("id"));
- county.setCityId(cityId);
- county.save();
- }
- return true;
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- return false;
- }
-
- }
- <!-- 定义一个展示所有省市县的碎片 -->
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:background="#fff">
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary">
-
- <TextView
- android:id="@+id/area_tv_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:textColor="#fff"
- android:textSize="20sp"/>
-
- <Button
- android:id="@+id/area_btn_back"
- android:layout_width="25dp"
- android:layout_height="25dp"
- android:layout_marginLeft="10dp"
- android:layout_marginStart="10dp"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_centerVertical="true"
- android:background="@drawable/area_btn_back"
- />
- </RelativeLayout>
-
- <ListView
- android:id="@+id/area_list_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </LinearLayout>
- /**
- * Description
- * <p>
- * 用于遍历省市县数据的碎片ChooseAreaFragment
- * @author qricis on 2020/9/3 17:25
- * @version 1.0.0
- */
- 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 mProgressDialog;
-
- private TextView mTitleText;
-
- private Button mBackButton;
-
- private ListView mListView;
-
- private ArrayAdapter<String> mStringArrayAdapter;
-
- private List<String> mDataList = new ArrayList<>();
-
- /**
- * 省列表
- * */
- private List<Province> mProvinceList;
-
- /**
- * 市列表
- * */
- private List<City> mCityList;
-
- /**
- * 县列表
- * */
- private List<County> mCountyList;
-
- /**
- * 选中的省份
- * */
- private Province mSelectedProvince;
-
- /**
- * 选中的城市
- * */
- private City mSelectedCity;
-
- /**
- * 当前选中的级别
- * */
- private int mCurrentLevel;
-
- /**
- * 获取控件实例,初始化mStringArrayAdapter,并将之设置为ListView的适配器
- * */
- @Nullable
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.choose_area,container,false);
- mTitleText = view.findViewById(R.id.area_tv_title);
- mBackButton = view.findViewById(R.id.area_btn_back);
- mListView = view.findViewById(R.id.area_list_view);
- mStringArrayAdapter = new ArrayAdapter<>(getContext(),android.R.layout.simple_list_item_1,mDataList);
- mListView.setAdapter(mStringArrayAdapter);
- return view;
- }
-
- /**
- * 给ListView和Button设置点击事件
- * */
- @Override
- public void onActivityCreated(@Nullable Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
- if (mCurrentLevel == LEVEL_PROVINCE) {
- mSelectedProvince = mProvinceList.get(position);
- queryCities();
- } else if (mCurrentLevel == LEVEL_CITY) {
- mSelectedCity = mCityList.get(position);
- queryCounties();
- }
- }
- });
- mBackButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mCurrentLevel == LEVEL_COUNTY) {
- queryCities();
- } else if (mCurrentLevel == LEVEL_CITY) {
- queryProvinces();
- }
- }
- });
- queryProvinces();
- }
-
- /**
- * 查询全国所有的省,优先从数据库查询,如果没有查询到再去服务器查询
- * */
- private void queryProvinces() {
- mTitleText.setText("中国");
- mBackButton.setVisibility(View.GONE);
- mProvinceList = DataSupport.findAll(Province.class);
- if (mProvinceList.size() > 0) {
- mDataList.clear();
- for (Province province : mProvinceList) {
- mDataList.add(province.getProvinceName());
- }
- mStringArrayAdapter.notifyDataSetChanged();
- mListView.setSelection(0);
- mCurrentLevel = LEVEL_PROVINCE;
- } else {
- String address = "http://guolin.tech/api/china";
- queryFromServer(address,"province");
- }
- }
-
- /**
- * 查询全国所有的市,优先从数据库查询,如果没有查询到再去服务器查询
- * */
- private void queryCities() {
- mTitleText.setText(mSelectedProvince.getProvinceName());
- mBackButton.setVisibility(View.VISIBLE);
- mCityList = DataSupport.where("provinceid = ?", String.valueOf(mSelectedProvince.getId())).find(City.class);
- if (mCityList.size() > 0) {
- mDataList.clear();
- for (City city : mCityList) {
- mDataList.add(city.getCityName());
- }
- mStringArrayAdapter.notifyDataSetChanged();
- mListView.setSelection(0);
- mCurrentLevel = LEVEL_CITY;
- } else {
- int provinceCode = mSelectedProvince.getProvinceCode();
- String address = "http://guolin.tech/api/china/" + provinceCode;
- queryFromServer(address,"city");
- }
- }
-
- /**
- * 查询全国所有的县,优先从数据库查询,如果没有查询到再去服务器查询
- * */
- private void queryCounties() {
- mTitleText.setText(mSelectedCity.getCityName());
- mBackButton.setVisibility(View.VISIBLE);
- mCountyList = DataSupport.where("cityid = ?", String.valueOf(mSelectedCity.getId())).find(County.class);
- if (mCountyList.size() > 0) {
- mDataList.clear();
- for (County county : mCountyList) {
- mDataList.add(county.getCountyName());
- }
- mStringArrayAdapter.notifyDataSetChanged();
- mListView.setSelection(0);
- mCurrentLevel = LEVEL_COUNTY;
- } else {
- int provinceCode = mSelectedProvince.getProvinceCode();
- int cityCode = mSelectedCity.getCitycode();
- String address = "http://guolin.tech/api/china/" + provinceCode + "/" + cityCode;
- queryFromServer(address,"county");
- }
- }
-
- /**
- * 根据传入的地址和类型从服务器上查询省市县数据
- * */
- private void queryFromServer(String address, final String type) {
- showProgressDialog();
- HttpUtil.sendOkHttpRequest(address, new Callback() {
- @Override
- public void onFailure(@NotNull Call call, @NotNull IOException e) {
- // 通过runOnUiThread回到主线程处理逻辑
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- closeProgressDialog();
- Toast.makeText(getContext(),"加载失败",Toast.LENGTH_SHORT).show();
- }
- });
- }
-
- @Override
- public void onResponse(@NotNull Call call, @NotNull 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,mSelectedProvince.getId());
- } else if ("county".equals(type)) {
- result = Utility.handleCountyResponse(responseText,mSelectedCity.getId());
- }
- if (result) {
- getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- closeProgressDialog();
- switch (type) {
- case "province":
- queryProvinces();
- break;
- case "city":
- queryCities();
- break;
- case "county":
- queryCounties();
- break;
- }
- }
- });
- }
- }
- });
- }
-
- /**
- * 显示对话框
- * */
- private void showProgressDialog() {
- if (mProgressDialog == null) {
- mProgressDialog = new ProgressDialog(getActivity());
-
- // 这里的话参数依次为,上下文,标题,内容,是否显示进度(flase表示显示进度),是否可以用取消按钮关闭
- // ProgressDialog.show(getActivity(), "资源加载中", "资源加载中,请稍后...",false,false);
- // setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)这里是设置进度条的风格,HORIZONTAL是水平进度条,SPINNER是圆形进度条
- mProgressDialog.setTitle("资源加载中");
- mProgressDialog.setMessage("正在加载,请稍后...");
- mProgressDialog.setCanceledOnTouchOutside(false);
- }
- mProgressDialog.show();
- }
-
- /**
- * 关闭进度对话框
- * */
- private void closeProgressDialog() {
- if (mProgressDialog != null) {
- mProgressDialog.dismiss();
- }
- }
- }
- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".activity.MainActivity">
-
- <fragment
- android:id="@+id/area_fragment_choose"
- android:name="com.coolweather.android.activity.ChooseAreaFragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- </FrameLayout>
- <?xml version="1.0" encoding="utf-8"?>
- <network-security-config>
- <base-config cleartextTrafficPermitted="true" />
- </network-security-config>
- <!-- 配置LitePalApplication -->
- <application
- android:name="org.litepal.LitePalApplication"
- android:networkSecurityConfig="@xml/network_security_config"
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/AppTheme"
- tools:targetApi="n">
- <activity android:name=".activity.MainActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
http://guolin.tech/api/weather?cityid=CN101010100&key=08f828b5a3ec4905a29156bf5f29136fhttp://guolin.tech/api/weather?cityid=CN101010100&key=08f828b5a3ec4905a29156bf5f29136f
- {"HeWeather":[{
- "basic":{"cid":"CN101010100","location":"北京","parent_city":"北京","admin_area":"北京","cnty":"中国","lat":"25.04060936","lon":"102.71224976","tz":"+8.00","city":"北京","id":"CN101010100","update":{"loc":"2020-09-04 10:52","utc":"2020-09-04 02:52"}},
- "update":{"loc":"2020-09-04 10:52","utc":"2020-09-04 02:52"},
- "status":"ok",
- "now":{"cloud":"0","cond_code":"100","cond_txt":"晴","fl":"19","hum":"34","pcpn":"0.0","pres":"1018","tmp":"21","vis":"16","wind_deg":"149","wind_dir":"东南风","wind_sc":"2","wind_spd":"10","cond":{"code":"100","txt":"晴"}},
- "daily_forecast":[
- {"date":"2020-09-05","cond":{"txt_d":"晴"},"tmp":{"max":"24","min":"7"}},
- {"date":"2020-09-06","cond":{"txt_d":"晴"},"tmp":{"max":"26","min":"8"}},
- {"date":"2020-09-07","cond":{"txt_d":"多云"},"tmp":{"max":"25","min":"10"}},
- {"date":"2020-09-08","cond":{"txt_d":"阴"},"tmp":{"max":"27","min":"7"}},
- {"date":"2020-09-09","cond":{"txt_d":"晴"},"tmp":{"max":"28","min":"9"}},
- {"date":"2020-09-10","cond":{"txt_d":"多云"},"tmp":{"max":"26","min":"11"}}],
- "aqi":{"city":{"aqi":"47","pm25":"28","qlty":"优"}},
- "suggestion":{
- "comf":{"type":"comf","brf":"舒适","txt":"白天不太热也不太冷,风力不大,相信您在这样的天气条件下,应会感到比较清爽和舒适。"},
- "sport":{"type":"sport","brf":"较适宜","txt":"天气较好,户外运动请注意防晒。推荐您进行室内运动。"},
- "cw":{"type":"cw","brf":"较适宜","txt":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"}},
- "msg":"所有天气数据均为模拟数据,仅用作学习目的使用,请勿当作真实的天气预报软件来使用。"
- }]}
basic、now、daily_forecast、aqi、suggestion的内部又有其他的内容,因此我们可以将这5个部分定义成5个实体类
- {
- "HeWeather":[
- {
- "basic":{},
- "status":"ok",
- "now":{},
- "daily_forecast":[],
- "aqi":{},
- "suggestion":{},
- }
- ]
- }
basic中,city表示城市名,id表示城市对应的天气update表示天气更新时间
- "basic":{
- "city":"北京",
- "id":"CN101010100",
- "update":{
- "loc":"2020-09-04 10:52",
- "utc":"2020-09-04 02:52"
- }
- }
- public class Basic {
-
- @SerializedName("city")
- public String cityName;
-
- @SerializedName("id")
- public String weatherId;
-
- @SerializedName("update")
- public Update update;
-
- public class Update {
-
- @SerializedName("loc")
- public String updateTime;
- }
-
- }
- "aqi":{
- "city":{
- "aqi":"47",
- "pm25":"28",
- "qlty":"优"
- }
- }
- public class AQI {
-
- @SerializedName("city")
- public AQICity mAQICity;
-
- public class AQICity {
-
- public String aqi;
-
- public String pm25;
-
- }
- }
now
- "now":{
- "tmp":"21",
- "cond":{
- "code":"100",
- "txt":"晴"
- }
- }
实体类
- public class Now {
-
- @SerializedName("tmp")
- public String temperature;
-
- @SerializedName("cond")
- public More more;
-
- public class More {
-
- @SerializedName("txt")
- public String info;
- }
- }
suggestipon
"suggestion":{ "comf":{ "type":"comf", "brf":"舒适", "txt":"白天不太热也不太冷,风力不大,相信您在这样的天气条件下,应会感到比较清爽和舒适。" }, "sport":{ "type":"sport", "brf":"较适宜", "txt":"天气较好,户外运动请注意防晒。推荐您进行室内运动。" }, "cw":{ "type":"cw", "brf":"较适宜", "txt":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。" } }
实体类
- public class Suggestion {
-
- @SerializedName("comf")
- public Comfort mComfort;
-
- @SerializedName("cw")
- public CarWash mCarWash;
-
- @SerializedName("sport")
- public Sport mSport;
-
- public static class Comfort {
-
- @SerializedName("txt")
- public String info;
-
- }
-
- public static class CarWash {
-
- @SerializedName("txt")
- public String info;
-
- }
-
- public static class Sport {
-
- @SerializedName("txt")
- public String info;
-
- }
-
- }
daily_forecast
- "daily_forecast":[
- {
- "date":"2020-09-05",
- "cond":{
- "txt_d":"晴"
- },
- "tmp":{
- "max":"24",
- "min":"7"
- }
- },
- {
- "date":"2020-09-06",
- "cond":{
- "txt_d":"晴"
- },
- "tmp":{
- "max":"26",
- "min":"8"
- }
- },
- ...
- ]
实体类
- public class Forecast {
-
- public String date;
-
- @SerializedName("tmp")
- public Temperature mTemperature;
-
- @SerializedName("cond")
- public More mMore;
-
- public static class Temperature {
-
- public String max;
-
- public String min;
-
- }
-
- public static class More {
-
- @SerializedName("txt")
- public String info;
- }
-
- }
weather
- public class Weather {
-
- public String status;
-
- @SerializedName("basic")
- public Basic mBasic;
-
- @SerializedName("aqi")
- public AQI mAQI;
-
- @SerializedName("now")
- public Now mNow;
-
- @SerializedName("suggestion")
- public Suggestion mSuggestion;
-
- @SerializedName("daily_forecast")
- public List<Forecast> mForecastList;
- }
第十二步,编写天气界面,由于模块较多,分开写,最后include进来
- <?xml version="1.0" encoding="utf-8"?>
- <!--将所有的子布局加载进来显示-->
- <FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".activity.WeatherActivity"
- android:background="@color/colorPrimary">
-
- <ScrollView
- android:id="@+id/weather_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scrollbars="none"
- android:overScrollMode="never">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <include layout="@layout/weather_title"/>
-
- <include layout="@layout/weather_now"/>
-
- <include layout="@layout/weather_forecast"/>
-
- <include layout="@layout/weather_aqi"/>
-
- <include layout="@layout/weather_suggestion"/>
- </LinearLayout>
- </ScrollView>
- </FrameLayout>
weather_title
- <?xml version="1.0" encoding="utf-8"?>
- <!--头布局,用于居中显示城市名,居右显示更新时间-->
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize">
-
-
- <TextView
- android:id="@+id/weather_title_city"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:textColor="#fff"
- android:textSize="20sp"/>
-
- <TextView
- android:id="@+id/weather_title_update_time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="10dp"
- android:layout_marginEnd="10dp"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- android:textColor="#fff"
- android:textSize="16sp" />
- </RelativeLayout>
weather_now
- <!--当前天气信息的布局,用于显示当前气温和天气概况-->
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_margin="15dp">
-
- <TextView
- android:id="@+id/weather_now_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_now_info_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end"
- android:textColor="#fff"
- android:textSize="20sp"/>
- </LinearLayout>
weather_forecast
- <!--未来几天天气的布局,用于显示未来几天天气,包含一个标题和用于显示未来几天天气信息的布局,无任何内容,因为要动态添加-->
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_margin="15dp"
- android:background="#8000">
-
- <TextView
- android:id="@+id/weather_forecast_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="15dp"
- android:layout_marginStart="15dp"
- android:layout_marginTop="15dp"
- android:text="@string/weather_forecast_text_view"
- android:textColor="#fff"
- android:textSize="20sp" />
-
- <LinearLayout
- android:id="@+id/weather_forecast_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"/>
- </LinearLayout>
item_forecast
- <!--用于显示天气预报日期、天气概况、最高温、最低温-->
- <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/item_forecast_data_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="2"
- android:layout_gravity="center_vertical"
- android:textColor="#fff"/>
-
- <TextView
- android:id="@+id/item_forecast_info_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="center_vertical"
- android:gravity="center"
- android:textColor="#fff" />
-
- <TextView
- android:id="@+id/item_forecast_max_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="center_vertical"
- android:gravity="right"
- android:textColor="#fff" />
-
- <TextView
- android:id="@+id/item_forecast_min_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="center_vertical"
- android:gravity="right"
- android:textColor="#fff" />
- </LinearLayout>
weather_aqi
- <!--空气质量信息的布局,这里用于显示AQI指数和PM25指数-->
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="15dp"
- android:background="#8000"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/weather_aqi_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="15dp"
- android:layout_marginStart="15dp"
- android:layout_marginTop="15dp"
- android:text="@string/weather_aqi_title"
- android:textColor="#fff"
- android:textSize="20sp" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_margin="15dp"
- android:baselineAligned="false">
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/weather_aqi_aqi_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:textColor="#fff"
- android:textSize="40sp"/>
-
- <TextView
- android:id="@+id/weather_aqi_aqi_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:textColor="#fff"
- android:text="@string/weather_aqi_aqi_info" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/weather_aqi_pm25_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:textColor="#fff"
- android:textSize="40sp" />
-
- <TextView
- android:id="@+id/weather_aqi_pm25_info"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:textColor="#fff"
- android:text="@string/weather_aqi_pm25_info" />
- </LinearLayout>
- </LinearLayout>
-
- </LinearLayout>
weather_suggestion
- <!--生活建议的布局,用于显示标题、舒适度、洗车指数和运动指数-->
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_margin="15dp"
- android:background="#8000">
-
- <TextView
- android:id="@+id/weather_suggestion_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="15dp"
- android:layout_marginStart="15dp"
- android:layout_marginTop="15dp"
- android:text="@string/weather_suggestion_title"
- android:textColor="#fff"
- android:textSize="20sp" />
-
- <TextView
- android:id="@+id/weather_suggestion_comfort_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="15dp"
- android:textColor="#fff"/>
-
- <TextView
- android:id="@+id/weather_suggestion_car_wash_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="15dp"
- android:textColor="#fff" />
-
- <TextView
- android:id="@+id/weather_suggestion_sport_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="15dp"
- android:textColor="#fff" />
- </LinearLayout>
- 第十三步,在Utility里添加一个用于解析天气Json数据的方法
- /**
- * 将返回的Json数据解析成Weather实体类
- * */
- public static Weather handleWeatherResponse(String response) {
- try {
- JSONObject jsonObject = new JSONObject(response);
- JSONArray jsonArray = jsonObject.getJSONArray("HeWeather");
- String weatherContent = jsonArray.getJSONArray(0).toString();
- return new Gson().fromJson(weatherContent,Weather.class);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- 第十四步,修改WeatherActivity的代码,在其中去请求天气数据,以及将数据展示在界面上
- public class WeatherActivity extends AppCompatActivity {
-
- private ScrollView weatherLayout;
-
- private TextView weatherTitleCity;
-
- private TextView weatherTitleUpdateTime;
-
- private TextView weatherNowDegreeText;
-
- private TextView weatherNowInfoText;
-
- private LinearLayout weatherForecastLayout;
-
- private TextView weatherAQIText;
-
- private TextView weatherPM25Text;
-
- private TextView weatherSuggestionComfortText;
-
- private TextView weatherSuggestionCarWashText;
-
- private TextView weatherSuggestionSportText;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_weather);
- //初始化各控件
- weatherLayout = findViewById(R.id.weather_layout);
- weatherTitleCity = findViewById(R.id.weather_title_city);
- weatherTitleUpdateTime = findViewById(R.id.weather_title_update_time);
- weatherNowDegreeText = findViewById(R.id.weather_now_degree_text);
- weatherNowInfoText = findViewById(R.id.weather_now_info_text);
- weatherForecastLayout = findViewById(R.id.weather_forecast_layout);
- weatherAQIText = findViewById(R.id.weather_aqi_aqi_text);
- weatherPM25Text = findViewById(R.id.weather_aqi_pm25_text);
- weatherSuggestionComfortText = findViewById(R.id.weather_suggestion_comfort_text);
- weatherSuggestionCarWashText = findViewById(R.id.weather_suggestion_car_wash_text);
- weatherSuggestionSportText = findViewById(R.id.weather_suggestion_sport_text);
-
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- String weatherString = prefs.getString("weather",null);
- if (weatherString != null) {
- //有缓存时直接解析天气数据
- Weather weather = Utility.handleWeatherResponse(weatherString);
- showWeatherInfo(weather);
- } else {
- //无缓存时去服务器查询天气
- String weatherId = getIntent().getStringExtra("weather_id");
- weatherLayout.setVisibility(View.INVISIBLE);
- requestWeather(weatherId);
- }
-
- }
-
- /**
- * 根据天气id请求城市天气信息
- * */
- public void requestWeather(final String weatherId) {
-
- String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=08f828b5a3ec4905a29156bf5f29136f";
-
- HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
- @Override
- public void onFailure(@NotNull Call call, @NotNull IOException e) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(WeatherActivity.this,"获取天气信息失败",Toast.LENGTH_SHORT).show();
- }
- });
- }
-
- @Override
- public void onResponse(@NotNull Call call, @NotNull 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);
- } else {
- Toast.makeText(WeatherActivity.this,"获取天气信息失败",Toast.LENGTH_SHORT);
- }
- }
- });
- }
- });
-
-
-
- }
-
- /**
- * 处理并展示Weather实体类中的数据
- * */
- private void showWeatherInfo(Weather weather) {
- String cityName = weather.mBasic.cityName;
- String updateTime = weather.mBasic.mUpdate.updateTime.split( " ")[1];
- String degree = weather.mNow.temperature + "℃";
- String weatherInfo = weather.mNow.mMore.info;
- weatherTitleCity.setText(cityName);
- weatherTitleUpdateTime.setText(updateTime);
- weatherNowDegreeText.setText(degree);
- weatherNowInfoText.setText(weatherInfo);
- weatherForecastLayout.removeAllViews();
- for (Forecast forecast : weather.mForecastList) {
- View view = LayoutInflater.from(this).inflate(R.layout.item_forecast,weatherForecastLayout,false);
- TextView dateText = view.findViewById(R.id.item_forecast_data_text);
- TextView infoText = view.findViewById(R.id.item_forecast_info_text);
- TextView maxText = view.findViewById(R.id.item_forecast_max_text);
- TextView minText = view.findViewById(R.id.item_forecast_min_text);
- dateText.setText(forecast.date);
- infoText.setText(forecast.mMore.info);
- maxText.setText(forecast.mTemperature.max);
- minText.setText(forecast.mTemperature.min);
- weatherForecastLayout.addView(view);
- }
- if (weather.mAQI != null) {
- weatherAQIText.setText(weather.mAQI.mAQICity.aqi);
- weatherPM25Text.setText(weather.mAQI.mAQICity.pm25);
- }
- String comfort = "舒适度:" + weather.mSuggestion.mComfort.info;
- String carWash = "洗车指数:" + weather.mSuggestion.mCarWash.info;
- String sport = "运动指数:" + weather.mSuggestion.mSport.info;
- weatherSuggestionComfortText.setText(comfort);
- weatherSuggestionCarWashText.setText(carWash);
- weatherSuggestionSportText.setText(sport);
- weatherLayout.setVisibility(View.VISIBLE);
-
- }
- }
- mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
- if (mCurrentLevel == LEVEL_PROVINCE) {
- mSelectedProvince = mProvinceList.get(position);
- queryCities();
- } else if (mCurrentLevel == LEVEL_CITY) {
- mSelectedCity = mCityList.get(position);
- queryCounties();
- } else if (mCurrentLevel == LEVEL_COUNTY) {
- String weatherId = mCountyList.get(position).getWeatherId();
- Intent intent = new Intent(getActivity(),WeatherActivity.class);
- intent.putExtra("weather_id",weatherId);
- startActivity(intent);
- getActivity().finish();
- }
- }
- });
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- if (prefs.getString("weather",null) != null) {
- Intent intent = new Intent(this,WeatherActivity.class);
- startActivity(intent);
- finish();
- }
- }
- <ImageView
- android:id="@+id/bing_pic_img"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerCrop"
- android:contentDescription="@string/bing_pic_img" />
- /**
- * 加载必应每日一图
- * */
- private void loadBingPic() {
- String requestBingPic = "http://guolin.tech/api/bing_pic";
- HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {
- @Override
- public void onFailure(@NotNull Call call, @NotNull IOException e) {
- e.printStackTrace();
- }
-
- @Override
- public void onResponse(@NotNull Call call, @NotNull 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() {
- @Override
- public void run() {
- Glide.with(WeatherActivity.this).load(bingPic).into(bingPicImg);
- }
- });
- }
- });
- }
- <!--使用DrawerLayout实现菜单布局,其中第一个子控件用于作为主屏幕显示的内容,第二个字控件用于作为滑动菜单中显示的内容
- layout_gravity指定了菜单所处的方向,且必须指定-->
- <androidx.drawerlayout.widget.DrawerLayout
- android:id="@+id/drawer_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
- android:id="@+id/swipe_refresh"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <ScrollView
- android:id="@+id/weather_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scrollbars="none"
- android:overScrollMode="never">
-
- <!--为状态看留出空间fitsSystemWindows="true"-->
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:fitsSystemWindows="true">
-
- <include layout="@layout/weather_title"/>
-
- <include layout="@layout/weather_now"/>
-
- <include layout="@layout/weather_forecast"/>
-
- <include layout="@layout/weather_aqi"/>
-
- <include layout="@layout/weather_suggestion"/>
- </LinearLayout>
- </ScrollView>
- </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
-
- <fragment
- android:id="@+id/choose_area_fragment"
- android:name="com.coolweather.android.activity.ChooseAreaFragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="start"/>
-
- </androidx.drawerlayout.widget.DrawerLayout>
- mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
- @Override
- public void onRefresh() {
- requestWeather(weatherId);
- }
- });
- String bingPic = prefs.getString("bing_pic",null);
- if (bingPic != null) {
- Glide.with(this).load(bingPic).into(bingPicImg);
- } else {
- loadBingPic();
- }
- public class AutoUpdateService extends Service {
- public AutoUpdateService() {
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- updateWeather();
- updateBingPic();
- AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
- // 八小时更新一次
- int anHour = 8 * 60 * 60 * 1000;
- long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
- Intent intentOne = new Intent(this,AutoUpdateService.class);
- PendingIntent pendingIntent = PendingIntent.getService(this,0,intentOne,0);
- manager.cancel(pendingIntent);
- manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent);
- return super.onStartCommand(intent, flags, startId);
- }
-
- /**
- * 更新天气信息
- * */
- private void updateWeather() {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- String weatherString = prefs.getString("weather",null);
- if (weatherString != null) {
- // 有缓存时直接解析天气数据
- Weather weather = Utility.handleWeatherResponse(weatherString);
- String weatherId = weather.mBasic.weatherId;
-
- String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=08f828b5a3ec4905a29156bf5f29136f";
- HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
- @Override
- public void onFailure(@NotNull Call call, @NotNull IOException e) {
- e.printStackTrace();
- }
-
- @Override
- public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
- String responseText = response.body().string();
- Weather weather = Utility.handleWeatherResponse(responseText);
- if (weather != null && "ok".equals(weather.status)) {
- SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(AutoUpdateService.this).edit();
- editor.putString("weather",responseText);
- editor.apply();
- }
- }
- });
- }
- }
-
- /**
- * 更新必应每日一图
- * */
- private void updateBingPic() {
- String requestBingPic = "http://guolin.tech/api/bing_pic";
- HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {
- @Override
- public void onFailure(@NotNull Call call, @NotNull IOException e) {
- e.printStackTrace();
- }
-
- @Override
- public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
- String bingPic = response.body().string();
- SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(AutoUpdateService.this).edit();
- editor.putString("bing_pic",bingPic);
- editor.apply();
- }
- });
- }
- }
https://github.com/qricis/DoSomeAndroidTest/tree/main/CoolWeather
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。