文章目录 前言一、SQLiteOpenHelper1. SQLite数据库介绍2. SQLiteOpenHelper类介绍 二、代码分析1. 创建 HistoryManager 对象HistoryManager 构造方法DBHelper 类HistoryManager. trimHistory 2. 保存扫码结果条目HistoryManager.addHistoryItem 3. 点击“历史记录”按钮CaptureActivity.onActivityResult 总结
前言
在前面的博客中,我们已经分析了 Zxing 安卓端的几大主要功能。本次博客将重点分析历史记录功能的相关代码,同时学习 Android 数据库存储的相关知识
一、SQLiteOpenHelper 1. SQLite数据库介绍
SQLite是Android内置的一个小型、关系型、属于文本型的数据库。 Android提供了对 SQLite数据库的完全支持,应用程序中的任何类都可以通过名称来访问任何的数据库,但是应用程序之外的就不能访问。
Android中,通过SQLiteOpenHelper类来实现对SQLite数据库的操作。
2. SQLiteOpenHelper类介绍 定义:SQLiteOpenHelper是一个辅助类作用:管理数据库(创建、增、删、改、查) 以及版本的控制使用过程:通过创建子类继承SQLiteOpenHelper类,实现它的一些方法来对数据库进行操作SQLiteOpenHelper类的数据库操作方法介绍如下:以上只是对 Android 数据库操作知识的基本介绍,具体使用将结合 Zxing 项目的代码来进行分析。
二、代码分析
在 Zxing 项目的主页面 CaptureActivity 中, 应用到历史记录的主要有以下几个地方:
1. 创建 HistoryManager 对象在 CaptureActivity 的生命周期函数 onResume 中,就首先创建了一个 HistoryManager 对象,并且调用了 trimHistory 方法
historyManager = new HistoryManager(this); historyManager.trimHistory(); HistoryManager 构造方法 public HistoryManager(Activity activity) { this.activity = activity; // 根据 activity 获取程序设置 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); // 是否 enable 历史记录 enableHistory = prefs.getBoolean(PreferencesActivity.KEY_ENABLE_HISTORY, true); }可知在 HistoryManager 的构造方法中,传入了 CaptureActivity 的实例对象,同时获取程序设置,来判断是否允许使用历史记录功能
DBHelper 类在 trimHistory 方法中,就涉及到了 SQLite 数据库的处理。 而可以操作 SQLite 数据库的 SQLiteOpenHelper 是一个抽象类,因此需要首先自己定义一个类对其进行继承,Zxing 项目在 history 包中定义了 DBHelper 类来继承 SQLiteOpenHelper
DBHelper 构造方法
//在SQLiteOpenHelper的子类当中,必须有该构造函数 // 参数分别为:上下文对象、数据库名称、CursorFactory、数据库版本号 DBHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); }onCreate 方法 onCreate 方法在数据库第一次创建时被调用,这里在创建数据库的同时,也创建了一个表。可知表中存储了一次扫码结果的条目编号、文字、编码格式、展现内容、时间戳和细节信息几个字段。
@Override public void onCreate(SQLiteDatabase sqLiteDatabase) { // 执行SQL语句,创建一个表 sqLiteDatabase.execSQL( "CREATE TABLE " + TABLE_NAME + " (" + ID_COL + " INTEGER PRIMARY KEY, " + TEXT_COL + " TEXT, " + FORMAT_COL + " TEXT, " + DISPLAY_COL + " TEXT, " + TIMESTAMP_COL + " INTEGER, " + DETAILS_COL + " TEXT);"); }onUpgrade 方法 当打开数据库时传入的版本号与当前的版本号不同时会调用该方法,可知这里首先删除了已有的数据,并且重新调用了 onCreate 方法来完成升级
//系统发现现有数据库版本不同,即会调用onUpgrade()方法 @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) { sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(sqLiteDatabase); } HistoryManager. trimHistory public void trimHistory() { // 创建 DBHelper 实例对象 SQLiteOpenHelper helper = new DBHelper(activity); // 创建(打开)并获取数据库 try (SQLiteDatabase db = helper.getWritableDatabase(); // 查询数据库中的条目 Cursor cursor = db.query(DBHelper.TABLE_NAME, ID_COL_PROJECTION, null, null, null, null, DBHelper.TIMESTAMP_COL + " DESC")) { // 移动到 Zxing 项目所允许存留的最大条目数处 cursor.move(MAX_ITEMS); // 超过 MAX_ITEMS 部分的历史记录应当删除 while (cursor.moveToNext()) { String id = cursor.getString(0); Log.i(TAG, "Deleting scan history ID " + id); db.delete(DBHelper.TABLE_NAME, DBHelper.ID_COL + '=' + id, null); } } catch (SQLException sqle) { Log.w(TAG, sqle); } }可知在 HistoryManager 的 trimHistory 方法中,主要完成的任务就是清理数据库中过多的历史记录条目。
这里注意一下获取数据库对象的流程:
首先创建一个 SQLiteOpenHelper 对象然后调用该对象的 getWritableDatabase 或 getReadableDatabase 方法来获得SQLiteDatabase 对象在 getWritableDatabase 和 getReadableDatabase 方法中,会判断指定的数据库是否存在,不存在则调用 SQLiteOpenHelper.onCreate 方法来创建数据库 2. 保存扫码结果条目在前面的博客中,我们已经分析了整个扫码处理的流程,其中 CaptureActivity 的 handleDecode 方法,就对扫码得到的结果进行了各种处理,有代码:
historyManager.addHistoryItem(rawResult, resultHandler);下面我们看一下 HistoryManager 的这个方法
HistoryManager.addHistoryItem public void addHistoryItem(Result result, ResultHandler handler) { // 如果设置了不保留历史记录,那么直接返回 if (!activity.getIntent().getBooleanExtra(Intents.Scan.SAVE_HISTORY, true) || handler.areContentsSecure() || !enableHistory) { return; } // 获取程序设置,判断是否允许保留重复的扫码条目。如果不允许则调用 deletePrevious 方法,将重复的旧的条目删除 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); if (!prefs.getBoolean(PreferencesActivity.KEY_REMEMBER_DUPLICATES, false)) { deletePrevious(result.getText()); } // 创建插入的字段值 ContentValues values = new ContentValues(); values.put(DBHelper.TEXT_COL, result.getText()); values.put(DBHelper.FORMAT_COL, result.getBarcodeFormat().toString()); values.put(DBHelper.DISPLAY_COL, handler.getDisplayContents().toString()); values.put(DBHelper.TIMESTAMP_COL, System.currentTimeMillis()); // 创建 DBHelper 对象 SQLiteOpenHelper helper = new DBHelper(activity); try (SQLiteDatabase db = helper.getWritableDatabase()) { // 将新条目加入数据库 db.insert(DBHelper.TABLE_NAME, DBHelper.TIMESTAMP_COL, values); } catch (SQLException sqle) { Log.w(TAG, sqle); } }这样就成功地保存了扫码结果到数据库
3. 点击“历史记录”按钮这里类似前面分析过的 ShareActivity 代码部分的操作 在 CaptureAcitivity 的 onOptionsItemSelected 方法中,也对点击“历史记录”按钮进行了响应
case R.id.menu_history: intent.setClassName(this, HistoryActivity.class.getName()); startActivityForResult(intent, HISTORY_REQUEST_CODE); break;其使用了意图跳转方法,也就是说在这里会跳转到 HistoryActivity 的界面,而在 HistoryActivity 中处理完毕后,会回调到 CaptureActivity 的 onActivityResult 方法来对结果进行处理 基本流程如下: 在第十篇博客中,我们介绍了 Android Adapter 体系,Adapter 完成对数据和界面的适配。一些不能直接赋值到界面上的数据类型,就需要靠适配器来展示到页面
HistoryActivity 页面中的条目就是通过继承了 ArrayAdapter 的 HistoryItemAdapter 来完成的适配显示在页面初始构造时,除了加载布局文件、设置适配器,还调用了 HistoryManager 的 buildHistoryItems() 方法,来获取所有的历史记录最终在点击历史记录条目时,跳转回了 CaptureActivity 来处理 CaptureActivity.onActivityResult public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (resultCode == RESULT_OK && requestCode == HISTORY_REQUEST_CODE && historyManager != null) { // 获取点击的历史记录条目号 int itemNumber = intent.getIntExtra(Intents.History.ITEM_NUMBER, -1); if (itemNumber >= 0) { // 根据 HistoryManager 找到对应在数据库中的内容 HistoryItem historyItem = historyManager.buildHistoryItem(itemNumber); // 显示返回结果(因为数据库中没有存储 Bitmap,这里无法显示二维码图片) decodeOrStoreSavedBitmap(null, historyItem.getResult()); } } }可知在方法中,根据返回点击的历史条目号,来查询数据库找到了对应的存储内容,而后调用 decodeOrStoreSavedBitmap 方法显示返回结果 而在 decodeOrStoreSavedBitmap 中有:
Message message = Message.obtain(handler, R.id.decode_succeeded, savedResultToShow); handler.sendMessage(message);这里向 CaptureActivityHandler 发送消息来处理,之后的流程与之前在博客(六)中分析的类似,在 CaptureActivityHandler.handleMessage 中处理消息,再调用 CaptureActivity 的 handleMessage 方法,在页面显示结果。 这里显示的是数据库中存储的内容,没有二维码图片
总结
通过本次代码分析,理清了在 Zxing 项目中历史记录的处理流程,同时学习了 Android 数据存储的相关知识
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。 |
标签: #2021SCSDUSC #代码分析 #Android #数据库存储的相关知识