前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >安卓天气预报app(三)——城市管理、数据库操作

安卓天气预报app(三)——城市管理、数据库操作

作者头像
roydonGuo
发布2022-11-02 15:43:15
1.5K0
发布2022-11-02 15:43:15
举报
文章被收录于专栏:postsposts

简易的安卓天气app(一)——解析Json数据、数据类封装简易的安卓天气app(二)——适配器、每小时数据展示 📌简易的安卓天气app(三)——城市管理、数据库操作简易的安卓天气app(四)——搜索城市、完善页面

需求🏷️

当我们查看天气时,我们都拥有自己的手机,都知道现在的智能手机已经可以根据定位来自动查询所在位置的天气信息,这个依靠的就是手机的定位功能,此处的项目纯属练手,不会涉及定位操作,那一大堆步骤我直接放弃,所以这个功能我们可以偷鸡摸,,,不对,投机取巧从天气api接口想办法搞到。(源码见页尾✨)

本项目用到的天气api接口天气api 详细操作内容见第一篇-->🧿简易的安卓天气app(一)——解析Json数据<--

此接口当我们默认不拼接参数,直接访问会得到当前位置的温度Json数据,这不就弥补了我们在定位方面的缺陷了吗,那么很好,当我们加上参数之后(此api根据城市查询的参数需+&city=(城市名称))那么,当我们只加了参数却没有加参数值(&city=)他还是会根据当前位置进行定位,简直是太妙了。 所以接下来就是进行安卓SQLite数据库的一些操作,把当前位置信息保存到数据库中(城市名,城市温度,更新时间) 待实现效果:

gif
gif

数据库成功插入当前位置数据信息(之前测试插入过几条的测试对照用数据): 位置商丘的信息成功插入,插入之后,后续要进行的操作就是实时更新数据库

mancity
mancity

涉及内容

  • SQLite数据库操作,创建数据库,新建表,增删查改操作
  • 适配器adapter添加点击事件
  • 页面传值跳转项目结构
3
3

其他内容暂不涉及,本文章只包含城市管理,添加城市到数据库等的一系列操作,前面基础内容移步到页首地址界面设计 城市管理的界面设计city_manager.xml

city_manager
city_manager

city_manager.xml界面布局源码:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/bg"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/iv_add"
            android:layout_width="35dp"
            android:layout_height="30dp"
            android:layout_marginLeft="20dp"
            android:src="@drawable/add" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="城市管理"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:textColor="@color/purple_200"
            android:textSize="20dp" />

        <ImageView
            android:id="@+id/iv_more"
            android:layout_width="35dp"
            android:layout_height="30dp"
            android:layout_marginRight="20dp"
            android:src="@drawable/more" />
    </LinearLayout>

    <View
        android:layout_width="390dp"
        android:layout_height="8px"
        android:layout_gravity="center"
        android:layout_marginBottom="5dp"
        android:alpha="0.6"
        android:background="@color/white" />

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/city_manager"/>

</LinearLayout>

added_city.xml页面表示要展示的一个个城市数据:

city
city

源码:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="55dp"
    android:textSize="20sp"
    android:layout_marginLeft="40dp"
    android:layout_marginRight="40dp"
    android:layout_marginTop="5dp"
    android:background="@drawable/blackground"
    android:gravity="center_vertical"
    android:paddingLeft="10dp"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="220dp"
            android:layout_height="wrap_content"
            android:id="@+id/city_city"
            android:layout_marginLeft="10dp"
            android:textSize="22dp"
            android:textColor="@color/white"
            android:text="西安" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="16°C"
            android:textSize="24dp"
            android:textColor="@color/white"
            android:id="@+id/city_tem"/>


    </LinearLayout>

</LinearLayout>

最终从数据库拿到信息呈现出的效果:

result
result

适配器AddCityAdapter

界面布局设计完成接下来就是适配器AddCityAdapter public class AddCityAdapter extends RecyclerView.Adapter<AddCityAdapter.AddViewHolder>

适配器就是决定在此城市管理页面的RecyclerView中展示哪个页面,跟之前一样,前几篇文章都有篇幅概括,基本的一些操作就是, 添加一个构造方法,

代码语言:javascript
复制
private Context mContext;
   private List<CityBean> mCityBeans;

   public AddCityAdapter(Context context, List<CityBean> cityBeans) {
       mContext = context;
       this.mCityBeans = cityBeans;
   }

