✅简易的安卓天气app(一)——解析Json数据、数据类封装
📌简易的安卓天气app(二)——适配器、每小时数据展示
✅简易的安卓天气app(三)——城市管理、数据库操作
✅简易的安卓天气app(四)——搜索城市、完善页面
需求
拒绝画饼,先讲需求,项目结构,整体思路,第一章我们只是封装了两个数据类WeatherBean和DayWeatherBean(此类存的是下图的data数据,是个JsonArray,里面包了JsonObject,7个表示7天,由于只需拿到当天数据,所以第0项就是当天详细天气),用来存放城市的当天天气,如果我们想要展示更精美的页面呢,或者说是展示更多的数据,比如,我们这里用RecyclerView展示一天中每个小时的天气,实现效果(若是想从当前时刻开始,获取小时温度,可自行实现,源码见页尾)
涉及内容
- 获取网络数据
- 数据实体类的封装
- 异步获取网络数据
- Gson工具类解析Json
- 界面设计RecyclerView
- 适配器adatper
项目结构
界面设计
既然用到了RecyclerView,那么就离不开adapter,RecyclerView负责准备一个框框,adapter负责把什么数据传到框内,顾名思义适配器
详细讲解C一下,第一篇就是,讲的非常全面,附加地址Android RecyclerView最全使用详解
布局效果
需要添加的RecyclerView
1 2 3 4 5 6 7 8 9 10 11 12
| <LinearLayout android:layout_width="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_height="100dp"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rlv_hour_weather" android:background="@drawable/blackground" android:alpha="0.75" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
|
id自定义名字,主要时在MainActivity里新增private RecyclerView rlvHourWeather;并findByView注册拿到之后就可以添加适配器了,想要哪个小页面传到这个RecyclerView中,,
每小时天气小界面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="60dp" android:layout_height="100dp" android:gravity="center_horizontal" android:orientation="vertical" tools:background="@mipmap/bg">
<TextView android:id="@+id/tv_hours" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="8:00" android:textColor="@color/white" android:textSize="18sp" /> <ImageView android:id="@+id/iv_weather" android:layout_width="45dp" android:layout_height="45dp" android:src="@drawable/weather_yin" />
<TextView android:id="@+id/tv_tem" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/white" android:textSize="19sp" tools:text="31" /> </LinearLayout>
|
网络Json数据解析
第一篇我们已经从天气api接口拿到了json并成功解析,还封装了两个实体类
下面四从api拿到的数据,里面的json数据格式化之后的形式,首先为了下面的讲解代码流畅性,这次先从解析此api接口的json数据入手
首先百度前往一个在线Json解析网站
https://www.json.cn/
或者是在Idea里新建个json后缀的文件,复制粘贴进去,格式化后就得到一层一层封装起来的json数据
或者前往客户端Android Studio寻找一个插件如下图第一个GsonFormat,详细用法自行C一下
这里讲解就去了在线Json解析网站
https://www.json.cn/
复制粘贴进去Json数据,转义和格式化后得到,ps(自用的火狐浏览器挺好的,自带Json转换功能)
第一篇文章已经写明,用到了第三方库Google的Gson工具,自动封装,两行代码完事,使用详情见第一篇文章,需要导包
想仔细学习,自己用JsonObject,JsonArray封装的,这篇文章不会讲太多,后面的文章会用到仔细封装,ps|小窍门(观察"[]"和"{}"你就会发现规律)
我们要得到每小时的数据,就要找一个对象,里面封装的是每小时的天气,就是说data数据0下标当天天气里还有一个对象,包了每个小时共24小时的详细数据,下面图片是解析
所以,从此hours数据的结构得知有需要封装一个数据类,还是包在当日天气DayWeatherBean下的一个List。
每小时数据实体类封装
此处这个数据类就叫做HoursWearBean,那么先修改当日天气DayWeatherBean,添加一个
private List<HoursWeatherBean> hoursWeatherBeanList;
属性,由于Gson会根据Json数据的属性名进行封装,所以就需要实现一个序列化接口implements Serializable
,并添加注解
这样变量名就可以随便命名了
若是不想实现,就老老实实用private List<HoursWeatherBean> hours;
,里面的变量名用hours命名之后就会发现可能报错,嘿嘿,每个小时数据里也有个hours
防止出错,属性可以都用一下注解,然后Get、Set修改一下,
接着就是每小时详细数据类的封装
HoursWeatherBean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class HoursWeatherBean implements Serializable { @SerializedName("hours") private String hours;
@SerializedName("wea_img") private String weaImg;
@SerializedName("tem") private String tem;
public String getHours() { return hours; }
public void setHours(String hours) { this.hours = hours; }
public String getWeaImg() { return weaImg; }
public void setWeaImg(String weaImg) { this.weaImg = weaImg; }
public String getTem() { return tem; }
public void setTem(String tem) { this.tem = tem; }
@Override public String toString() { return "HoursWeatherBean{" + "hours='" + hours + '\'' + ", weaImg='" + weaImg + '\'' + ", tem='" + tem + '\'' + '}'; } }
|
适配器HourWeatherAdapter
- 继承自RecyclerView.Adapter,构造HourWeatherAdapter
1 2 3 4 5 6
| private Context mContext; private List<HoursWeatherBean> mHoursWeatherBeans; public HourWeatherAdapter(Context context, List<HoursWeatherBean> hoursWeatherBeans) { mContext = context; this.mHoursWeatherBeans = hoursWeatherBeans; }
|
- 新建class类HourViewHolder
1 2 3 4 5 6 7 8 9 10 11 12 13
| class HourViewHolder extends RecyclerView.ViewHolder {
TextView tvHours, tvTem; ImageView ivWeather;
public HourViewHolder(@NonNull View itemView) { super(itemView); tvHours = itemView.findViewById(R.id.tv_hours); tvTem = itemView.findViewById(R.id.tv_tem); ivWeather = itemView.findViewById(R.id.iv_weather); } }
|
- 然后重写三个方法
点击错误提示,快速重写三个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @NonNull @Override public HourViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.hour_item_layout, parent, false); HourViewHolder hourViewHolder = new HourViewHolder(view); return hourViewHolder; }
@Override public void onBindViewHolder(@NonNull HourViewHolder holder, int position) { HoursWeatherBean hoursweatherBean = mHoursWeatherBeans.get(position); holder.tvTem.setText(hoursweatherBean.getTem()+"℃"); holder.tvHours.setText(hoursweatherBean.getHours().substring(0,2)+":00"); holder.ivWeather.setImageResource(WeatherImgUtil.getImgResOfWeather(hoursweatherBean.getWeaImg())); }
@Override public int getItemCount() { return (mHoursWeatherBeans == null) ? 0 : mHoursWeatherBeans.size(); }
|
MainActivity.java
接着就是拿到Json数据,封装称为数据类,我代码中直接Gson封装成WeatherBean,里面封装有List,而DayWeatherBean中又有List,一层一层包着,
当数据异步封装好后,
添加属性
1 2 3
| private HourWeatherAdapter mHourAdapter;
private RecyclerView rlvHourWeather;
|
1 2 3 4 5 6 7 8 9
|
mHourAdapter = new HourWeatherAdapter(this, dayWeather.getHoursWeatherBeanList()); rlvHourWeather.setAdapter(mHourAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); rlvHourWeather.setLayoutManager(layoutManager);
|
到此处就能完美展示每小时数据了,步骤在目录中,就是先设计界面,封装数据类,适配器,activity。代码行数有点小多,末尾附带源码
==源码地址==: