Android-填充sqlite表需要很长时间

Android-填充sqlite表需要很长时间,android,achartengine,Android,Achartengine,几个月前我就遇到过这个问题,现在是时候重新开始了 我将手机的通话记录查询到数据库中,但填充该表大约需要30秒。看起来查询大约需要1秒,但人口需要永远,尽管手机只存储最后500个电话。为什么这么慢?我做错什么了吗 我只在手机上测试它,因为模拟器的调用日志中只有8项 final String[] projection = null; HotOrNot infoA = new HotOrNot(Charts.this); infoA.open();

几个月前我就遇到过这个问题,现在是时候重新开始了

我将手机的通话记录查询到数据库中,但填充该表大约需要30秒。看起来查询大约需要1秒,但人口需要永远,尽管手机只存储最后500个电话。为什么这么慢?我做错什么了吗

我只在手机上测试它,因为模拟器的调用日志中只有8项

  final String[] projection = null;

            HotOrNot infoA = new HotOrNot(Charts.this);
            infoA.open();
            infoA.createtable_Calls();
            infoA.deleteAllEntries_Calls();
            infoA.close();

            final Context context = getApplicationContext();
            final String selection = null;
            final String sortOrder = android.provider.CallLog.Calls.DATE + " DESC";

            Cursor c = context.getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI, projection, selection, null, sortOrder);
            while (c.moveToNext()) { 
                String callLogID = c.getString(c.getColumnIndex(android.provider.CallLog.Calls._ID));

                int numberColumn = c.getColumnIndex(android.provider.CallLog.Calls.NUMBER);
                int dateColumn = c.getColumnIndex(android.provider.CallLog.Calls.DATE);
                int typeColumn = c.getColumnIndex(android.provider.CallLog.Calls.TYPE);
                int durationColumn = c.getColumnIndex(android.provider.CallLog.Calls.DURATION);
                int person = c.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME);



                String number = c.getString(numberColumn);
                int duration = c.getInt(durationColumn);
                String personname = c.getString(person);
                long callDate = c.getLong(dateColumn);
                int callType = c.getInt(typeColumn);

                if (duration >= 0)
                {
                    switch (callType) {
                    case 1:
                        duration_in = duration;
                        duration_out = 0;
                        break;
                    case 2:
                        duration_out = duration;
                        duration_in = 0;
                        break;
                    case 3:
                        duration_in = 0;
                        duration_out = 0;
                        break;


                    }
                    }

    //Here comes the slow part

                    HotOrNot info = new HotOrNot(Charts.this);
                    info.open();
                    info.pop   
ulate_Calls(personname, number, String.valueOf(callType), Integer.toString(duration), Long.toString(callDate), callLogID);
                info.close();   
             }
这是填充函数:

public long populate_Calls(String name, String phone, String type, String duration, String date, String contactid) {
        ContentValues cv = new ContentValues();
        cv.put(KEY_NAME, name);
        cv.put(KEY_PHONE, phone);
        cv.put(KEY_TYPE, type);
        cv.put(KEY_DURATION, duration);
        cv.put(KEY_DATE, date);
        cv.put(KEY_CONTACTID, contactid);
        return ourDatabase.insert(DATABASE_TABLE, null, cv);        
    }
编辑

根据Andreas Ka和twaddington的答案,我修改了SQLiteOpenHelper类中的population方法,但不幸的是,这并没有带来什么不同:

public long populate_Calls(String name, String phone, String type, String duration, String date, String contactid) {
    ContentValues cv = new ContentValues();
     try {
         ourDatabase.beginTransaction();

         cv.put(KEY_NAME, name);
         cv.put(KEY_PHONE, phone);
         cv.put(KEY_TYPE, type);
         cv.put(KEY_DURATION, duration);
         cv.put(KEY_DATE, date);
         cv.put(KEY_CONTACTID, contactid);

         ourDatabase.yieldIfContendedSafely();

         ourDatabase.setTransactionSuccessful();
     } finally {
         ourDatabase.endTransaction();
     }

    return ourDatabase.insert(DATABASE_TABLE, null, cv);        
}
EDIT2: 根据Babibu和twaddington的答案发布整个代码。顺便说一下,临时数组现在是LinkedList,但这在时间上没有什么区别

 final String[] projection = null;
        final Context context = getApplicationContext();
        final String selection = null;
        final String sortOrder = android.provider.CallLog.Calls.DATE + " DESC";
        lv1 = (ListView) findViewById(R.id.ListView02); 


        HotOrNot infoA = new HotOrNot(Calllogs.this);
        infoA.open();
        infoA.createtable_Calls();
        infoA.deleteAllEntries_Calls();
        infoA.close();

          pd = ProgressDialog.show(Calllogs.this, "Please wait..", "Loading data, it may take a few" +
                " seconds based on the number of data.", false, true);

        Cursor c = context.getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI, projection, selection, null, sortOrder);
        while (c.moveToNext()) { 
            String callLogID = c.getString(c.getColumnIndex(android.provider.CallLog.Calls._ID));

            int numberColumn = c.getColumnIndex(android.provider.CallLog.Calls.NUMBER);
            int dateColumn = c.getColumnIndex(android.provider.CallLog.Calls.DATE);
            int typeColumn = c.getColumnIndex(android.provider.CallLog.Calls.TYPE);
            int durationColumn = c.getColumnIndex(android.provider.CallLog.Calls.DURATION);
            int person = c.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME);



            String number = c.getString(numberColumn);
            int duration = c.getInt(durationColumn);
            String personname = c.getString(person);
            long callDate = c.getLong(dateColumn);
            int callType = c.getInt(typeColumn);

            if (duration >= 0)
            {
                switch (callType) {
                case 1:
                    duration_in = duration;
                    duration_out = 0;
                    break;
                case 2:
                    duration_out = duration;
                    duration_in = 0;
                    break;
                case 3:
                    duration_in = 0;
                    duration_out = 0;
                    break;
                }
            }

            temp_name.add(personname);
            temp_num.add(number);
            temp_type.add(String.valueOf(callType));
            temp_dur.add(Integer.toString(duration));
            temp_date.add(String.valueOf(callDate));
            temp_id.add(callLogID);
          } //end of while loop


        HotOrNot infotemp = new HotOrNot(Calllogs.this);
        infotemp.open();


            for (int i=0; i<temp_name.size(); i++)
            {
                infotemp.populate_Calls(temp_name.get(i), temp_num.get(i), temp_type.get(i), temp_dur.get(i), temp_date.get(i), temp_type.get(i));
            }
 infotemp.close();
