当前位置:   article > 正文

Android基础实战之天气实战|完整代码|带实例地址_android天气预报实战演练

android天气预报实战演练

天气实战

  • 第一步

第一步,注册和风天气控制台 | 和风天气,申请key

08f828b5a3ec4905a29156bf5f29136f

查看郭林的后台天气pai接口

http://guolin.tech/api/china

  • 第二步,建立省市县实体类
  1. /**
  2. * Description
  3. * <p>
  4. * id是每个实体该有的字段
  5. * provinceName记录省的名字
  6. * provinceCode记录省的代号
  7. * @author qricis on 2020/9/3 14:47
  8. * @version 1.0.0
  9. */
  10. public class Province extends DataSupport {
  11. private int id;
  12. private String provinceName;
  13. private int provinceCode;
  14. public int getId() {
  15. return id;
  16. }
  17. public void setId(int id) {
  18. this.id = id;
  19. }
  20. public String getProvinceName() {
  21. return provinceName;
  22. }
  23. public void setProvinceName(String provinceName) {
  24. this.provinceName = provinceName;
  25. }
  26. public int getProvinceCode() {
  27. return provinceCode;
  28. }
  29. public void setProvinceCode(int provinceCode) {
  30. this.provinceCode = provinceCode;
  31. }
  32. }
  33. /**
  34. * Description
  35. * <p>
  36. * id是每个实体类都应该有的字段
  37. * cityName记录市的名字
  38. * cityCode记录市的代码
  39. * provinceId记录当前市所属省的id值
  40. * @author qricis on 2020/9/3 14:47
  41. * @version 1.0.0
  42. */
  43. public class City extends DataSupport {
  44. private int id;
  45. private String cityName;
  46. private int citycode;
  47. private int provinceId;
  48. public int getId() {
  49. return id;
  50. }
  51. public void setId(int id) {
  52. this.id = id;
  53. }
  54. public String getCityName() {
  55. return cityName;
  56. }
  57. public void setCityName(String cityName) {
  58. this.cityName = cityName;
  59. }
  60. public int getCitycode() {
  61. return citycode;
  62. }
  63. public void setCitycode(int citycode) {
  64. this.citycode = citycode;
  65. }
  66. public int getProvinceId() {
  67. return provinceId;
  68. }
  69. public void setProvinceId(int provinceId) {
  70. this.provinceId = provinceId;
  71. }
  72. }
  73. /**
  74. * Description
  75. * <p>
  76. * id是每个实体类都应该有的字段
  77. * countyName记录县的名字
  78. * weatherId记录县的天气代码
  79. * cityId记录当前县所属市的id
  80. * @author qricis on 2020/9/3 14:47
  81. * @version 1.0.0
  82. */
  83. public class County extends DataSupport {
  84. private int id;
  85. private String countyName;
  86. private int countyCode;
  87. private int cityId;
  88. public int getId() {
  89. return id;
  90. }
  91. public void setId(int id) {
  92. this.id = id;
  93. }
  94. public String getCountyName() {
  95. return countyName;
  96. }
  97. public void setCountyName(String countyName) {
  98. this.countyName = countyName;
  99. }
  100. public int getCountyCode() {
  101. return countyCode;
  102. }
  103. public void setCountyCode(int countyCode) {
  104. this.countyCode = countyCode;
  105. }
  106. public int getCityId() {
  107. return cityId;
  108. }
  109. public void setCityId(int cityId) {
  110. this.cityId = cityId;
  111. }
  112. }
  • 第三步,配置litepal
  1. <litepal>
  2. <!-- 设置数据库名为cool_weather,数据库版本1,并将三个实体类映射到列表当中 -->
  3. <dbname value="cool_weather" />
  4. <version value="1" />
  5. <list>
  6. <mapping class="com.coolweather.android.db.Province" />
  7. <mapping class="com.coolweather.android.db.City" />
  8. <mapping class="com.coolweather.android.db.County" />
  9. </list>
  10. </litepal>
  • 第四步,编写与服务端交互的类HttpUtil
  1. /**
  2. * Description
  3. * <p>
  4. * 与服务器进行交互
  5. * @author qricis on 2020/9/3 15:46
  6. * @version 1.0.0
  7. */
  8. public class HttpUtil {
  9. public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
  10. OkHttpClient client = new OkHttpClient();
  11. Request request = new Request.Builder().url(address).build();
  12. client.newCall(request).enqueue(callback);
  13. }
  14. }
  • 第五步,编写一个工具类用来处理从服务器端获取到的数据Utility
  1. /**
  2. * Description
  3. * <p>
  4. * 解析服务器返回的数据
  5. * @author qricis on 2020/9/3 15:53
  6. * @version 1.0.0
  7. */
  8. public class Utility {
  9. /**
  10. * 解析和处理服务器返回的省级数据
  11. * */
  12. public static boolean handleProvinceResponse(String response) {
  13. if (!TextUtils.isEmpty(response)) {
  14. try {
  15. JSONArray allProvinces = new JSONArray(response);
  16. for (int i = 0; i < allProvinces.length(); i++) {
  17. JSONObject provinceObject = allProvinces.getJSONObject(i);
  18. Province province = new Province();
  19. province.setProvinceName(provinceObject.getString("name"));
  20. province.setProvinceCode(provinceObject.getInt("id"));
  21. province.save();
  22. }
  23. return true;
  24. } catch (JSONException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. return false;
  29. }
  30. /**
  31. * 解析和处理服务器返回的市级数据
  32. * */
  33. public static boolean handleCityResponse(String response, int provinceId) {
  34. if (!TextUtils.isEmpty(response)) {
  35. try {
  36. JSONArray allCities = new JSONArray(response);
  37. for (int i = 0; i < allCities.length(); i++) {
  38. JSONObject cityObject = allCities.getJSONObject(i);
  39. City city = new City();
  40. city.setCityName(cityObject.getString("name"));
  41. city.setCitycode(cityObject.getInt("id"));
  42. city.setProvinceId(provinceId);
  43. city.save();
  44. }
  45. return true;
  46. } catch (JSONException e) {
  47. e.printStackTrace();
  48. }
  49. }
  50. return false;
  51. }
  52. /**
  53. * 解析和处理服务器返回的县级数据
  54. * */
  55. public static boolean handleCountyResponse(String response, int cityId) {
  56. if (!TextUtils.isEmpty(response)) {
  57. try {
  58. JSONArray allCounties = new JSONArray(response);
  59. for (int i = 0; i < allCounties.length(); i++) {
  60. JSONObject countyObject = allCounties.getJSONObject(i);
  61. County county = new County();
  62. county.setCountyName(countyObject.getString("name"));
  63. county.setCountyCode(countyObject.getInt("id"));
  64. county.setCityId(cityId);
  65. county.save();
  66. }
  67. return true;
  68. } catch (JSONException e) {
  69. e.printStackTrace();
  70. }
  71. }
  72. return false;
  73. }
  74. }
  • 第六步,编写选择布局choose_area
  1. <!-- 定义一个展示所有省市县的碎片 -->
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical"
  7. android:background="#fff">
  8. <RelativeLayout
  9. android:layout_width="match_parent"
  10. android:layout_height="?attr/actionBarSize"
  11. android:background="?attr/colorPrimary">
  12. <TextView
  13. android:id="@+id/area_tv_title"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:layout_centerInParent="true"
  17. android:textColor="#fff"
  18. android:textSize="20sp"/>
  19. <Button
  20. android:id="@+id/area_btn_back"
  21. android:layout_width="25dp"
  22. android:layout_height="25dp"
  23. android:layout_marginLeft="10dp"
  24. android:layout_marginStart="10dp"
  25. android:layout_alignParentLeft="true"
  26. android:layout_alignParentStart="true"
  27. android:layout_centerVertical="true"
  28. android:background="@drawable/area_btn_back"
  29. />
  30. </RelativeLayout>
  31. <ListView
  32. android:id="@+id/area_list_view"
  33. android:layout_width="match_parent"
  34. android:layout_height="match_parent" />
  35. </LinearLayout>
  • 第七步,编写用于遍历省市县数据的碎片ChooseAreaFragment
  1. /**
  2. * Description
  3. * <p>
  4. * 用于遍历省市县数据的碎片ChooseAreaFragment
  5. * @author qricis on 2020/9/3 17:25
  6. * @version 1.0.0
  7. */
  8. public class ChooseAreaFragment extends Fragment {
  9. public static final int LEVEL_PROVINCE = 0;
  10. public static final int LEVEL_CITY = 1;
  11. public static final int LEVEL_COUNTY = 2;
  12. private ProgressDialog mProgressDialog;
  13. private TextView mTitleText;
  14. private Button mBackButton;
  15. private ListView mListView;
  16. private ArrayAdapter<String> mStringArrayAdapter;
  17. private List<String> mDataList = new ArrayList<>();
  18. /**
  19. * 省列表
  20. * */
  21. private List<Province> mProvinceList;
  22. /**
  23. * 市列表
  24. * */
  25. private List<City> mCityList;
  26. /**
  27. * 县列表
  28. * */
  29. private List<County> mCountyList;
  30. /**
  31. * 选中的省份
  32. * */
  33. private Province mSelectedProvince;
  34. /**
  35. * 选中的城市
  36. * */
  37. private City mSelectedCity;
  38. /**
  39. * 当前选中的级别
  40. * */
  41. private int mCurrentLevel;
  42. /**
  43. * 获取控件实例,初始化mStringArrayAdapter,并将之设置为ListView的适配器
  44. * */
  45. @Nullable
  46. @Override
  47. public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  48. View view = inflater.inflate(R.layout.choose_area,container,false);
  49. mTitleText = view.findViewById(R.id.area_tv_title);
  50. mBackButton = view.findViewById(R.id.area_btn_back);
  51. mListView = view.findViewById(R.id.area_list_view);
  52. mStringArrayAdapter = new ArrayAdapter<>(getContext(),android.R.layout.simple_list_item_1,mDataList);
  53. mListView.setAdapter(mStringArrayAdapter);
  54. return view;
  55. }
  56. /**
  57. * 给ListView和Button设置点击事件
  58. * */
  59. @Override
  60. public void onActivityCreated(@Nullable Bundle savedInstanceState) {
  61. super.onActivityCreated(savedInstanceState);
  62. mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  63. @Override
  64. public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
  65. if (mCurrentLevel == LEVEL_PROVINCE) {
  66. mSelectedProvince = mProvinceList.get(position);
  67. queryCities();
  68. } else if (mCurrentLevel == LEVEL_CITY) {
  69. mSelectedCity = mCityList.get(position);
  70. queryCounties();
  71. }
  72. }
  73. });
  74. mBackButton.setOnClickListener(new View.OnClickListener() {
  75. @Override
  76. public void onClick(View view) {
  77. if (mCurrentLevel == LEVEL_COUNTY) {
  78. queryCities();
  79. } else if (mCurrentLevel == LEVEL_CITY) {
  80. queryProvinces();
  81. }
  82. }
  83. });
  84. queryProvinces();
  85. }
  86. /**
  87. * 查询全国所有的省,优先从数据库查询,如果没有查询到再去服务器查询
  88. * */
  89. private void queryProvinces() {
  90. mTitleText.setText("中国");
  91. mBackButton.setVisibility(View.GONE);
  92. mProvinceList = DataSupport.findAll(Province.class);
  93. if (mProvinceList.size() > 0) {
  94. mDataList.clear();
  95. for (Province province : mProvinceList) {
  96. mDataList.add(province.getProvinceName());
  97. }
  98. mStringArrayAdapter.notifyDataSetChanged();
  99. mListView.setSelection(0);
  100. mCurrentLevel = LEVEL_PROVINCE;
  101. } else {
  102. String address = "http://guolin.tech/api/china";
  103. queryFromServer(address,"province");
  104. }
  105. }
  106. /**
  107. * 查询全国所有的市,优先从数据库查询,如果没有查询到再去服务器查询
  108. * */
  109. private void queryCities() {
  110. mTitleText.setText(mSelectedProvince.getProvinceName());
  111. mBackButton.setVisibility(View.VISIBLE);
  112. mCityList = DataSupport.where("provinceid = ?", String.valueOf(mSelectedProvince.getId())).find(City.class);
  113. if (mCityList.size() > 0) {
  114. mDataList.clear();
  115. for (City city : mCityList) {
  116. mDataList.add(city.getCityName());
  117. }
  118. mStringArrayAdapter.notifyDataSetChanged();
  119. mListView.setSelection(0);
  120. mCurrentLevel = LEVEL_CITY;
  121. } else {
  122. int provinceCode = mSelectedProvince.getProvinceCode();
  123. String address = "http://guolin.tech/api/china/" + provinceCode;
  124. queryFromServer(address,"city");
  125. }
  126. }
  127. /**
  128. * 查询全国所有的县,优先从数据库查询,如果没有查询到再去服务器查询
  129. * */
  130. private void queryCounties() {
  131. mTitleText.setText(mSelectedCity.getCityName());
  132. mBackButton.setVisibility(View.VISIBLE);
  133. mCountyList = DataSupport.where("cityid = ?", String.valueOf(mSelectedCity.getId())).find(County.class);
  134. if (mCountyList.size() > 0) {
  135. mDataList.clear();
  136. for (County county : mCountyList) {
  137. mDataList.add(county.getCountyName());
  138. }
  139. mStringArrayAdapter.notifyDataSetChanged();
  140. mListView.setSelection(0);
  141. mCurrentLevel = LEVEL_COUNTY;
  142. } else {
  143. int provinceCode = mSelectedProvince.getProvinceCode();
  144. int cityCode = mSelectedCity.getCitycode();
  145. String address = "http://guolin.tech/api/china/" + provinceCode + "/" + cityCode;
  146. queryFromServer(address,"county");
  147. }
  148. }
  149. /**
  150. * 根据传入的地址和类型从服务器上查询省市县数据
  151. * */
  152. private void queryFromServer(String address, final String type) {
  153. showProgressDialog();
  154. HttpUtil.sendOkHttpRequest(address, new Callback() {
  155. @Override
  156. public void onFailure(@NotNull Call call, @NotNull IOException e) {
  157. // 通过runOnUiThread回到主线程处理逻辑
  158. getActivity().runOnUiThread(new Runnable() {
  159. @Override
  160. public void run() {
  161. closeProgressDialog();
  162. Toast.makeText(getContext(),"加载失败",Toast.LENGTH_SHORT).show();
  163. }
  164. });
  165. }
  166. @Override
  167. public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
  168. String responseText = response.body().string();
  169. boolean result = false;
  170. if ("province".equals(type)) {
  171. result = Utility.handleProvinceResponse(responseText);
  172. } else if ("city".equals(type)) {
  173. result = Utility.handleCityResponse(responseText,mSelectedProvince.getId());
  174. } else if ("county".equals(type)) {
  175. result = Utility.handleCountyResponse(responseText,mSelectedCity.getId());
  176. }
  177. if (result) {
  178. getActivity().runOnUiThread(new Runnable() {
  179. @Override
  180. public void run() {
  181. closeProgressDialog();
  182. switch (type) {
  183. case "province":
  184. queryProvinces();
  185. break;
  186. case "city":
  187. queryCities();
  188. break;
  189. case "county":
  190. queryCounties();
  191. break;
  192. }
  193. }
  194. });
  195. }
  196. }
  197. });
  198. }
  199. /**
  200. * 显示对话框
  201. * */
  202. private void showProgressDialog() {
  203. if (mProgressDialog == null) {
  204. mProgressDialog = new ProgressDialog(getActivity());
  205. // 这里的话参数依次为,上下文,标题,内容,是否显示进度(flase表示显示进度),是否可以用取消按钮关闭
  206. // ProgressDialog.show(getActivity(), "资源加载中", "资源加载中,请稍后...",false,false);
  207. // setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)这里是设置进度条的风格,HORIZONTAL是水平进度条,SPINNER是圆形进度条
  208. mProgressDialog.setTitle("资源加载中");
  209. mProgressDialog.setMessage("正在加载,请稍后...");
  210. mProgressDialog.setCanceledOnTouchOutside(false);
  211. }
  212. mProgressDialog.show();
  213. }
  214. /**
  215. * 关闭进度对话框
  216. * */
  217. private void closeProgressDialog() {
  218. if (mProgressDialog != null) {
  219. mProgressDialog.dismiss();
  220. }
  221. }
  222. }
  • 第八步,修改activity_main,使得碎片依附于活动显示
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. tools:context=".activity.MainActivity">
  7. <fragment
  8. android:id="@+id/area_fragment_choose"
  9. android:name="com.coolweather.android.activity.ChooseAreaFragment"
  10. android:layout_width="match_parent"
  11. android:layout_height="match_parent"/>
  12. </FrameLayout>
  • 第九步,设置http的访问权限,新建xml/network_security_config
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <network-security-config>
  3. <base-config cleartextTrafficPermitted="true" />
  4. </network-security-config>
  • 第十步,修改Manifest
  1. <!-- 配置LitePalApplication -->
  2. <application
  3. android:name="org.litepal.LitePalApplication"
  4. android:networkSecurityConfig="@xml/network_security_config"
  5. android:allowBackup="true"
  6. android:icon="@mipmap/ic_launcher"
  7. android:label="@string/app_name"
  8. android:roundIcon="@mipmap/ic_launcher_round"
  9. android:supportsRtl="true"
  10. android:theme="@style/AppTheme"
  11. tools:targetApi="n">
  12. <activity android:name=".activity.MainActivity">
  13. <intent-filter>
  14. <action android:name="android.intent.action.MAIN" />
  15. <category android:name="android.intent.category.LAUNCHER" />
  16. </intent-filter>
  17. </activity>
  18. </application>
  • 第十一步,查看天气json数据

http://guolin.tech/api/weather?cityid=CN101010100&key=08f828b5a3ec4905a29156bf5f29136fhttp://guolin.tech/api/weather?cityid=CN101010100&key=08f828b5a3ec4905a29156bf5f29136f

  • 返回值
  1. {"HeWeather":[{
  2. "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"}},
  3. "update":{"loc":"2020-09-04 10:52","utc":"2020-09-04 02:52"},
  4. "status":"ok",
  5. "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":"晴"}},
  6. "daily_forecast":[
  7. {"date":"2020-09-05","cond":{"txt_d":"晴"},"tmp":{"max":"24","min":"7"}},
  8. {"date":"2020-09-06","cond":{"txt_d":"晴"},"tmp":{"max":"26","min":"8"}},
  9. {"date":"2020-09-07","cond":{"txt_d":"多云"},"tmp":{"max":"25","min":"10"}},
  10. {"date":"2020-09-08","cond":{"txt_d":"阴"},"tmp":{"max":"27","min":"7"}},
  11. {"date":"2020-09-09","cond":{"txt_d":"晴"},"tmp":{"max":"28","min":"9"}},
  12. {"date":"2020-09-10","cond":{"txt_d":"多云"},"tmp":{"max":"26","min":"11"}}],
  13. "aqi":{"city":{"aqi":"47","pm25":"28","qlty":"优"}},
  14. "suggestion":{
  15. "comf":{"type":"comf","brf":"舒适","txt":"白天不太热也不太冷,风力不大,相信您在这样的天气条件下,应会感到比较清爽和舒适。"},
  16. "sport":{"type":"sport","brf":"较适宜","txt":"天气较好,户外运动请注意防晒。推荐您进行室内运动。"},
  17. "cw":{"type":"cw","brf":"较适宜","txt":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"}},
  18. "msg":"所有天气数据均为模拟数据,仅用作学习目的使用,请勿当作真实的天气预报软件来使用。"
  19. }]}
  • 简化版

basic、now、daily_forecast、aqi、suggestion的内部又有其他的内容,因此我们可以将这5个部分定义成5个实体类

  1. {
  2. "HeWeather":[
  3. {
  4. "basic":{},
  5. "status":"ok",
  6. "now":{},
  7. "daily_forecast":[],
  8. "aqi":{},
  9. "suggestion":{},
  10. }
  11. ]
  12. }

basic中,city表示城市名,id表示城市对应的天气update表示天气更新时间

  1. "basic":{
  2. "city":"北京",
  3. "id":"CN101010100",
  4. "update":{
  5. "loc":"2020-09-04 10:52",
  6. "utc":"2020-09-04 02:52"
  7. }
  8. }
  • 实体类
  1. public class Basic {
  2. @SerializedName("city")
  3. public String cityName;
  4. @SerializedName("id")
  5. public String weatherId;
  6. @SerializedName("update")
  7. public Update update;
  8. public class Update {
  9. @SerializedName("loc")
  10. public String updateTime;
  11. }
  12. }
  • aqi中
  1. "aqi":{
  2. "city":{
  3. "aqi":"47",
  4. "pm25":"28",
  5. "qlty":"优"
  6. }
  7. }
  • 实体类
  1. public class AQI {
  2. @SerializedName("city")
  3. public AQICity mAQICity;
  4. public class AQICity {
  5. public String aqi;
  6. public String pm25;
  7. }
  8. }

