Android--数据持久化之SQLite

简介:

前言

  对于一个应用程序而言,数据持久化是必不可少的,Android程序也不例外。这篇博客将介绍Android中关于SQLite的使用,SQLite是一种嵌入式的数据库引擎,专门适用于资源有限的设备上进行适量的数据存储,而Android就全面支持标准的SQLite数据库。在本片博客中,将说明SQLite数据库的创建以及维护,还有使用SQLite执行CRUD的两种方式,以及SQLite中事务的使用,最后都会使用示例讲解博客中所提到的概念性的内容。

SQLite

  Android对SQLite数据库,提供了完全的支持,而所有创建的SQLite数据库,仅限于当前应用访问,如果其他应用需要访问,则必须提供的Content Provider的支持,并且SQLite数据库会随着Android应用的卸载而被删除。SQLite是一个嵌入式的数据库引擎,最后是以文件的形式保存数据的。从本质上来看,SQLite的操作方式只是一种更为便捷的文件操作,当应用程序创建或打开一个SQLite数据库时,其实只是打开一个文件准备读写。因为SQLite仅适用于资源有限的小型设备,所以本身就不应该把大量数据存储在设备的SQLite数据库里,SQLite只适合存储一些小型的数据。

   为了使SQLite和其他数据库间的兼容性最大化,SQLite支持对列上类型进行“类型近似”,列的类型近似指的是存储在列上的数据进行推荐类型存储。所以虽然SQLite内部只支持NULL、INTEGER、REAL(浮点书)、TEXT(文本)和BLOB(大二进制对象)这五种数据类型,但实际上SQLite完全可以接受varchar(n)、char(n)、decimal(p,s)、date等类型数据,只不过SQLite会在运算或保存时将它们转换为上面五种数据类型中相应的类型。大多数数据库的引擎都是使用静态的、强类型的数据类型,数据的类型是由它的容器决定的,这个容器是指被存放的特定列。而SQLite使用的是动态类型,在SQLite中,值的数据类型跟值本身相关,而不是与它的容器相关,所以SQLite允许把各种类型的数据保存到任何类型字段中,开发者可以不用关心声明该字段说使用的数据类型。但是有一种情况例外,定义为INTEGER PRIMARY KEY的字段只能存储64位整数,当向这种字段保存除整数意外的其他类型的数据时,SQLite会产生错误。

SQLite数据库创建与维护

  从官方文档上了解到,在Android项目中,创建SQLite数据库推荐继承SQLiteOpenHelper类,然后重写其中的onCreate()方法,在onCreate()方法中,对执行数据库创建的SQL语句。而SQLiteOpenHelper不仅仅用于SQLite数据的创建,还可以对其进行维护,以及获得SQLiteDatabase这个数据库操作对象。

  SQLiteOpenHelper提供了两个构造器,用于传递当前上下文对象以及SQLite数据库版本信息,在SQLiteOpenHelper的继承类的构造函数中,会调用它,构造器的签名如下:

  • SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version).
  • SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactroy factory,int version,DatabaseErrorHandler errorHandler).

  上面的构造函数中,都是用于创建一个SQLite数据库,context为一个当前应用的上下文对象;name是数据库名称;factory是一个允许子类在查询时使用的游标,一般不用传Null;version是数据库版本号;errorHandler是一个接口,传递当数据库错误的时候,执行的补救方法。

  在SQLiteOpenHelper中,可以进行SQLite数据库的创建、维护、日志以及获取可读写的数据库对象,通过下面几个常用方法得到支持:

  • String getDatabaseName():获取数据库名。
  • SQLiteDatabase getReadableDatabase():创建或者打开一个可读的数据库对象。
  • SQLiteDatabase getWritableDatabase():创建或者打开一个可读/写的数据库对象。
  • abstract void onCreate(SQLiteDatabase db):当第一次调用SQLiteOpenHelper的时候执行,之后再次调用将不再执行,一般用于完成数据库初始化的工作。
  • void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion):当数据库版本号发生向上更新时,被执行。
  • void onDowngrade(SQLiteDatabase db,int oldVersion,int newVersion):当数据库版本号发生向下更新时,被执行。

  下面提供一个简单的SQLiteOpenHelper的继承类代码,用于创建数据库以及表结构:

复制代码
 1 package com.example.sqlitedbdemo.db;
 2 
 3 import android.content.Context;
 4 import android.database.sqlite.SQLiteDatabase;
 5 import android.database.sqlite.SQLiteOpenHelper;
 6 
 7 public class DbOpenHelper extends SQLiteOpenHelper {
 8     private static String name = "mydb.db";
 9     private static int version = 1;
10 
11     public DbOpenHelper(Context context) {
12         super(context, name, null, version);
13     }
14 
15     @Override
16     public void onCreate(SQLiteDatabase db) {
17         // 只能支持基本数据类型
18         String sql = "create table person(id integer primary key autoincrement,name varchar(64),address varchar(64))";
19         db.execSQL(sql);
20     }
21     @Override
22     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
23         // TODO Auto-generated method stub
24         String sql="alter table person add sex varchar(8)";
25         db.execSQL(sql);
26     }
27 }
复制代码

   Tips:当创建好SQLite数据库的之后,可以在/data/data/<package name>/databases目录下找到SQLite数据库文件。

执行CRUD操作

  当使用SQLiteOpenHelper的getReadableDatabase()或者getWritableDatabase()方法获取到SQLiteDatabase对象,就可以对这个数据库进行操作了。

  对于熟悉SQL语句的开发者而言,其实只需要使用两个方法,即可执行所有CRUD操作,以下方法提供多个重载方法:

  • void execSQL():通过SQL语句执行一条非查询语句。
  • Cursor rawQuery():通过SQL语句执行一条查询语句。

  下面以一个示例讲解一下单纯使用SQL语句实现CRUD操作:

  接口代码:

复制代码
 1 package com.examle.sqlitedbdemo.service;
 2 
 3 import java.util.List;
 4 import java.util.Map;
 5 
 6 public interface PersonService {
 7 
 8     public boolean addPerson(Object[] params);
 9     public boolean deletePerson(Object[] params);
10     public boolean updatePerson(Object[] params);
11     public Map<String, String> viewPerson(String[] selectionArgs);
12     public List<Map<String, String>> listPersonMaps(String[] selectionArgs);
13 }
复制代码

  接口的实现代码:

