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

时间:2012-05-28 16:35:45

标签: android achartengine

我几个月前遇到过这个问题,现在是时候回到它了。

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

我只在手机上测试,因为我在模拟器的calllog中只有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类中的填充方法,但不幸的是它并没有什么区别:

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的答案发布整个代码。顺便说一句,temp_数组现在是LinkedLists,但这并没有带来时间上的差异。

 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();

我发布了twaddington的解决方案,将时间从8秒减少到不到2秒:

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

        // Get our database. You can do this however you wish, but
        // it seems like since the database is contained in your `HotOrNot`
        // object, it would be best to simply add a getter method to
        // the class.
        SQLiteDatabase db = infotemp.getDatabase();

        try {
            // Begin our transaction
            db.beginTransaction();

            // Loop over the array of calls and
            // perform a db insert for each.
            for (int i=0; i<temp_name.size(); i++) {
                // Yield the database lock if requested. This will
                // temporarily suspend our loop, but it should
                // continue when the lock is opened.
                db.yieldIfContendedSafely();

                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));
            }

            // Mark our transaction as successful!
            db.setTransactionSuccessful();
        } finally {
            // Always end the transaction!
            db.endTransaction();
        }

        infotemp.close();

3 个答案:

答案 0 :(得分:2)

对于您对SQLite数据库所做的每一个更改都是一系列复杂的 步骤发生,包括创建journal file以回滚 如果发生错误则更改。您可以将一系列更新包装在数据库中 事务强制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();
}

答案 1 :(得分:1)

答案 2 :(得分:1)

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