now

  1. "now":{
  2. "tmp":"21",
  3. "cond":{
  4. "code":"100",
  5. "txt":"晴"
  6. }
  7. }

实体类

  1. public class Now {
  2. @SerializedName("tmp")
  3. public String temperature;
  4. @SerializedName("cond")
  5. public More more;
  6. public class More {
  7. @SerializedName("txt")
  8. public String info;
  9. }
  10. }

suggestipon

"suggestion":{ "comf":{ "type":"comf", "brf":"舒适", "txt":"白天不太热也不太冷,风力不大,相信您在这样的天气条件下,应会感到比较清爽和舒适。" }, "sport":{ "type":"sport", "brf":"较适宜", "txt":"天气较好,户外运动请注意防晒。推荐您进行室内运动。" }, "cw":{ "type":"cw", "brf":"较适宜", "txt":"较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。" } }

实体类

  1. public class Suggestion {
  2. @SerializedName("comf")
  3. public Comfort mComfort;
  4. @SerializedName("cw")
  5. public CarWash mCarWash;
  6. @SerializedName("sport")
  7. public Sport mSport;
  8. public static class Comfort {
  9. @SerializedName("txt")
  10. public String info;
  11. }
  12. public static class CarWash {
  13. @SerializedName("txt")
  14. public String info;
  15. }
  16. public static class Sport {
  17. @SerializedName("txt")
  18. public String info;
  19. }
  20. }

