Android使用SQLiteOpenHelper实现离线浏览
相信在Android開發(fā)中,很多APP都會用到數(shù)據(jù)庫來保存數(shù)據(jù),今天我們來討論一下它其中用法,用數(shù)據(jù)庫實現(xiàn)離線瀏覽。數(shù)據(jù)庫類型很多,Android默認是使用SQLite。
首先我們來看一下界面
很簡單,經(jīng)典的圖文混排。
要想實現(xiàn)APP離線瀏覽,我們需要:
- 創(chuàng)建一個類繼承SQLiteOpenHelper(該類幫我們封裝好了很多數(shù)據(jù)庫操作)
- 將功能抽象出來
- 創(chuàng)建數(shù)據(jù)庫管理類
- 使用我們創(chuàng)建的數(shù)據(jù)庫來實現(xiàn)離線瀏覽。
首先我們根據(jù)模型類來創(chuàng)建SQLiteOpenHelper
模型類
public class News {private int id;private String title;private String postdate;private String editor;private String icon;public News(int id, String title, String postdate, String editor, String icon) {this.id = id;this.title = title;this.postdate = postdate;this.editor = editor;this.icon = icon;}// getter and setter ... } public class NewsSQLiteOpenHelper extends SQLiteOpenHelper {// 數(shù)據(jù)庫名private static final String NAME = "learn.db";// 數(shù)據(jù)庫版本private static final int VERSION = 1;// 建表語句private static final String CREATE_NEWS = "create table if not exists news(" +"_id integer primary key," +"title text," +// 這個時間字段只是單純的為了后面查詢時好排序"time integer," +"icon text," +"editor text," +"postdate text)";public NewsSQLiteOpenHelper(Context context) {super(context, NAME, null, VERSION);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(CREATE_NEWS);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {} }這里主要要實現(xiàn)的方法是onCreate,在里面完成我們的初始化建表工作,構(gòu)造函數(shù)需要傳入的四個參數(shù)分別為:上下文、數(shù)據(jù)庫名、游標(biāo)工廠(默認為null)、版本號。onUpgrade方法 只會在數(shù)據(jù)庫更新才會調(diào)用。這里我們不會用到。
將功能抽象出來
public interface INewsDB {List<News> getAllNews();void deleteAllNews();News getNewsById(int id);void insertAllNews(List<News> newsList);void insertNews(News news);}這里首先說一下為什么要創(chuàng)建這么一個接口,很簡單,解耦合,以后維護修改的時候方便。抽象出來的這些功能都是我們后面將用到的,都是基本的增刪改查操作。
創(chuàng)建數(shù)據(jù)庫管理類(重點)
public class NewsDBManager implements INewsDB {private static NewsDBManager sManager;private NewsSQLiteOpenHelper mHelper;private NewsDBManager(Context context) {mHelper = new NewsSQLiteOpenHelper(context);}public static NewsDBManager getInstance(Context context) {if (sManager == null) {synchronized (NewsDBManager.class) {if (sManager == null) {sManager = new NewsDBManager(context);}}}return sManager;}/*** 查詢所有新聞** @return*/@Overridepublic List<News> getAllNews() {SQLiteDatabase db = mHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select * from news order by time ASC", null);List<News> newsList = new ArrayList<>();while (cursor.moveToNext()) {int id = cursor.getInt(cursor.getColumnIndex("_id"));String title = cursor.getString(cursor.getColumnIndex("title"));String icon = cursor.getString(cursor.getColumnIndex("icon"));String editor = cursor.getString(cursor.getColumnIndex("editor"));String postdate = cursor.getString(cursor.getColumnIndex("postdate"));News news = new News(id, title, postdate, editor, icon);newsList.add(news);}mHelper.close();return newsList;}/*** 刪除所有新聞*/@Overridepublic void deleteAllNews() {SQLiteDatabase db = mHelper.getWritableDatabase();db.execSQL("delete from news");mHelper.close();}/*** 通過給定的id獲取新聞** @param id* @return*/@Overridepublic News getNewsById(int id) {SQLiteDatabase db = mHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select * from news where _id = ?", new String[]{String.valueOf(id)});cursor.moveToNext();String title = cursor.getString(cursor.getColumnIndex("title"));String icon = cursor.getString(cursor.getColumnIndex("icon"));String editor = cursor.getString(cursor.getColumnIndex("editor"));String postdate = cursor.getString(cursor.getColumnIndex("postdate"));News news = new News(id, title, postdate, editor, icon);mHelper.close();return news;}@Overridepublic void insertAllNews(List<News> newsList) {for (News news : newsList) {insertNews(news);}}@Overridepublic void insertNews(News news) {SQLiteDatabase db = mHelper.getWritableDatabase();db.execSQL("insert into news(_id,title,time,icon,editor,postdate) values(?,?,?,?,?,?)", new Object[]{news.getId(), news.getTitle(), System.currentTimeMillis(), news.getIcon(), news.getEditor(), news.getPostdate()});} }解析一下代碼:這里我們創(chuàng)建一個News數(shù)據(jù)庫管理類,專門進行數(shù)據(jù)庫的增刪改查操作,實現(xiàn)INewsDB抽象的功能。增刪改查的代碼就不多解釋了,這里注意一下delete操作,Android的delete有一個蜜汁bug,本來數(shù)據(jù)庫的刪除操作應(yīng)該是delete * from table,但是這個 * 無法通過編譯,所以只能delete from table。
實際運用
好了,終于到最后一步了,有木有很激動。
private void initView() {mNewsRv = ((RecyclerView) findViewById(R.id.rv_news));mLoading = findViewById(R.id.pb_loading);LinearLayoutManager layout = new LinearLayoutManager(this);mNewsRv.setLayoutManager(layout);mAdapter = new NewsAdapter(this, null);mNewsRv.setAdapter(mAdapter);mLoading.setVisibility(View.VISIBLE);// 加載數(shù)據(jù)的時候先檢測網(wǎng)絡(luò)if (NetworkUtils.checkNetworkState(this)) {Log.d(TAG, "initView: 從網(wǎng)絡(luò)獲取數(shù)據(jù)");getDataFromInternet();} else {Log.d(TAG, "initView: 從數(shù)據(jù)庫獲取數(shù)據(jù)");getDataFromDB();}}private void getDataFromInternet() {HttpUtils.getAsynString(Urls.URL_NEWS_ITEM_SOFTWARE, new HttpUtils.ResultCallback() {@Overridepublic void onFailure(Exception e) {Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();}@Overridepublic void onFinish(String result) {Gson gson = new Gson();List<News> data = gson.fromJson(result, new TypeToken<List<News>>() {}.getType());mAdapter.update(data);NewsDBManager manager = NewsDBManager.getInstance(MainActivity.this);// 刪除舊數(shù)據(jù),保存最新數(shù)據(jù)manager.deleteAllNews();manager.insertAllNews(data);mLoading.setVisibility(View.GONE);}});}private void getDataFromDB() {NewsDBManager manager = NewsDBManager.getInstance(this);List<News> data = manager.getAllNews();if (data.size() > 0) {mAdapter.update(data);}mLoading.setVisibility(View.GONE);}最后再來看看調(diào)試結(jié)果
根據(jù)log可知,沒網(wǎng)時,最后走了getDataFromDB(),界面數(shù)據(jù)也與有網(wǎng)時一樣正常顯示出來。
項目源碼
總結(jié)
以上是生活随笔為你收集整理的Android使用SQLiteOpenHelper实现离线浏览的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Web安全-URL跳转与钓鱼
- 下一篇: 揭秘直销软件系统PHP源码开发价格与奖金