妹子图APP(四)—— SQLite保存数据实现离线图片查看

    xiaoxiao2021-03-25  134

    接上文: 妹子图APP(三)—— RecyclerView的Item点击事件和图片保存至本地 前面实现了加载网络图片并保存至本地,但无法实现离线查看已缓存的图片,现在需要实现离线查看缓存的图片 Glie在加载图片时已经实现三级缓存了,所以现在只需要使用SQLite将图片地址保存,无网络时加载SQLite数据即可 1.判断有无网络连接 新建一个工具类,判断是否联网 public class Network { //除了判断是否有网络,还写工具方法判断网络为什么类型 2G、3G、4G、wifi此处忽略 public static boolean checkNetworkState(Context context) { //得到网络信息 ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = manager.getActiveNetworkInfo(); if (info != null && info.isAvailable()) { //当前的网络是连接的 return true; } else { return false; } } } 记得加上权限 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> 2.SQLite数据库的操作 2.1创建一个类继承SQLiteOpenHelper实现对数据库进行版本管理 public class MySqliteOpenHelper extends SQLiteOpenHelper{ //数据库名称 private static final String name = "girl.db"; //数据库版本 private static final int version = 1; public static final String tableNmae = "girls"; public MySqliteOpenHelper(Context context) { //第三个参数CursorFactory指定在执行查询时获得一个游标实例的工厂类,设置为null,代表使用系统默认的工厂类 super(context, name, null, version); } //用于初次使用软件时生成数据库表 @Override public void onCreate(SQLiteDatabase db) { /** * 图片的所以属性 * title : 清纯气质韩国美女沙滩写真 * picUrl : http://t1.du114.com/uploads/151201/10-1512011521415N.jpg * description : 114美女 * ctime : 2016-03-06 14:11 * url : http://www.du114.com/qingchun/66307.html */ //执行SQL语句 创建表 此处注意table后的空格 不然语句就成了tablegirls而报错 db.execSQL("create table " + tableNmae + "(id integer primary key autoincrement,title text," + "picUrl text,description text,ctime text,url text)"); } //用于升级软件时更新数据库表结构 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } 2.2使用SQLiteDatabase操作SQLite数据库 public class GirlImageDao { MySqliteOpenHelper mHelper; public GirlImageDao(Context context) { mHelper = new MySqliteOpenHelper(context); } //向数据库中添加数据 即NewslistBean对象 public void addGirl(GirlsBean.ShowapiResBodyBean.NewslistBean bean) { //Android提供了一个名为SQLiteDatabase的类,该类封装了一些操作数据库的API, //该类可以对数据进行添加(Create)、查询(Retrieve)、更新(Update)和删除(Delete)操作(简称为CRUD) SQLiteDatabase db = mHelper.getReadableDatabase(); ContentValues values = new ContentValues(); //存入图片的Url地址 values.put("title", bean.getTitle()); values.put("picUrl", bean.getPicUrl()); values.put("description", bean.getDescription()); values.put("ctime", bean.getCtime()); values.put("url", bean.getUrl()); //向表中插入数据 db.insert(MySqliteOpenHelper.tableNmae, null, values); db.close(); } //for循环遍历girl集合,将每个图片地址挨个插入数据库 public void addGirlList(List<GirlsBean.ShowapiResBodyBean.NewslistBean> list) { for (GirlsBean.ShowapiResBodyBean.NewslistBean bean : list) { addGirl(bean); } } //查询SQLite取出数据存入集合 public List<GirlsBean.ShowapiResBodyBean.NewslistBean> queryAllGirls() { List<GirlsBean.ShowapiResBodyBean.NewslistBean> list = new ArrayList<>(); SQLiteDatabase db = mHelper.getReadableDatabase(); //Cursor是结果集游标,用于对结果集进行随机访问,Cursor与JDBC中的ResultSet作用很相似。 Cursor cursor = db.query(MySqliteOpenHelper.tableNmae,null,null,null,null,null,null); //moveToNext()方法可以将游标从当前行移到下一行,如果移过了结果集的最后一行,返回结果为false,否则为true while (cursor.moveToNext()) { GirlsBean.ShowapiResBodyBean.NewslistBean bean = new GirlsBean.ShowapiResBodyBean.NewslistBean(); //通过key 得到图片地址值value bean.setTitle(cursor.getString(cursor.getColumnIndex("title"))); bean.setPicUrl(cursor.getString(cursor.getColumnIndex("picUrl"))); bean.setDescription(cursor.getString(cursor.getColumnIndex("description"))); bean.setCtime(cursor.getString(cursor.getColumnIndex("ctime"))); bean.setUrl(cursor.getString(cursor.getColumnIndex("url"))); //将NewslistBean对象加入集合 list.add(bean); } return list; } } 3.MainActivity中调用数据库操作方法 3.1当从网络请求数据成功后将数据存入数据库,即在网络请求回掉方法OnFish()中调用存数据方法 @Override public void onFinish(GirlsBean data) { // //得到适配器 // mAdapter = new MyAdapter(this,data.getShowapi_res_body().getNewslist()); // //设置适配器 // mRecyclerView.setAdapter(mAdapter); // //RecyclerView设置Item的点击事件 // mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() { // // @Override // public void onItemClick(String data) { // //跳转显示详细图片的Activity // Intent intent = new Intent(MainActivity.this, ImageShowActivity.class); // intent.putExtra("data",data); // startActivity(intent); // } // }); //存储数据 GirlImageDao dao = new GirlImageDao(this); dao.addGirlList(data.getShowapi_res_body().getNewslist()); } 3.2当无网络时读取数据库的数据进行加载本地缓存的图片 //是否联网 boolean isNetwork; isNetwork = Network.checkNetworkState(this); //判断是否联网,选择数据的加载方式 if (isNetwork) { //如果有网络,调用getGirlList方法请求数据 1数据请求时的页面 mRequest.getGirlList(this,1); } else { //没有网络则加载数据库的数据 GirlImageDao dao = new GirlImageDao(this); List<GirlsBean.ShowapiResBodyBean.NewslistBean> list = dao.queryAllGirls(); if (list.size() == 0) { //集合数据为0则第一次进入也未联网 Toast.makeText(this,"网络连接失败",Toast.LENGTH_SHORT).show(); } else { //数据库有数据时候 mAdapter = new MyAdapter(this,list); mRecyclerView.setAdapter(mAdapter); } } 在无网络并且数据库也无数据时,需要在Recycler滑动监听里加判断,不然因为没有图片会出空指针异常 3.3当无网络时进入app,然后又开启网络,此时app应该自动加载图片,并改变前面isNetwork的值,因此需要监听网络变化 采用广播的方式 创建一个类继承于BoradcastReceiver 重写方法 public class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //再次判断有无网络 isNetwork = Network.checkNetworkState(MainActivity.this); //如果有网络 if (isNetwork) { Toast.makeText(context,"已连接网络",Toast.LENGTH_SHORT).show(); //如果有网络,调用getGirlList方法请求数据 1数据请求时的页面 mRequest.getGirlList(MainActivity.this,1); }else { Toast.makeText(context,"已断开网络",Toast.LENGTH_SHORT).show(); } } } 然后注册广播,在Activity的onCreate()方法中调用 NetworkChangeReceiver networkChangeReceiver; //注册网络变化广播接收器 public void registerNetworkChangeReceiver() { IntentFilter intentFilter = new IntentFilter(); //广播的动作类型 intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); networkChangeReceiver = new NetworkChangeReceiver(); //注册 registerReceiver(networkChangeReceiver,intentFilter); } 别忘记取消广播 //动态注册的广播接收器都要取消 @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(networkChangeReceiver); } 以及在AndroidMaindest文件中注册 <receiver android:name=".activity.MainActivity$NetworkChangeReceiver"> <intent-filter> <!-- 监听的动作类型,这里是网络连接状态--> <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> </intent-filter> </receiver> 此图片加载Demo基本完成了,让我学了很多知识以及框架的简单用法,感觉加载新闻以及其他简单的数据也是这样步骤 初学者可以在 https://www.showapi.com/处申请很多数据,自己做简单的天气预报,图片加载,新闻客户端等等。 代码问题很多,因为是初学,想到哪里写到哪里。 加载数据的方法应该抽出来,在里面判断是否联网,取得数据,然后Recycler适配器直接调用数据即可。 详细代码: https://github.com/897532167/LoadNetworkPicture
    转载请注明原文地址: https://ju.6miu.com/read-20672.html

    最新回复(0)