daily_forecast

  1. "daily_forecast":[
  2. {
  3. "date":"2020-09-05",
  4. "cond":{
  5. "txt_d":"晴"
  6. },
  7. "tmp":{
  8. "max":"24",
  9. "min":"7"
  10. }
  11. },
  12. {
  13. "date":"2020-09-06",
  14. "cond":{
  15. "txt_d":"晴"
  16. },
  17. "tmp":{
  18. "max":"26",
  19. "min":"8"
  20. }
  21. },
  22. ...
  23. ]

实体类

  1. public class Forecast {
  2. public String date;
  3. @SerializedName("tmp")
  4. public Temperature mTemperature;
  5. @SerializedName("cond")
  6. public More mMore;
  7. public static class Temperature {
  8. public String max;
  9. public String min;
  10. }
  11. public static class More {
  12. @SerializedName("txt")
  13. public String info;
  14. }
  15. }

weather

  1. public class Weather {
  2. public String status;
  3. @SerializedName("basic")
  4. public Basic mBasic;
  5. @SerializedName("aqi")
  6. public AQI mAQI;
  7. @SerializedName("now")
  8. public Now mNow;
  9. @SerializedName("suggestion")
  10. public Suggestion mSuggestion;
  11. @SerializedName("daily_forecast")
  12. public List<Forecast> mForecastList;
  13. }

第十二步,编写天气界面,由于模块较多,分开写,最后include进来

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--将所有的子布局加载进来显示-->
  3. <FrameLayout
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. xmlns:app="http://schemas.android.com/apk/res-auto"
  6. xmlns:tools="http://schemas.android.com/tools"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. tools:context=".activity.WeatherActivity"
  10. android:background="@color/colorPrimary">
  11. <ScrollView
  12. android:id="@+id/weather_layout"
  13. android:layout_width="match_parent"
  14. android:layout_height="match_parent"
  15. android:scrollbars="none"
  16. android:overScrollMode="never">
  17. <LinearLayout
  18. android:layout_width="match_parent"
  19. android:layout_height="wrap_content"
  20. android:orientation="vertical">
  21. <include layout="@layout/weather_title"/>
  22. <include layout="@layout/weather_now"/>
  23. <include layout="@layout/weather_forecast"/>
  24. <include layout="@layout/weather_aqi"/>
  25. <include layout="@layout/weather_suggestion"/>
  26. </LinearLayout>
  27. </ScrollView>
  28. </FrameLayout>

weather_title

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--头布局,用于居中显示城市名,居右显示更新时间-->
  3. <RelativeLayout
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:layout_width="match_parent"
  6. android:layout_height="?attr/actionBarSize">
  7. <TextView
  8. android:id="@+id/weather_title_city"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:layout_centerInParent="true"
  12. android:textColor="#fff"
  13. android:textSize="20sp"/>
  14. <TextView
  15. android:id="@+id/weather_title_update_time"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:layout_marginRight="10dp"
  19. android:layout_marginEnd="10dp"
  20. android:layout_alignParentRight="true"
  21. android:layout_alignParentEnd="true"
  22. android:layout_centerVertical="true"
  23. android:textColor="#fff"
  24. android:textSize="16sp" />
  25. </RelativeLayout>

weather_now

  1. <!--当前天气信息的布局,用于显示当前气温和天气概况-->
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:orientation="vertical"
  7. android:layout_margin="15dp">
  8. <TextView
  9. android:id="@+id/weather_now_degree_text"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:layout_gravity="end"
  13. android:textColor="#fff"
  14. android:textSize="60sp"/>
  15. <TextView
  16. android:id="@+id/weather_now_info_text"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:layout_gravity="end"
  20. android:textColor="#fff"
  21. android:textSize="20sp"/>
  22. </LinearLayout>

weather_forecast

  1. <!--未来几天天气的布局,用于显示未来几天天气,包含一个标题和用于显示未来几天天气信息的布局,无任何内容,因为要动态添加-->
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:orientation="vertical"
  7. android:layout_margin="15dp"
  8. android:background="#8000">
  9. <TextView
  10. android:id="@+id/weather_forecast_title"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:layout_marginLeft="15dp"
  14. android:layout_marginStart="15dp"
  15. android:layout_marginTop="15dp"
  16. android:text="@string/weather_forecast_text_view"
  17. android:textColor="#fff"
  18. android:textSize="20sp" />
  19. <LinearLayout
  20. android:id="@+id/weather_forecast_layout"
  21. android:layout_width="match_parent"
  22. android:layout_height="wrap_content"
  23. android:orientation="vertical"/>
  24. </LinearLayout>

item_forecast

  1. <!--用于显示天气预报日期、天气概况、最高温、最低温-->
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:layout_margin="15dp">
  7. <TextView
  8. android:id="@+id/item_forecast_data_text"
  9. android:layout_width="0dp"
  10. android:layout_height="wrap_content"
  11. android:layout_weight="2"
  12. android:layout_gravity="center_vertical"
  13. android:textColor="#fff"/>
  14. <TextView
  15. android:id="@+id/item_forecast_info_text"
  16. android:layout_width="0dp"
  17. android:layout_height="wrap_content"
  18. android:layout_weight="1"
  19. android:layout_gravity="center_vertical"
  20. android:gravity="center"
  21. android:textColor="#fff" />
  22. <TextView
  23. android:id="@+id/item_forecast_max_text"
  24. android:layout_width="0dp"
  25. android:layout_height="wrap_content"
  26. android:layout_weight="1"
  27. android:layout_gravity="center_vertical"
  28. android:gravity="right"
  29. android:textColor="#fff" />
  30. <TextView
  31. android:id="@+id/item_forecast_min_text"
  32. android:layout_width="0dp"
  33. android:layout_height="wrap_content"
  34. android:layout_weight="1"
  35. android:layout_gravity="center_vertical"
  36. android:gravity="right"
  37. android:textColor="#fff" />
  38. </LinearLayout>