创建一个类class AddViewHolder extends RecyclerView.ViewHolder来绑定控件,此时在城市管理页面要求点击某个城市,需要传值到MainActivity,并获取指定点击城市的天气信息 所以适配器中添加一个点击事件,首先在适配器中添加接口

代码语言:javascript
复制
public interface OnItemClickListener {

       /**
        * 当RecyclerView某个被点击的时候回调
        * @param view 点击item的视图
        * @param position 点击得到的数据,参数自定义
        */
       public void onItemClick(View view, int position);

   }

   private OnItemClickListener onItemClickListener;

   public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
       this.onItemClickListener = onItemClickListener;
   }

然后在适配器中的类AddViewHolder中绑定点击事件

代码语言:javascript
复制
class AddViewHolder extends RecyclerView.ViewHolder {

       TextView cityCity,cityTem;//城市名,温度

       public AddViewHolder(@NonNull View itemView) {
           super(itemView);
           //绑定控件
           cityCity=itemView.findViewById(R.id.city_city);
           cityTem = itemView.findViewById(R.id.city_tem);
           //绑定点击事件
           itemView.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                   if (onItemClickListener!=null) {
                       onItemClickListener.onItemClick(view,getLayoutPosition());
                   }
               }
           });
       }
   }

然后就是一如既往的重写三个方法

代码语言:javascript
复制
@NonNull
   @Override
   public AddViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
   	//绑定控件,哪个页面展示在RecyclerView中,R.layout.added_city
       View view = LayoutInflater.from(mContext).inflate(R.layout.added_city, parent, false);
       AddViewHolder cityViewHolder = new AddViewHolder(view);
       return cityViewHolder;
   }

   @Override
   public void onBindViewHolder(@NonNull AddViewHolder holder, int position) {
       CityBean cityBean = mCityBeans.get(position);
       //控件传值
       holder.cityCity.setText(cityBean.getName());
       holder.cityTem.setText(cityBean.getTem());
   }

   @Override
   public int getItemCount() {
       return (mCityBeans == null) ? 0 : mCityBeans.size();
   }

适配器AddCityAdapter源码:

代码语言:javascript
复制
public class AddCityAdapter extends RecyclerView.Adapter<AddCityAdapter.AddViewHolder>{

    private Context mContext;
    private List<CityBean> mCityBeans;

    public AddCityAdapter(Context context, List<CityBean> cityBeans) {
        mContext = context;
        this.mCityBeans = cityBeans;
    }

    @NonNull
    @Override
    public AddViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.added_city, parent, false);
        AddViewHolder cityViewHolder = new AddViewHolder(view);
        return cityViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull AddViewHolder holder, int position) {
        CityBean cityBean = mCityBeans.get(position);

        holder.cityCity.setText(cityBean.getName());
        holder.cityTem.setText(cityBean.getTem());
    }

    @Override
    public int getItemCount() {
        return (mCityBeans == null) ? 0 : mCityBeans.size();
    }

    class AddViewHolder extends RecyclerView.ViewHolder {

        TextView cityCity,cityTem;

        public AddViewHolder(@NonNull View itemView) {
            super(itemView);

            cityCity=itemView.findViewById(R.id.city_city);
            cityTem = itemView.findViewById(R.id.city_tem);

            //绑定点击事件
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (onItemClickListener!=null) {
                        onItemClickListener.onItemClick(view,getLayoutPosition());
                    }
                }
            });
        }
    }
    /**
     * 点击响应事件
     */
    public interface OnItemClickListener {

        /**
         * 当RecyclerView某个被点击的时候回调
         * @param view 点击item的视图
         * @param position 点击得到的数据
         */
        public void onItemClick(View view, int position);

    }

    private OnItemClickListener onItemClickListener;

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }
}

操作数据库

然后进行数据库工具的构建,要操作数据库,一般的方法得需要实体类吧,接着就是城市实体类的封装,当获取当前定位天气信息时,把此数据类保存到数据库 所以先构建城市实体类CityBean

代码语言:javascript
复制
public class CityBean {

    private String name;//城市名称
    private String[] area;//县/区
    private String tem;//温度
    private String updateTime;//更新时间

//构造方法自定义,主要看数据库操作和new时传值
    public CityBean() {
    }