复制代码
  1 package com.examle.sqlitedbdemo.dao;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 
  8 import android.content.Context;
  9 import android.database.Cursor;
 10 import android.database.sqlite.SQLiteDatabase;
 11 
 12 import com.examle.sqlitedbdemo.service.PersonService;
 13 import com.example.sqlitedbdemo.db.DbOpenHelper;
 14 
 15 public class PersonDao implements PersonService {
 16     private DbOpenHelper helper = null;
 17 
 18     public PersonDao(Context context) {
 19         helper = new DbOpenHelper(context);
 20     }
 21 
 22     @Override
 23     public boolean addPerson(Object[] params) {
 24         boolean flag = false;
 25         SQLiteDatabase database = null;
 26         try {
 27             // insert一条数据
 28             String sql = "insert into person(name,address,sex) values(?,?,?)";
 29             database = helper.getWritableDatabase();
 30             // 执行SQL
 31             database.execSQL(sql, params);
 32             flag = true;
 33         } catch (Exception e) {
 34             e.printStackTrace();
 35         } finally {
 36             if (database != null) {
 37                 // finally中关闭数据库
 38                 database.close();
 39             }
 40         }
 41         return flag;
 42     }
 43 
 44     @Override
 45     public boolean deletePerson(Object[] params) {
 46         boolean flag = false;
 47         SQLiteDatabase database = null;
 48         try {
 49             // 删除一条数据
 50             String sql = "delete from person where id=?";
 51             database = helper.getWritableDatabase();
 52             database.execSQL(sql, params);
 53             flag = true;
 54         } catch (Exception e) {
 55             e.printStackTrace();
 56         } finally {
 57             if (database != null) {
 58                 database.close();
 59             }
 60         }
 61         return flag;
 62     }
 63 
 64     @Override
 65     public boolean updatePerson(Object[] params) {
 66         boolean flag = false;
 67         SQLiteDatabase database = null;
 68         try {
 69             // 更新一条数据
 70             String sql = "update person set name=?,address=?,sex=? where id=?";
 71             database = helper.getWritableDatabase();
 72             // 执行SQL
 73             database.execSQL(sql, params);
 74             flag = true;
 75         } catch (Exception e) {
 76             e.printStackTrace();
 77         } finally {
 78             if (database != null) {
 79                 database.close();
 80             }
 81         }
 82         return flag;
 83     }
 84 
 85     @Override
 86     public Map<String, String> viewPerson(String[] selectionArgs) {
 87         Map<String, String> map = new HashMap<String, String>();
 88         SQLiteDatabase database = null;
 89         try {
 90             // 查询单条记录
 91             String sql = "select * from person where id=?";
 92             // 以只读的形式打开数据库
 93             database = helper.getReadableDatabase();
 94             // 执行SQL语句,返回一个游标
 95             Cursor cursor = database.rawQuery(sql, selectionArgs);
 96 
 97             int colums = cursor.getColumnCount();
 98             while (cursor.moveToNext()) {
 99                 for (int i = 0; i < colums; i++) {
100                     String cols_name = cursor.getColumnName(i);
101                     String cols_value = cursor.getString(cursor
102                             .getColumnIndex(cols_name));
103                     if (cols_value == null) {
104                         cols_value = "";
105                     }
106                     map.put(cols_name, cols_value);
107                 }
108             }
109         } catch (Exception e) {
110             e.printStackTrace();
111         } finally {
112             if (database != null) {
113                 database.close();
114             }
115         }
116         return map;
117     }
118 
119     @Override
120     public List<Map<String, String>> listPersonMaps(String[] selectionArgs) {
121         List<Map<String, String>> list = new ArrayList<Map<String, String>>();
122         String sql = "select * from person";
123         SQLiteDatabase database = null;
124         try {
125             database = helper.getReadableDatabase();
126             Cursor cursor = database.rawQuery(sql, selectionArgs);
127             int colums = cursor.getColumnCount();
128             while (cursor.moveToNext()) {
129                 Map<String, String> map = new HashMap<String, String>();
130                 for (int i = 0; i < colums; i++) {
131                     String cols_name = cursor.getColumnName(i);
132                     String cols_value = cursor.getString(cursor
133                             .getColumnIndex(cols_name));
134                     if (cols_value == null) {
135                         cols_value = "";
136                     }
137                     map.put(cols_name, cols_value);
138                 }
139                 list.add(map);
140             }
141         } catch (Exception e) {
142             e.printStackTrace();
143         } finally {
144             if (database != null) {
145                 database.close();
146             }
147         }
148         return list;
149     }
150 }
复制代码

   再写一个测试类测试这个数据操作类是否有效,Android下JUnit的配置参见另外一篇博客:Android--JUnit单元测试

复制代码
 1 package com.example.sqlitedbdemo.db;
 2 
 3 import java.util.List;
 4 import java.util.Map;
 5 
 6 import com.examle.sqlitedbdemo.dao.PersonDao;
 7 import com.examle.sqlitedbdemo.service.PersonService;
 8 
 9 import android.test.AndroidTestCase;
10 import android.util.Log;
11 
12 public class TestDb extends AndroidTestCase {
13     private final String TAG = "main";
14 
15     public TestDb() {
16         // TODO Auto-generated constructor stub
17     }
18 
19     public void createDB() {
20         DbOpenHelper helper = new DbOpenHelper(getContext());
21         helper.getWritableDatabase();
22     }
23 
24     public void insertDb() {
25         PersonService service = new PersonDao(getContext());
26         Object[] params1 = { "张龙", "beijing", "male" };
27         boolean flag = service.addPerson(params1);
28         Object[] params2 = { "赵虎", "shanghai", "male" };
29         flag = flag&&service.addPerson(params2);
30         Object[] params3 = { "王朝", "HK", "male" };
31         flag = flag&&service.addPerson(params3);
32         Object[] params4 = { "马汉", "beijing", "female" };
33         flag = flag&&service.addPerson(params4);
34         Log.i(TAG, "-----插入数据----->>" + flag);
35     }
36 
37     public void deleteDb() {
38         PersonService service = new PersonDao(getContext());
39         Object[] params = { 1 };
40         boolean flag = service.deletePerson(params);
41         Log.i(TAG, "-----删除数据----->>" + flag);
42     }
43 
44     public void updateDb() {
45         PersonService service=new PersonDao(getContext());
46         Object[] params = { "张三", "上海", "男","2" };
47         boolean flag=service.updatePerson(params);
48         Log.i(TAG, "---------->>" + flag);
49     }
50     
51     public void getDb(){
52         PersonService service=new PersonDao(getContext());
53         Map<String, String> map = service.viewPerson(new String[]{"2"});
54         Log.i(TAG, "---------->>" + map.toString());
55     }
56     
57     public void listDb() {
58         PersonService service = new PersonDao(getContext());
59         List<Map<String, String>> list = service.listPersonMaps(null);
60         Log.i(TAG, "---------->>" + list.toString());
61     }
62 }
复制代码

  insertDB()后,如果是在模拟器上调试,可以使用FIle Explorer工具导出mydb.db文件,使用SQLite Expert Professional(这是一个SQLite的管理软件,博客最后提供下载地址),打开数据库:

  执行deleteDb()删除第一条数据:

  执行updateDb()更新第二条数据:

  执行getDb(),查询第二条数据,执行listDb(),查询全部数据,查看日志输出:

  

  而如果是从事Android开发,还有必要了解另外一种操作SQLite的方式,使用SQLiteDatabase所提供的方法实现CRUD操作。主要有以下几个方法:

  • long insert(String table ,String nullColumnHack,ContentValues values):插入一条数据。
  • int delete(String table ,String whereCaluse,String[] whereArgs):根据条件,删除数据。
  • int updata(String table,ContentValues values,String whereCaluse,String[] whereArgs):根据条件,更新数据
  • Cursor query(...):根据条件,查询数据。提供多种重载方法,主要查询不同的条件。

  下面以一个示例程序讲解一下使用SQLiteDatabase所提供的方法实现CRUD操作:

  接口代码:

复制代码
 1 package com.examle.sqlitedbdemo.service;
 2 
 3 import java.util.List;
 4 import java.util.Map;
 5 
 6 import android.content.ContentValues;
 7 
 8 public interface PersonService2 {
 9 
10     public boolean addPerson(ContentValues values);
11 
12     public boolean deletePerson(String whereClause, String[] whereArgs);
13 
14     public boolean updatePerson(ContentValues values, String whereClause,
15             String[] whereArgs);
16 
17     public Map<String, String> viewPerson(String selection,
18             String[] selectionArgs);
19 
20     public List<Map<String, String>> listPersonMaps(String selection,
21             String[] selectionArgs);
22 }
复制代码

  实现代码:

复制代码
  1 package com.examle.sqlitedbdemo.dao;
  2 
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 
  8 import android.content.ContentValues;
  9 import android.content.Context;
 10 import android.database.Cursor;
 11 import android.database.sqlite.SQLiteDatabase;
 12 
 13 import com.examle.sqlitedbdemo.service.PersonService2;
 14 import com.example.sqlitedbdemo.db.DbOpenHelper;
 15 
 16 public class PersonDao2 implements PersonService2 {
 17     private DbOpenHelper helper = null;
 18 
 19     public PersonDao2(Context context) {
 20         helper = new DbOpenHelper(context);
 21     }
 22 
 23     @Override
 24     public boolean addPerson(ContentValues values) {
 25         boolean flag = false;
 26         SQLiteDatabase database = null;
 27         long id = -1;
 28         try {
 29             database = helper.getWritableDatabase();
 30             // 执行insert,返回当前行ID
 31             id = database.insert("person", null, values);
 32             flag = (id != -1 ? true : false);
 33         } catch (Exception e) {
 34             e.printStackTrace();
 35         } finally {
 36             if (database != null) {
 37                 database.close();
 38             }
 39         }
 40         return flag;
 41     }
 42 
 43     @Override
 44     public boolean deletePerson(String whereClause, String[] whereArgs) {
 45         boolean flag = false;
 46         SQLiteDatabase database = null;
 47         int count = 0;
 48         try {
 49             database = helper.getWritableDatabase();
 50             // 执行删除操作,返回影响行数
 51             count = database.delete("person", whereClause, whereArgs);
 52             flag = (count > 0 ? true : false);
 53         } catch (Exception e) {
 54             e.printStackTrace();
 55         } finally {
 56             if (database != null) {
 57                 database.close();
 58             }
 59         }
 60         return flag;
 61     }
 62 
 63     @Override
 64     public boolean updatePerson(ContentValues values, String whereClause,
 65             String[] whereArgs) {
 66         boolean flag = false;
 67         SQLiteDatabase database = null;
 68         int count = 0;
 69         try {
 70             database = helper.getWritableDatabase();
 71             // 执行更新操作,返回影响行数
 72             count = database.update("person", values, whereClause, whereArgs);
 73             flag = (count > 0 ? true : false);
 74         } catch (Exception e) {
 75             e.printStackTrace();
 76         } finally {
 77             if (database != null) {
 78                 database.close();
 79             }
 80         }
 81         return flag;
 82     }
 83 
 84     @Override
 85     public Map<String, String> viewPerson(String selection,
 86             String[] selectionArgs) {
 87         SQLiteDatabase database = null;
 88         Cursor cursor = null;
 89         Map<String, String> map = new HashMap<String, String>();
 90         try {
 91             database = helper.getReadableDatabase();
 92             // 设置查询条件
 93             cursor = database.query(true, "person", null, selection,
 94                     selectionArgs, null, null, null, null);
 95             int cols_len = cursor.getColumnCount();
 96             while (cursor.moveToNext()) {
 97                 for (int i = 0; i < cols_len; i++) {
 98                     String cols_key = cursor.getColumnName(i);
 99                     String cols_value = cursor.getString(cursor
100                             .getColumnIndex(cols_key));
101                     if (cols_value == null) {
102                         cols_value = "";
103                     }
104                     map.put(cols_key, cols_value);
105                 }
106             }
107         } catch (Exception e) {
108             e.printStackTrace();
109         }
110         return map;
111     }
112 
113     @Override
114     public List<Map<String, String>> listPersonMaps(String selection,
115             String[] selectionArgs) {
116         List<Map<String, String>> list = new ArrayList<Map<String, String>>();
117         SQLiteDatabase database = null;
118         Cursor cursor = null;
119         try {
120             database = helper.getReadableDatabase();
121             cursor = database.query(false, "person", null, selection,
122                     selectionArgs, null, null, null, null);
123             int cols_len = cursor.getColumnCount();
124             while (cursor.moveToNext()) {
125                 Map<String, String> map = new HashMap<String, String>();
126                 for (int i = 0; i < cols_len; i++) {
127                     String cols_key = cursor.getColumnName(i);
128                     String cols_value = cursor.getString(cursor
129                             .getColumnIndex(cols_key));
130                     if (cols_value == null) {
131                         cols_value = "";
132                     }
133                     map.put(cols_key, cols_value);
134                 }
135                 list.add(map);
136             }
137         } catch (Exception e) {
138             e.printStackTrace();
139         }
140         return list;
141     }
142 
143 }
复制代码

  最后和上面一下,创建一个测试类来测试这个数据库操作:

