Android 性能优化 (一)APK高效瘦身
http://blog.csdn.net/whb20081815/article/details/70140063
Android 性能优化 (二)数据库优化 秒变大神
http://blog.csdn.net/whb20081815/article/details/70142033
Android 性能优化(三)布局优化 秒变大神
http://blog.csdn.net/whb20081815/article/details/70147958
Android 性能优化(四)内存优化OOM 秒变大神
http://blog.csdn.net/whb20081815/article/details/70243105
Android 性能优化(五)ANR 秒变大神
http://blog.csdn.net/whb20081815/article/details/70245594
Android 性能优化(六) RelativeLayout和LinearLayout性能比较
http://blog.csdn.net/whb20081815/article/details/74465870
Android 性能优化<七>自定义view绘制优化
http://blog.csdn.net/whb20081815/article/details/74474736
Android 性能优化<八> 多线程优化和线程管理
https://blog.csdn.net/WHB20081815/article/details/77775444
Android 性能优化 <九>RecyclerView替代Listview用法
https://blog.csdn.net/WHB20081815/article/details/76221998
https://blog.csdn.net/WHB20081815/article/details/88595045
1.数据库插入效率
有三种方法:
1)直接拼接SQL语句,执行execSQL方法;
2)借用ContentValues进行插入;
3)使用compileStatement进行插入;
1)直接拼接SQL语句,执行execSQL方法, 一个一个插入
/**
* 向表中插入数据
*
* @param openHelper
* @param appInfo
* @return
*/
public static boolean insert(SQLiteOpenHelper openHelper,
RemoteAppInfo appInfo) {
if (null == appInfo) {
return true;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
ContentValues values = appInfo.getContentValues();
return -1 != db.insert(RemoteDBHelper.TABLE_APP_REMOTE, null,
values);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != db) {
db.close();
}
}
return false;
}
for (RemoteAppInfo remoteAppInfo : list)
{
RemoteDBUtil.insert(helper, remoteAppInfo);
}
public void execSQL(){
String sql = "create table msgTable(uid INTEGER NOT NULL, msg TEXT NOT NULL)";
db.execSQL(sql);
}
缺点:存在SQL注入危险;
查看源码得出:execSQL调用的本质就是创建SQLiteStatement对象,调用其executeUpdateDelete插入方法
1.利用android提高的的insert,query,update,deleteAPI与execSql,rawQuery函数执行原生的插入,查询,更新,删除语句操作花费时间的对比结果
在相同的环境(adnroid4.0)和相同的机器下执行相同的动作,记录条数也一样的情况下的对比,多次验证的如下:
(1)如果批量执行的记录数在1000条,则Android SqliteDatabase提供的insert,query,update,delete函数和直接写SQL文的execSql,rawQuery的效率差不多,几乎一样。所以使用哪种方式都可以,不会影响到执行效率。
(2)如果批量执行的记录数在10万条,则会存在差别。在某台手机上SqliteDatabase提供的insert执行插入操作耗时45秒,要比execSql插入35秒慢10秒左右。
可见在数据库大的情况下,还是有差别的。execSql省去了拼接sql语句的步骤,要比SqliteDatabase提供的insert,query,update,delete等函数效率高。当数据库越大,差别也越大。
二.开启事务批量插入,借用ContentValues;
这样如果连续插入100次数据实际是创建事务->执行语句->提交这个过程被重复执行了100次。如果我们显示的创建事务->执行100条语句->提交会使得这个创建事务和提交这个过程只做一次,通过这种一次性事务可以使得性能大幅提升。尤其当数据库位于sd卡时,时间上能节省两个数量级左右。
/**
* 向表中插入一串数据
*
* @param openHelper
* @param appInfo
* @return 如果成功则返回true,否则返回flase
*/
public static boolean insert(SQLiteOpenHelper openHelper,
List list) {
boolean result = true;
if (null == list || list.size() <= 0) {
return true;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
db.beginTransaction();
for (RemoteAppInfo remoteAppInfo : list) {
ContentValues values = remoteAppInfo.getContentValues();
if (db.insert(RemoteDBHelper.TABLE_APP_REMOTE, null, values) < 0) {
result = false;
break;
}
}
if (result) {
db.setTransactionSuccessful();
}
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (null != db) {
db.endTransaction();
db.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
借用ContentValues进行插入,解决了执行纯SQL语句引入的sql注入漏洞。
源码分析:使用ContentValues 最终是创建SQLiteStatement对象,并调用executeInsert()方法。
三,compileStatement,开启事务批量插入,使用SQLiteStatement
public static boolean insertBySql(SQLiteOpenHelper openHelper,
List list) {
if (null == openHelper || null == list || list.size() <= 0) {
return false;
}
SQLiteDatabase db = null;
try {
db = openHelper.getWritableDatabase();
String sql = "insert into " + RemoteDBHelper.TABLE_APP_REMOTE + "("
+ RemoteDBHelper.COL_PKG_NAME + ","// 包名
+ RemoteDBHelper.COL_USER_ACCOUNT + ","// 账号
+ RemoteDBHelper.COL_APP_SOURCE + ","// 来源
+ RemoteDBHelper.COL_SOURCE_UNIQUE + ","// PC mac 地址
+ RemoteDBHelper.COL_MOBILE_UNIQUE + ","// 手机唯一标识
+ RemoteDBHelper.COL_IMEI + ","// 手机IMEI
+ RemoteDBHelper.COL_INSTALL_STATUS + ","// 安装状态
+ RemoteDBHelper.COL_TRANSFER_RESULT + ","// 传输状态
+ RemoteDBHelper.COL_REMOTE_RECORD_ID // 唯一标识
+ ") " + "values(?,?,?,?,?,?,?,?,?)";
SQLiteStatement stat = db.compileStatement(sql);
db.beginTransaction();
for (RemoteAppInfo remoteAppInfo : list) {
stat.bindString(1, remoteAppInfo.getPkgName());
stat.bindString(2, remoteAppInfo.getAccount());
stat.bindLong(3, remoteAppInfo.getFrom());
stat.bindString(4, remoteAppInfo.getFromDeviceMd5());
stat.bindString(5, remoteAppInfo.getMoblieMd5());
stat.bindString(6, remoteAppInfo.getImei());
stat.bindLong(7, remoteAppInfo.getInstallStatus());
stat.bindLong(8, remoteAppInfo.getTransferResult());
stat.bindString(9, remoteAppInfo.getRecordId());
long result = stat.executeInsert();
if (result < 0) {
return false;
}
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (null != db) {
db.endTransaction();
db.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
SQLiteStatement stat = TelSqlAdapter.getInstance().getSqliteDb().compileStatement(sql);
小结:对于执行纯sql,ContentValues和compileStatement最终都是new 一个SQLiteStatement对象,并调用SQLiteStatement对象的相应方法。
无论哪种方法的话,都会用SQLiteStatement,直接用这个看,
=========================================
其他方式:
1)。语句的拼接使用StringBuilder代替String
简单的string相加会导致创建多个临时对象消耗性能。StringBuilder的空间预分配性能好得多。如果你对字符串的长度有大致了解,如100字符左右,可以直接new StringBuilder(128)指定初始大小,减少空间不够时的再次分配。
2)。少用cursor.getColumnIndex
根据性能调优过程中的观察cursor.getColumnIndex的时间消耗跟cursor.getInt相差无几。可以在建表的时候用static变量记住某列的index,直接调用相应index而不是每次查询。
3)。查询条件多点限制,查表就速度快
提问:
1.数据库的操作类型有哪些,如何导入外部数据库?
把原数据库包括在项目源码的 res/raw。android系统下数据库应该存放在 /data/data/com..(package name)/ 目录下,所以我们需要做的是把已有的数据库传入那个目录下.操作方法是用FileInputStream读取原数据库,再用FileOutputStream把读取到的东西写入到那个目录.