    public CityBean(String name) {
        this.name = name;
    }

    public CityBean(String name, String tem, String updateTime) {
        this.name = name;
        this.tem = tem;
        this.updateTime = updateTime;
    }
//get和set、toString注释
    
}
db
db

接着就是数据库的CityDatabaseConfig,有数据库名,表名的信息,以防操作数据库写错名称,故写在此配置下:

代码语言:javascript
复制
public class CityDatabaseConfig {
    //数据库的名字
    public static final String DATABASE_NAME = "cityDb";
    //表名
    public static final String TABLE_NAME = "city_weather";
}

然后是CityDbHelper继承自SQLiteOpenHelper

代码语言:javascript
复制
public class CityDbHelper extends SQLiteOpenHelper {

    public CityDbHelper(Context context) {
    	//创建数据库CityDatabaseConfig.DATABASE_NAME
        super(context, CityDatabaseConfig.DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    //创建表,字段(cityName text,tem text,updateTime text)
        String sql = "create table if not exists "+CityDatabaseConfig.TABLE_NAME+"(cityName text,tem text,updateTime text)";
        db.execSQL(sql);
        Log.i(CityDatabaseConfig.DATABASE_NAME,"created success!!");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        Log.i(CityDatabaseConfig.DATABASE_NAME,"updated success!!");
    }

}

接着是数据库一些操作的工具,里面写一些能用到的方法,自行扩展即可

代码语言:javascript
复制
public class DBUtils {

    private Context context;
    private CityDbHelper helper;

    /**
     * 单例模式
     * @param context
     */
    public DBUtils(Context context) {
        this.context = context;
        helper = new CityDbHelper(context) {
        };
    }

    /**
     * 向表中插入
     *
     * @param
     * @return
     */
    public boolean insertData(String cityName,String tem,String updateTime) {
        SQLiteDatabase db = helper.getReadableDatabase();
        ContentValues values = new ContentValues();

        values.put("cityName", cityName);
        values.put("tem", tem);
        values.put("updateTime", updateTime);
        long insert = db.insert(CityDatabaseConfig.TABLE_NAME, null, values);
        if (insert > 0) {
            return true;
        }
        return false;
    }

//根据城市名称更新数据
    public boolean updateByName(String cityName,String tem,String updateTime){
        SQLiteDatabase db = helper.getReadableDatabase();
        ContentValues values = new ContentValues();

        values.put("cityName", cityName);
        values.put("tem", tem);
        values.put("updateTime", updateTime);
        long update = db.update(CityDatabaseConfig.TABLE_NAME,values,"cityName=?", new String[]{cityName});

        if (update>0){
            return true;
        }return false;
    }

    /**
     * 查询全部的信息
     *
     * @return
     */
    public List<CityBean> getAllCity() {
        List<CityBean> list = new ArrayList<>();
        SQLiteDatabase db = helper.getReadableDatabase();
        Cursor cursor = db.rawQuery("select * from " + CityDatabaseConfig.TABLE_NAME, null);
        if (cursor != null && cursor.getCount() > 0) {
            while (cursor.moveToNext()) {

                String cityName = cursor.getString(0);
                String tem = cursor.getString(1);
                String updateTime = cursor.getString(2);

                CityBean cityBean = new CityBean(cityName,tem,updateTime);
                list.add(cityBean);
            }
        }
        return list;
    }

    /**
     * 根据城市名查询一条信息
     */
    public CityBean getCityByName(String cityName) {
        CityBean cityBean = new CityBean();
        SQLiteDatabase db = helper.getReadableDatabase();
        Cursor cursor = db.rawQuery("select * from " + CityDatabaseConfig.TABLE_NAME + " where cityName=?", new String[]{cityName});
        if (cursor != null && cursor.getCount() > 0) {
            while (cursor.moveToFirst()) {

                String cityNameResult = cursor.getString(0);
                cityBean.setName(cityName);
                break;
            }

        }
        return cityBean;

    }