weather_aqi

  1. <!--空气质量信息的布局,这里用于显示AQI指数和PM25指数-->
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:layout_margin="15dp"
  7. android:background="#8000"
  8. android:orientation="vertical">
  9. <TextView
  10. android:id="@+id/weather_aqi_title"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:layout_marginLeft="15dp"
  14. android:layout_marginStart="15dp"
  15. android:layout_marginTop="15dp"
  16. android:text="@string/weather_aqi_title"
  17. android:textColor="#fff"
  18. android:textSize="20sp" />
  19. <LinearLayout
  20. android:layout_width="match_parent"
  21. android:layout_height="wrap_content"
  22. android:orientation="horizontal"
  23. android:layout_margin="15dp"
  24. android:baselineAligned="false">
  25. <LinearLayout
  26. android:layout_width="0dp"
  27. android:layout_weight="1"
  28. android:layout_height="wrap_content"
  29. android:orientation="vertical">
  30. <TextView
  31. android:id="@+id/weather_aqi_aqi_text"
  32. android:layout_width="wrap_content"
  33. android:layout_height="wrap_content"
  34. android:layout_gravity="center"
  35. android:textColor="#fff"
  36. android:textSize="40sp"/>
  37. <TextView
  38. android:id="@+id/weather_aqi_aqi_info"
  39. android:layout_width="wrap_content"
  40. android:layout_height="wrap_content"
  41. android:layout_gravity="center"
  42. android:textColor="#fff"
  43. android:text="@string/weather_aqi_aqi_info" />
  44. </LinearLayout>
  45. <LinearLayout
  46. android:layout_width="0dp"
  47. android:layout_weight="1"
  48. android:layout_height="wrap_content"
  49. android:orientation="vertical">
  50. <TextView
  51. android:id="@+id/weather_aqi_pm25_text"
  52. android:layout_width="wrap_content"
  53. android:layout_height="wrap_content"
  54. android:layout_gravity="center"
  55. android:textColor="#fff"
  56. android:textSize="40sp" />
  57. <TextView
  58. android:id="@+id/weather_aqi_pm25_info"
  59. android:layout_width="wrap_content"
  60. android:layout_height="wrap_content"
  61. android:layout_gravity="center"
  62. android:textColor="#fff"
  63. android:text="@string/weather_aqi_pm25_info" />
  64. </LinearLayout>
  65. </LinearLayout>
  66. </LinearLayout>

weather_suggestion

  1. <!--生活建议的布局,用于显示标题、舒适度、洗车指数和运动指数-->
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:orientation="vertical"
  7. android:layout_margin="15dp"
  8. android:background="#8000">
  9. <TextView
  10. android:id="@+id/weather_suggestion_title"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:layout_marginLeft="15dp"
  14. android:layout_marginStart="15dp"
  15. android:layout_marginTop="15dp"
  16. android:text="@string/weather_suggestion_title"
  17. android:textColor="#fff"
  18. android:textSize="20sp" />
  19. <TextView
  20. android:id="@+id/weather_suggestion_comfort_text"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:layout_margin="15dp"
  24. android:textColor="#fff"/>
  25. <TextView
  26. android:id="@+id/weather_suggestion_car_wash_text"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:layout_margin="15dp"
  30. android:textColor="#fff" />
  31. <TextView
  32. android:id="@+id/weather_suggestion_sport_text"
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:layout_margin="15dp"
  36. android:textColor="#fff" />
  37. </LinearLayout>

