获取并保存联系人到SQLite数据库长时间阻止UI

时间:2017-12-26 06:59:58

标签: android android-sqlite android-contacts

我使用下面的代码来获取所有联系人并保存在本地数据库中。

获取联系人:

ArrayList<ContactHolder> contactList = new ArrayList<ContactHolder>();


    String order = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
    Cursor managedCursor = mContext.getContentResolver().query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null,
            null, order);

    int _number = managedCursor
            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
    int _name = managedCursor
            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
    int _id = managedCursor
            .getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID);



    while (managedCursor.moveToNext()) {

        ContactHolder holder = new ContactHolder();
        //String mData = Utility.filterLocaleWithAppropreateFlagsTest(mContext, managedCursor.getString(_number));
        holder.setNumber(managedCursor.getString(_number).replaceAll("\\s+",""));
        holder.setName(managedCursor.getString(_name));
        holder.setImageUrl(managedCursor.getString(_name));
        contactList.add(holder);
    }

保存在SQLite DB中:

 public List<Contact> insertContactDetails() {

    ArrayList<ContactHolder> arr = Utility.getContactDetails(context);
    List<Contact> serverArr = new ArrayList<Contact>();
    List<ContentValues> list = new ArrayList<ContentValues>();
    for (int i = 0; i < arr.size(); i++) {
        String mLocaleNo = "";

        ContactHolder mObject = arr.get(i);
        String mData = Utility.filterLocaleWithAppropreateFlagsTest(context, mObject.getNumber().replaceAll("\\s+",""));
        if (mData != null) {
            Contact mContact = new Contact();

            ContentValues values = new ContentValues();
            values.put(CONTACT_NAME, mObject.getName());
            mContact.setName(mObject.getName());

            values.put(CONTACT_MOBILE_NUMBER, mObject.getNumber().replaceAll("\\s+",""));


            values.put(CONTACT_IMAGE, mObject.getImageUrl());
            ArrayList<String> extra = new ArrayList<String>();
            StringTokenizer token = new StringTokenizer(mData);

            while (token.hasMoreElements()) {
                extra.add(String.valueOf(token.nextElement()));
            }

            mLocaleNo = extra.get(0);
            int mLocaleFlag = Integer.parseInt(extra.get(1));

            values.put(LOCALE_NUMBER, mLocaleNo);
            mContact.setPhNo(mLocaleNo);
            values.put(LOCALE_FLAG, mLocaleFlag);
            values.put(REG_STATUS, "0");

            list.add(values);
            serverArr.add(mContact);
        }
        /*
        arr.get(i).setContactStatus("0");
        arr.get(i).setLocaleNumber(mLocaleNo);*/
    }

    ourDatabase.beginTransaction();
    for (ContentValues entry : list) {

        try{
            long id = ourDatabase.insertOrThrow(CONTACT_TABLE, null, entry);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    ourDatabase.setTransactionSuccessful();
    ourDatabase.endTransaction();

    return serverArr;

}  

一切都按预期工作,但如果联系人的尺寸很大,那么实际问题会出现在图片上,这会使屏幕长白。

我仍然没有找到任何适当的解决方案来解决这个问题。

2 个答案:

答案 0 :(得分:1)

我可以建议仅使用ContentValues作为模型来处理从源到目标的联系人。

如果你会挖掘一点,你就能找到实际的问题。您正在使用contactHolder存储并再次检索并再次存储在ContentValues中,我认为这是不必要的。只需更改下面的代码并查看改进。

我只是在方法中添加了代码并在其中添加了一些更改。

获取联系人:

 public static ArrayList<ContentValues> getContactDetails(final Context mContext){
    ArrayList<ContentValues> contactList = new ArrayList<ContentValues>();


    String order = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
    Cursor managedCursor = mContext.getContentResolver().query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null,
            null, order);

    int _number = managedCursor
            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
    int _name = managedCursor
            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
    int _id = managedCursor
            .getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID);



    while (managedCursor.moveToNext()) {

        ContentValues values = new ContentValues();
        Contact mContact = new Contact();


            values.put(ContactClass.CONTACT_NAME, managedCursor.getString(_name));
            values.put(ContactClass.CONTACT_MOBILE_NUMBER, managedCursor.getString(_number).replaceAll("\\s+",""));
            mContact.setPhNo(managedCursor.getString(_number).replaceAll("\\s+",""));
            mContact.setName(managedCursor.getString(_name));

            contactList.add(values);
            serverContactList.add(mContact);

        }
    }

    return contactList;
}

在这里,我只使用相同的ContentValues类作为模型来保存联系人内部的联系人,并简单地为您的联系人(服务器内容)类添加相同的数据,这些数据保存在静态集合(serverContactList)中,您可以从任何地方直接访问。

注意:ContactClass.CONTACT_MOBILE_NUMBER是您的专栏名称。

将联系人插入数据库:

public List<Contact> insertContactDetails() {

    List<ContentValues> list = Utility.getContactDetails(context);

    ourDatabase.beginTransaction();
    for (ContentValues entry : list) {

        try{
            long id = ourDatabase.insertOrThrow(CONTACT_TABLE, null, entry);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    ourDatabase.setTransactionSuccessful();
    ourDatabase.endTransaction();

    return Utility.serverContactList;

}

如果您将在后台线程中完成所有这些内容,这将使您的表现更好。正如其他人在此建议的那样。

答案 1 :(得分:0)

如果数据很大,您应该使用CursorLoader进行保存/检索。

使用CursorLoader有三个主要好处:

  1. 查询是在后台线程上处理的(由于构建在AsyncTaskLoader上),因此大数据查询不会阻止UI。当您使用普通光标时,这是文档建议您执行的操作,但现在它已在引擎盖下完成。
  2. CursorLoader是自动更新。除了执行初始查询之外,CursorLoader还使用您请求的数据集注册ContentObserver,并在数据集更改时调用forceLoad()。
  3. 这样可以在数据发生变化时随时获取异步回调以更新视图。
  4. 如需更多阅读此Cursor Loader.