	/**
     * 根据城市名删除一条数据
     * @param cityName
     * @return
     */
    public boolean delCityByName(String cityName){
        SQLiteDatabase db = helper.getReadableDatabase();

        long delRow = db.delete(CityDatabaseConfig.TABLE_NAME, "cityName=?", new String[]{cityName});
        if (delRow > 0) {
            return true;
        }
        return false;

    }

}

跳转页面,展示数据

一些基本的方法写好后就是MainActivity.java文件,用Intent跳转到城市管理界面,注意先引入数据库操作工具

代码语言:javascript
复制
DBUtils dbUtils = new DBUtils(MainActivity.this);

设置右上角图标的点击事件,此小圆点图标绑定为ivMore

tub
tub
代码语言:javascript
复制
	ivMore.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (null == dbUtils.getCityByName(tvCity.getText().toString()).getName()) {
                    //数据库不存在此城市就插入
                    dbUtils.insertData(tvCity.getText().toString(),tvTem.getText().toString(),tvTime.getText().toString());
                }
                else {
                    //存在就更新
                    dbUtils.updateByName(tvCity.getText().toString(),tvTem.getText().toString(),tvTime.getText().toString());
//                dbUtils.insertData("北京","30°C","2022-06-19 21:23:35");测试用
//                dbUtils.delCityByName("商丘");测试用
                    List<CityBean> list = dbUtils.getAllCity();
                    Log.d("getAllCity", "allList<CityBean>>>>》》》" + list.toString());

                    ToastUtil.showShortToast(MainActivity.this, "当前位置:" + tvCity.getText());
                    Intent intent = new Intent(MainActivity.this, CityManagerActivity.class);
                    Log.d("getNowCity", "nowCity<CityBean>>>>》》》" + tvCity.getText());
//                要求跳转页面传值回来,requestCode:200;
                    startActivityForResult(intent, 200);
                }
            }
        });

跳转到城市管理页面,添加activity.java文件,命名CityManagerActivity

代码语言:javascript
复制
public class CityManagerActivity extends AppCompatActivity {

    private AddCityAdapter addCityAdapter;//适配器
    private RecyclerView rvAddedCity;

    private List<CityBean> cityDbBeanList;
    DBUtils dbUtils= new DBUtils(CityManagerActivity.this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.city_manager);

        initView();
    }


    public void initView() {

        rvAddedCity = findViewById(R.id.city_manager);

        cityDbBeanList = dbUtils.getAllCity();
        Log.d("cityList",">>>>>数据库中的数据》》》》》》"+cityDbBeanList);
        addCityAdapter = new AddCityAdapter(CityManagerActivity.this,cityDbBeanList);
        rvAddedCity.setAdapter(addCityAdapter);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        rvAddedCity.setLayoutManager(layoutManager);
		//设置点击事件
        addCityAdapter.setOnItemClickListener(new AddCityAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
//                ToastUtil.showShotToast(CityManagerActivity.this, cityDbBeanList.get(position).getName());
                Intent intent = new Intent(CityManagerActivity.this,MainActivity.class);
                intent.putExtra("selectedCity",cityDbBeanList.get(position).getName());
				//返回MainActivity页面并传值setResult(200,intent);设置resultCode:200;
                setResult(200,intent);
                finish();

//                ToastUtil.showShotToast(CityManagerActivity.this,"finish");
            }
        });
    }

}

然后既然是要求页面返回传值,MainActivity就要重写方法onActivityResult接受传来的值

代码语言:javascript
复制
@Override
   protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
       super.onActivityResult(requestCode, resultCode, data);
       if (requestCode == 200 && resultCode == 200) {
       //getString拿到传来的值
           String dt = data.getExtras().getString("selectedCity");
           tvCity.setText(dt);
           nowCity=dt;
           //重新从api根据传来的城市名称获取天气
           getWeather(nowCity);
           ToastUtil.showLongToast(this,dt+"天气更新😘~");
       }
   }

自此一部分功能就实现了,跳转城市管理页面,展示城市,指定城市展示天气信息,

数据库操作实现了:

  1. 拿到数据库所有城市信息、
  2. 插入一条数据、
  3. 根据城市名称更新数据、
  4. 删除一条数据待完成,,自行拓展,只要工具类删除方法写对,无非就是添加个事件调用删除方法

更精细化的搜索城市,主动根据搜索到的城市添加城市到数据库,后篇文章会逐渐完善,此篇文章主要是数据库的一些操作和适配器添加点击事件,订阅此栏可同步获取项目搭建过程😘😘

==源码地址==:Gitee

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 需求🏷️
  • 涉及内容
  • 适配器AddCityAdapter
  • 操作数据库
  • 跳转页面,展示数据
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档