我在使用ormlite的Android应用程序中工作。我正在接收我的电话簿联系人并将其保存在我的本地数据库中,但问题是它需要花费太多时间,例如近1500次接触,这需要将近70秒。
我在ormlite中搜索了批量插入内容,但我无法在以下代码中弄清楚如何实现它。
public static void loadLocalPhoneBookSample(Context ctx) {
try{
ContentResolver contentRes = ctx.getContentResolver();
Cursor cur = null;
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
cur = contentRes.query(ContactsContract.Contacts.CONTENT_URI, PROJECTIONS, selection, null, Phone.DISPLAY_NAME + " ASC");
context = ctx;
if (cur.getCount() > 0) {
// create DB object
MUrgencyDBHelper db = new MUrgencyDBHelper(ctx);
RuntimeExceptionDao<ContactLocal, ?> contactDAO = db.getContactLocalIntDataDao();
UpdateBuilder<ContactLocal, ?> updateDAO = contactDAO.updateBuilder();
try {
updateDAO.updateColumnValue("isUseless", true);
updateDAO.update();
} catch (SQLException e) {
e.printStackTrace();
}finally {
// db.writeUnlock();
}
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
/** read names **/
String displayName = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
/** Phone Numbers **/
Cursor pCur = contentRes.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = ?", new String[] { id }, null);
while (pCur.moveToNext()) {
String number = pCur
.getString(pCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String formatedNo = number.replaceAll("\\s+", "").replace("+", "00").replace("-", "").trim();
try {
QueryBuilder<ContactLocal, ?> query = contactDAO.queryBuilder();
query.where().eq("mFormatedNumber", number);
ContactLocal contact = query.queryForFirst();
boolean addContact = false, alreadyUpdated = true;
if (contact == null) {
addContact = true;
contact = new ContactLocal();
contact.setFirstName(displayName.trim());
contact.setLastName(displayName.trim());
contact.setContactNumber(formatedNo);
}
// check if this contact was already updated before
if (contact.getContactNumber() == null || contact.getContactNumber().length() == 0) {
contact.setContFirstLastNo(number, displayName, displayName, number);
alreadyUpdated = false;
}
contact.setUseless(false);
// if not updated already, Create/Update
if (addContact) {
contactDAO.create(contact);
} else
contactDAO.update(contact);
}
}
pCur.close();
}
}
}
答案 0 :(得分:2)
这是我的修订版本(可能需要一些语法更改)
public static void loadLocalPhoneBookSample(Context ctx) {
try {
ContentResolver contentRes = ctx.getContentResolver();
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Cursor cur = contentRes.query(ContactsContract.Contacts.CONTENT_URI, PROJECTIONS, selection, null, Phone.DISPLAY_NAME + " ASC");
context = ctx;
if (cur.getCount() > 0) {
// create DB object
MUrgencyDBHelper db = new MUrgencyDBHelper(ctx);
RuntimeExceptionDao<ContactLocal, ?> contactDAO = db.getContactLocalIntDataDao();
UpdateBuilder<ContactLocal, ?> updateDAO = contactDAO.updateBuilder();
try {
updateDAO.updateColumnValue("isUseless", true);
updateDAO.update();
} catch (SQLException e) {
e.printStackTrace();
}finally {
// db.writeUnlock();
}
ArrayList<ContactLocal> contacts = new ArrayList<>();
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
/** read names **/
String displayName = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
/** Phone Numbers **/
Cursor pCur = contentRes.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);
while (pCur.moveToNext()) {
String number = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String formatedNo = number.replaceAll("\\s+", "").replace("+", "00").replace("-", "").trim();
try {
QueryBuilder<ContactLocal, ?> query = contactDAO.queryBuilder();
query.where().eq("mFormatedNumber", number);
ContactLocal contact = query.queryForFirst();
if (contact == null) {
contact = new ContactLocal();
contact.setFirstName(displayName.trim());
contact.setLastName(displayName.trim());
contact.setContactNumber(formatedNo);
}
contact.setUseless(false);
contacts.add(contact);
}
}
pCur.close();
}
contactDao.callBatchTasks(new Callable<Void>() {
public Void call() throws Exception {
for (ContactLocal contact : contacts) {
contactDAO.createOrUpdate(contact);
}
}
});
}
}
主要优化是使用callBatchTasks
。从ormlite文档:
默认情况下,数据库在每次SQL操作后都会更改。此方法禁用此“自动提交”行为,因此可以更快地进行一些更改,然后一次全部提交。
通过创建ArrayList
并跟踪更改,您可以一次性使用callBatchTasks
创建/更新。
此外,我注意到alreadyUpdated
从未被访问过,因此可以安全删除。
同样Dao
的{{1}}方法与之前的createOrUpdate
if语句相同。
答案 1 :(得分:2)
问题在于它需要花费太多时间,例如近1500次接触需要花费近70秒
@CarloB在dao. callBatchTasks(...)
方法中进行质量创建方面有正确的答案。这是关于该主题的文档:
为了让事情变得更快,您还可以浏览并记录另一个mFormatedNumber
中的所有List
,然后使用IN
查询查询它们。使用原始查询来获取数据库中已有的mFormatedNumber
:
results = dao.queryRaw(
"SELECT mFormatedNumber from Contact WHERE mFormatedNumber IN ?",
mFormatedNumberList);
对于使用ORMLite的原始查询,请参阅:
那么您可以进行一次查询以查看需要创建哪些联系人,然后在批处理事务中执行所有插入。
否则,您正在进行~3000个同步数据库事务,并且在Android设备上40 /秒很不典型。