final String[]projection=null;
最终上下文=getApplicationContext();
最终字符串选择=null;
最后一个字符串sortOrder=android.provider.CallLog.Calls.DATE+“DESC”;
lv1=(ListView)findViewById(R.id.ListView02);
HotOrNot infoA=新的HotOrNot(Calllogs.this);
infoA.open();
infoA.createtable_调用();
infoA.deleteAllEntries_Calls();
infoA.close();
pd=ProgressDialog.show(Calllogs.this,“请稍候…”,“加载数据,可能需要几分钟”+
“基于数据数量的秒数。”,false,true);
游标c=context.getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI、投影、选择、null、排序器);
而(c.moveToNext()){
String callLogID=c.getString(c.getColumnIndex(android.provider.CallLog.Calls._ID));
int numberColumn=c.getColumnIndex(android.provider.CallLog.Calls.NUMBER);
int dateColumn=c.getColumnIndex(android.provider.CallLog.Calls.DATE);
int-typeColumn=c.getColumnIndex(android.provider.CallLog.Calls.TYPE);
int durationColumn=c.getColumnIndex(android.provider.CallLog.Calls.DURATION);
int person=c.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME);
字符串编号=c.getString(numberColumn);
int duration=c.getInt(durationColumn);
String personname=c.getString(person);
long callDate=c.getLong(dateColumn);
int callType=c.getInt(typeColumn);
如果(持续时间>=0)
{
开关(呼叫类型){
案例1:
持续时间=持续时间;
持续时间=0;
打破
案例2:
持续时间=持续时间;
持续时间_in=0;
打破
案例3:
持续时间_in=0;
持续时间=0;
打破
}
}
临时名称添加(人名);
添加临时编号(编号);
temp_type.add(String.valueOf(callType));
临时期间添加(整数到字符串(持续时间));
temp_date.add(String.valueOf(callDate));
临时id添加(callLogID);
}//while循环结束
HotOrNot infotemp=newhotornot(Calllogs.this);
infotemp.open();

对于(inti=0;i,对于您对SQLite数据库所做的每个更改,都有一系列复杂的 执行以下步骤,包括创建回滚 如果发生错误,请更改。您可以将一系列更新包装到数据库中 强制SQLite将整个系列视为单个操作的事务。 这样会更有效率

try {
    db.beginTransaction();
    while (c.moveToNext()) {
        // Yield the database lock if requested
        db.yieldIfContendedSafely();

        // Add your code here!
        // ...

        // Perform the database insert
        populate_Calls(...);
    }
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

对于您对SQLite数据库所做的每一次更改,都会有一系列复杂的 执行以下步骤,包括创建回滚 如果发生错误,请更改。您可以将一系列更新包装到数据库中 强制SQLite将整个系列视为单个操作的事务。 这样会更有效率

try {
    db.beginTransaction();
    while (c.moveToNext()) {
        // Yield the database lock if requested
        db.yieldIfContendedSafely();

        // Add your code here!
        // ...

        // Perform the database insert
        populate_Calls(...);
    }
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

尝试对整个方法使用单个事务:
尝试对整个方法使用单个事务:

您在浏览时插入,这会锁定数据库。您需要先完成while循环,然后再将其插入数据库。只需将数据保留在同一个临时链接列表中(在您的情况下,最好是数组,因为它可以快速插入)

您在浏览时插入,这会锁定数据库。您需要先完成while循环,然后再将其插入数据库。只需将数据保留在同一个临时链接列表中(在您的情况下,最好是数组,因为它可以快速插入)

使用Traceview确定您的困难的确切来源。请为我计算下一次的时间:“c.moveToNext()”,整个while循环时间,“infotemp.open())“,”infotemp.populate_Calls“,整个for循环时间感谢您包含更新的代码!使用Traceview确定困难的确切来源。请为我计算下一次的时间:'c.moveToNext()',整个while循环时间,'infotemp.open()“,”infotemp.populate_Calls“,整个for循环时间感谢您提供了更新的代码!他正在从不同的数据库进行读写。您是对的,这通常是个坏主意,但我认为这不会导致任何问题。相反,主要的问题是他需要在事务中包装插入内容。@twaddington那些时候是我不可能,他确实得到了一些锁。而且交易可能会花费很多钱……我会建议以任何方式拆分它,即使只是为了解决问题。谁知道可能是android的错误……我使用的是一个数据库和一个表。我试过了,它将时间从28秒缩短到了7秒!很高兴有帮助,Babibu是对的,通常是这样的混合读写不是一个好主意。它通常会导致奇怪的问题。如果您更新代码以使用正确的transac