复制代码
 1 package com.example.sqlitedbdemo.db;
 2 
 3 import java.util.List;
 4 import java.util.Map;
 5 
 6 import com.examle.sqlitedbdemo.dao.PersonDao2;
 7 import com.examle.sqlitedbdemo.service.PersonService2;
 8 
 9 import android.content.ContentValues;
10 import android.test.AndroidTestCase;
11 import android.util.Log;
12 
13 public class TestDb2 extends AndroidTestCase {
14     private final String TAG = "main";
15 
16     public TestDb2() {
17         // TODO Auto-generated constructor stub
18     }
19 
20     public void addPerson() {
21         PersonService2 service2 = new PersonDao2(getContext());
22         ContentValues values1 = new ContentValues();
23         values1.put("name", "张龙");
24         values1.put("address", "beijing");
25         values1.put("sex", "male");
26         boolean flag = service2.addPerson(values1);
27         ContentValues values2 = new ContentValues();
28         values2.put("name", "赵虎");
29         values2.put("address", "shanghai");
30         values2.put("sex", "male");
31         flag = flag&&service2.addPerson(values2);
32         ContentValues values3 = new ContentValues();
33         values3.put("name", "王朝");
34         values3.put("address", "HK");
35         values3.put("sex", "male");
36         flag = flag&&service2.addPerson(values3);
37         ContentValues values4 = new ContentValues();
38         values4.put("name", "王朝");
39         values4.put("address", "HK");
40         values4.put("sex", "male");
41         flag = flag&&service2.addPerson(values4);
42         Log.i(TAG, "----------->>" + flag);
43     }
44     
45     public void deletePerson() {
46         PersonService2 service2 = new PersonDao2(getContext());
47         boolean flag = service2.deletePerson(" id =?", new String[]{"1"});
48         Log.i(TAG, "----------->>" + flag);
49     }
50     
51     public void updatePerson(){
52         PersonService2 service2 = new PersonDao2(getContext());
53         ContentValues values = new ContentValues();
54         values.put("name", "张三"); 
55         values.put("address", "上海");
56         values.put("sex", "男");
57         boolean flag=service2.updatePerson(values, " id=? ", new String[]{"2"});
58         Log.i(TAG, "----------->>" + flag);
59     }
60     
61     public void viewPerson(){
62         PersonService2 service2 = new PersonDao2(getContext());
63         Map<String, String> map=service2.viewPerson(" id=? ", new String[]{"2"});
64         Log.i(TAG, "----------->>" + map.toString());
65     }
66     public void listPerson(){
67         PersonService2 service2 = new PersonDao2(getContext());
68         List<Map<String, String>> list=service2.listPersonMaps(null,null);
69         Log.i(TAG, "----------->>" + list.toString());
70     }
71 }
复制代码

  实现的功能和上面一样,这里就不展示效果图了,但是因为是上面两种操作数据库的方式是在一个应用中完成的,并且数据一样,执行第二个测试类的时候,需要把之前创建的数据库删除,详情参见源码。 

 SQLite事务

  SQLite的事务通过SQLiteDatabase中包含的两个方法对其进行控制:beginTransaction(),开始事务;endTransaction(),结束事务。除此之外,SQLiteDatabase还提供了一个inTransaction()方法用来判断当前上下文是否处于事务环境中。当程序执行endTransaction()方法时将会结束事务,到底是回滚事务还是提交事务取决于SQLiteDatabase是否调用了setTransactionSuccessful()方法来设置事务标志,如果程序事务执行中调用该方法设置了事务成功则提交事务,否则程序将回滚事务。

  示例源码下载

总结

  上面就基本讲解了SQLite在Android中的时候,虽然有两种操作方式,并且直接使用SQL语句操作数据库对于熟悉SQL语句的开发者开说,是非常贴心的,但是在Android中,还是有必要了解一下使用SQLiteDatabase提供的方法操作数据库的方式,因为Android有一个内容提供者(Content Provider),可以使用外部应用访问内部应用的数据,它传递数据的形式,大部分是与SQLiteDatabase内置方法的参数一致的,所以如果同一使用SQLiteDatabase提供的方法操作数据库,是很方便的,无需额外转换SQL语句。

 