- 第十三步,在Utility里添加一个用于解析天气Json数据的方法

  1. /**
  2. * 将返回的Json数据解析成Weather实体类
  3. * */
  4. public static Weather handleWeatherResponse(String response) {
  5. try {
  6. JSONObject jsonObject = new JSONObject(response);
  7. JSONArray jsonArray = jsonObject.getJSONArray("HeWeather");
  8. String weatherContent = jsonArray.getJSONArray(0).toString();
  9. return new Gson().fromJson(weatherContent,Weather.class);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. return null;
  14. }

- 第十四步,修改WeatherActivity的代码,在其中去请求天气数据,以及将数据展示在界面上

  1. public class WeatherActivity extends AppCompatActivity {
  2. private ScrollView weatherLayout;
  3. private TextView weatherTitleCity;
  4. private TextView weatherTitleUpdateTime;
  5. private TextView weatherNowDegreeText;
  6. private TextView weatherNowInfoText;
  7. private LinearLayout weatherForecastLayout;
  8. private TextView weatherAQIText;
  9. private TextView weatherPM25Text;
  10. private TextView weatherSuggestionComfortText;
  11. private TextView weatherSuggestionCarWashText;
  12. private TextView weatherSuggestionSportText;
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_weather);
  17. //初始化各控件
  18. weatherLayout = findViewById(R.id.weather_layout);
  19. weatherTitleCity = findViewById(R.id.weather_title_city);
  20. weatherTitleUpdateTime = findViewById(R.id.weather_title_update_time);
  21. weatherNowDegreeText = findViewById(R.id.weather_now_degree_text);
  22. weatherNowInfoText = findViewById(R.id.weather_now_info_text);
  23. weatherForecastLayout = findViewById(R.id.weather_forecast_layout);
  24. weatherAQIText = findViewById(R.id.weather_aqi_aqi_text);
  25. weatherPM25Text = findViewById(R.id.weather_aqi_pm25_text);
  26. weatherSuggestionComfortText = findViewById(R.id.weather_suggestion_comfort_text);
  27. weatherSuggestionCarWashText = findViewById(R.id.weather_suggestion_car_wash_text);
  28. weatherSuggestionSportText = findViewById(R.id.weather_suggestion_sport_text);
  29. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  30. String weatherString = prefs.getString("weather",null);
  31. if (weatherString != null) {
  32. //有缓存时直接解析天气数据
  33. Weather weather = Utility.handleWeatherResponse(weatherString);
  34. showWeatherInfo(weather);
  35. } else {
  36. //无缓存时去服务器查询天气
  37. String weatherId = getIntent().getStringExtra("weather_id");
  38. weatherLayout.setVisibility(View.INVISIBLE);
  39. requestWeather(weatherId);
  40. }
  41. }
  42. /**
  43. * 根据天气id请求城市天气信息
  44. * */
  45. public void requestWeather(final String weatherId) {
  46. String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=08f828b5a3ec4905a29156bf5f29136f";
  47. HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
  48. @Override
  49. public void onFailure(@NotNull Call call, @NotNull IOException e) {
  50. runOnUiThread(new Runnable() {
  51. @Override
  52. public void run() {
  53. Toast.makeText(WeatherActivity.this,"获取天气信息失败",Toast.LENGTH_SHORT).show();
  54. }
  55. });
  56. }
  57. @Override
  58. public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
  59. final String responseText = response.body().string();
  60. final Weather weather = Utility.handleWeatherResponse(responseText);
  61. runOnUiThread(new Runnable() {
  62. @Override
  63. public void run() {
  64. if (weather != null && "ok".equals(weather.status)) {
  65. SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();
  66. editor.putString("weather",responseText);
  67. editor.apply();
  68. showWeatherInfo(weather);
  69. } else {
  70. Toast.makeText(WeatherActivity.this,"获取天气信息失败",Toast.LENGTH_SHORT);
  71. }
  72. }
  73. });
  74. }
  75. });
  76. }
  77. /**
  78. * 处理并展示Weather实体类中的数据
  79. * */
  80. private void showWeatherInfo(Weather weather) {
  81. String cityName = weather.mBasic.cityName;
  82. String updateTime = weather.mBasic.mUpdate.updateTime.split( " ")[1];
  83. String degree = weather.mNow.temperature + "℃";
  84. String weatherInfo = weather.mNow.mMore.info;
  85. weatherTitleCity.setText(cityName);
  86. weatherTitleUpdateTime.setText(updateTime);
  87. weatherNowDegreeText.setText(degree);
  88. weatherNowInfoText.setText(weatherInfo);
  89. weatherForecastLayout.removeAllViews();
  90. for (Forecast forecast : weather.mForecastList) {
  91. View view = LayoutInflater.from(this).inflate(R.layout.item_forecast,weatherForecastLayout,false);
  92. TextView dateText = view.findViewById(R.id.item_forecast_data_text);
  93. TextView infoText = view.findViewById(R.id.item_forecast_info_text);
  94. TextView maxText = view.findViewById(R.id.item_forecast_max_text);
  95. TextView minText = view.findViewById(R.id.item_forecast_min_text);
  96. dateText.setText(forecast.date);
  97. infoText.setText(forecast.mMore.info);
  98. maxText.setText(forecast.mTemperature.max);
  99. minText.setText(forecast.mTemperature.min);
  100. weatherForecastLayout.addView(view);
  101. }
  102. if (weather.mAQI != null) {
  103. weatherAQIText.setText(weather.mAQI.mAQICity.aqi);
  104. weatherPM25Text.setText(weather.mAQI.mAQICity.pm25);
  105. }
  106. String comfort = "舒适度:" + weather.mSuggestion.mComfort.info;
  107. String carWash = "洗车指数:" + weather.mSuggestion.mCarWash.info;
  108. String sport = "运动指数:" + weather.mSuggestion.mSport.info;
  109. weatherSuggestionComfortText.setText(comfort);
  110. weatherSuggestionCarWashText.setText(carWash);
  111. weatherSuggestionSportText.setText(sport);
  112. weatherLayout.setVisibility(View.VISIBLE);
  113. }
  114. }
  • 第十五步,修改ChooseAreaFragment的onActivityCreated()代码
  1. mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  2. @Override
  3. public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
  4. if (mCurrentLevel == LEVEL_PROVINCE) {
  5. mSelectedProvince = mProvinceList.get(position);
  6. queryCities();
  7. } else if (mCurrentLevel == LEVEL_CITY) {
  8. mSelectedCity = mCityList.get(position);
  9. queryCounties();
  10. } else if (mCurrentLevel == LEVEL_COUNTY) {
  11. String weatherId = mCountyList.get(position).getWeatherId();
  12. Intent intent = new Intent(getActivity(),WeatherActivity.class);
  13. intent.putExtra("weather_id",weatherId);
  14. startActivity(intent);
  15. getActivity().finish();
  16. }
  17. }
  18. });
  • 第十六步,修改MainActivity中的代码,判断是否已经请求过数据
  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  5. if (prefs.getString("weather",null) != null) {
  6. Intent intent = new Intent(this,WeatherActivity.class);
  7. startActivity(intent);
  8. finish();
  9. }
  10. }
  • 第十七步,获取必应的每日一图,修改activity_weather、weatherActivity
  1. <ImageView
  2. android:id="@+id/bing_pic_img"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:scaleType="centerCrop"
  6. android:contentDescription="@string/bing_pic_img" />
  7. /**
  8. * 加载必应每日一图
  9. * */
  10. private void loadBingPic() {
  11. String requestBingPic = "http://guolin.tech/api/bing_pic";
  12. HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {
  13. @Override
  14. public void onFailure(@NotNull Call call, @NotNull IOException e) {
  15. e.printStackTrace();
  16. }
  17. @Override
  18. public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
  19. final String bingPic = response.body().string();
  20. SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(WeatherActivity.this).edit();
  21. editor.putString("bing_pic",bingPic);
  22. editor.apply();
  23. runOnUiThread(new Runnable() {
  24. @Override
  25. public void run() {
  26. Glide.with(WeatherActivity.this).load(bingPic).into(bingPicImg);
  27. }
  28. });
  29. }
  30. });
  31. }
  • 第十八步,修改activity_weather,实现手动更新天气,切换城市
  1. <!--使用DrawerLayout实现菜单布局,其中第一个子控件用于作为主屏幕显示的内容,第二个字控件用于作为滑动菜单中显示的内容
  2. layout_gravity指定了菜单所处的方向,且必须指定-->
  3. <androidx.drawerlayout.widget.DrawerLayout
  4. android:id="@+id/drawer_layout"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent">
  7. <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
  8. android:id="@+id/swipe_refresh"
  9. android:layout_width="match_parent"
  10. android:layout_height="match_parent">
  11. <ScrollView
  12. android:id="@+id/weather_layout"
  13. android:layout_width="match_parent"
  14. android:layout_height="match_parent"
  15. android:scrollbars="none"
  16. android:overScrollMode="never">
  17. <!--为状态看留出空间fitsSystemWindows="true"-->
  18. <LinearLayout
  19. android:layout_width="match_parent"
  20. android:layout_height="wrap_content"
  21. android:orientation="vertical"
  22. android:fitsSystemWindows="true">
  23. <include layout="@layout/weather_title"/>
  24. <include layout="@layout/weather_now"/>
  25. <include layout="@layout/weather_forecast"/>
  26. <include layout="@layout/weather_aqi"/>
  27. <include layout="@layout/weather_suggestion"/>
  28. </LinearLayout>
  29. </ScrollView>
  30. </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
  31. <fragment
  32. android:id="@+id/choose_area_fragment"
  33. android:name="com.coolweather.android.activity.ChooseAreaFragment"
  34. android:layout_width="match_parent"
  35. android:layout_height="match_parent"
  36. android:layout_gravity="start"/>
  37. </androidx.drawerlayout.widget.DrawerLayout>
  38. mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
  39. @Override
  40. public void onRefresh() {
  41. requestWeather(weatherId);
  42. }
  43. });
  44. String bingPic = prefs.getString("bing_pic",null);
  45. if (bingPic != null) {
  46. Glide.with(this).load(bingPic).into(bingPicImg);
  47. } else {
  48. loadBingPic();
  49. }
  • 第十九步,新建AutoUpdateService,实现自动更新天气与城市
  1. public class AutoUpdateService extends Service {
  2. public AutoUpdateService() {
  3. }
  4. @Override
  5. public IBinder onBind(Intent intent) {
  6. return null;
  7. }
  8. @Override
  9. public int onStartCommand(Intent intent, int flags, int startId) {
  10. updateWeather();
  11. updateBingPic();
  12. AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
  13. // 八小时更新一次
  14. int anHour = 8 * 60 * 60 * 1000;
  15. long triggerAtTime = SystemClock.elapsedRealtime() + anHour;
  16. Intent intentOne = new Intent(this,AutoUpdateService.class);
  17. PendingIntent pendingIntent = PendingIntent.getService(this,0,intentOne,0);
  18. manager.cancel(pendingIntent);
  19. manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pendingIntent);
  20. return super.onStartCommand(intent, flags, startId);
  21. }
  22. /**
  23. * 更新天气信息
  24. * */
  25. private void updateWeather() {
  26. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
  27. String weatherString = prefs.getString("weather",null);
  28. if (weatherString != null) {
  29. // 有缓存时直接解析天气数据
  30. Weather weather = Utility.handleWeatherResponse(weatherString);
  31. String weatherId = weather.mBasic.weatherId;
  32. String weatherUrl = "http://guolin.tech/api/weather?cityid=" + weatherId + "&key=08f828b5a3ec4905a29156bf5f29136f";
  33. HttpUtil.sendOkHttpRequest(weatherUrl, new Callback() {
  34. @Override
  35. public void onFailure(@NotNull Call call, @NotNull IOException e) {
  36. e.printStackTrace();
  37. }
  38. @Override
  39. public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
  40. String responseText = response.body().string();
  41. Weather weather = Utility.handleWeatherResponse(responseText);
  42. if (weather != null && "ok".equals(weather.status)) {
  43. SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(AutoUpdateService.this).edit();
  44. editor.putString("weather",responseText);
  45. editor.apply();
  46. }
  47. }
  48. });
  49. }
  50. }
  51. /**
  52. * 更新必应每日一图
  53. * */
  54. private void updateBingPic() {
  55. String requestBingPic = "http://guolin.tech/api/bing_pic";
  56. HttpUtil.sendOkHttpRequest(requestBingPic, new Callback() {
  57. @Override
  58. public void onFailure(@NotNull Call call, @NotNull IOException e) {
  59. e.printStackTrace();
  60. }
  61. @Override
  62. public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
  63. String bingPic = response.body().string();
  64. SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(AutoUpdateService.this).edit();
  65. editor.putString("bing_pic",bingPic);
  66. editor.apply();
  67. }
  68. });
  69. }
  70. }
  • 下载地址

https://github.com/qricis/DoSomeAndroidTest/tree/main/CoolWeather

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/590044
推荐阅读
相关标签
  

闽ICP备14008679号