本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/android_SQLite.html,如需转载请自行联系原作者


相关文章
|
3月前
|
开发工具 Android开发 开发者
Android平台如何不推RTMP|不发布RTSP流|不实时录像|不回传GB28181数据时实时快照?
本文介绍了一种在Android平台上实现实时截图快照的方法,尤其适用于无需依赖系统接口的情况,如在RTMP推送、RTSP服务或GB28181设备接入等场景下进行截图。通过底层模块(libSmartPublisher.so)实现了截图功能,封装了`SnapShotImpl.java`类来管理截图流程。此外,提供了关键代码片段展示初始化SDK实例、执行截图、以及在Activity销毁时释放资源的过程。此方案还考虑到了快照数据的灵活处理需求,符合GB/T28181-2022的技术规范。对于寻求更灵活快照机制的开发者来说,这是一个值得参考的设计思路。
|
1月前
|
消息中间件 数据采集 数据库
小说爬虫-03 爬取章节的详细内容并保存 将章节URL推送至RabbitMQ Scrapy消费MQ 对数据进行爬取后写入SQLite
小说爬虫-03 爬取章节的详细内容并保存 将章节URL推送至RabbitMQ Scrapy消费MQ 对数据进行爬取后写入SQLite
24 1
|
2月前
|
存储 API 数据库
QML使用Sqlite数据库存储ListModel数据
本文介绍了在QML中使用Sqlite数据库存储ListModel数据的方法,包括如何创建数据库、读取数据、动态添加和删除数据,以及如何在程序启动和退出时与数据库同步数据。
|
1月前
|
存储 大数据 数据库
Android经典面试题之Intent传递数据大小为什么限制是1M?
在 Android 中,使用 Intent 传递数据时存在约 1MB 的大小限制,这是由于 Binder 机制的事务缓冲区限制、Intent 的设计初衷以及内存消耗和性能问题所致。推荐使用文件存储、SharedPreferences、数据库存储或 ContentProvider 等方式传递大数据。
55 0
|
3月前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
84 1
|
3月前
|
缓存 API Android开发
Android经典实战之Kotlin Flow中的3个数据相关的操作符:debounce、buffer和conflate
本文介绍了Kotlin中`Flow`的`debounce`、`buffer`及`conflate`三个操作符。`debounce`过滤快速连续数据,仅保留指定时间内的最后一个;`buffer`引入缓存减轻背压;`conflate`仅保留最新数据。通过示例展示了如何在搜索输入和数据流处理中应用这些操作符以提高程序效率和用户体验。
49 6
|
3月前
|
编解码 网络协议 前端开发
如何实现Android平台GB28181设备接入模块按需打开摄像头并回传数据
后台采集摄像头,如果想再进一步扩展,可以把android平台gb28181的camera2 demo,都移植过来,实现功能更强大的国标设备侧,这里主要是展示,收到国标平台侧的回传请求后,才打开摄像头,才开始编码打包,最大限度的减少资源的占用
|
3月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
3月前
|
算法 数据处理 开发工具
Android平台RTSP|RTMP播放器如何回调YUV或RGB数据
在开发Android平台上的RTSP或RTMP播放器时,开发者不仅追求低延迟播放,还希望获取解码后的视频数据(如YUV或RGB格式),以便进行视觉算法分析。使用大牛直播SDK中的SmartPlayer,可在确保播放流畅的同时,通过设置外部渲染器(`SmartPlayerSetExternalRender`)来高效地回调原始视频数据。例如,对于RGBA数据,需实现`NTExternalRender`接口,并重写相关方法以处理数据和尺寸变化。同样地,对于I420(YUV)数据,也需要相应地实现接口以满足需求。这种方式使得开发者能在不影响常规播放功能的情况下,进行定制化的视频处理任务。
|
3月前
|
存储 缓存 Java
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
Android项目架构设计问题之优化业务接口数据的加载效率如何解决
45 0