问题
I get a lot of records from webService
(over 5000) and then I need to Insert
them in my sqlite
but when I Insert
them in my sqlite
get a long time for Insert
and often get me crash. What can I do?
My insert item is same below:
public long InsertData(Marketing_Points_B MP, Context context) {
DBS db = new DBS(context);
PACKAGE_NAME = context.getApplicationContext().getPackageName();
db.GetPackageName(PACKAGE_NAME);
db.CreateFile();
try {
db.CreateandOpenDataBase();
} catch (IOException e) {
e.printStackTrace();
}
sql = db.openDataBase();
ContentValues values = new ContentValues();
values.put("Count", MP.getCounts());
values.put("mDate", MP.getDate());
values.put("mTime", MP.getTime());
values.put("xLat", String.valueOf(MP.getLat()));
values.put("yLng", String.valueOf(MP.getLng()));
values.put("UserId", MP.getUserCode());
long LastId = sql.insert("ReportAct_tbl", null, values);
sql.close();
return LastId;
}
My LogCat:
08-10 13:05:47.470 988-2132/? E/qdlights: [BL] mode=0 brightness=10
08-10 13:05:50.090 988-4931/? E/qdlights: [BL] mode=0 brightness=255
08-10 13:06:02.720 21447-21447/? E/cutils-trace: Error opening trace file: No such file or directory (2)
08-10 13:06:21.090 988-1000/? E/Sensors: poll() failed (Interrupted system call)
08-10 13:06:22.320 988-1004/? E/ActivityManager: ANR in com.ir.zanis.marketing_manager (com.ir.zanis.marketing_manager/.ReportActivity_B)
Reason: keyDispatchingTimedOut
Load: 8.13 / 7.87 / 7.75
CPU usage from 15696ms to 0ms ago:
33% 19742/com.ir.zanis.marketing_manager: 20% user + 13% kernel / faults: 425 minor
26% 436/sdcard: 0.5% user + 26% kernel
3.8% 169/mmcqd/0: 0% user + 3.8% kernel
2.2% 24138/com.ucloudy.jewel: 1.5% user + 0.7% kernel / faults: 6627 minor 5 major
1.9% 988/system_server: 1.2% user + 0.7% kernel / faults: 407 minor 4 major
1.2% 438/adbd: 0.3% user + 0.9% kernel / faults: 1377 minor
0.4% 346/netd: 0.4% user + 0% kernel / faults: 11 minor
0.3% 20276/ksoftirqd/1: 0% user + 0.3% kernel
0.2% 3/ksoftirqd/0: 0% user + 0.2% kernel
0.2% 1867/mpdecision: 0% user + 0.2% kernel
0.1% 24070/kworker/0:2H: 0% user + 0.1% kernel
0.1% 1194/com.android.systemui: 0% user + 0% kernel
0% 1318/com.google.android.gms.persistent: 0% user + 0% kernel / faults: 836 minor 11 major
0% 1457/com.google.android.gms: 0% user + 0% kernel / faults: 649 minor 63 major
0.1% 24459/com.dewmobile.kuaiya.play: 0.1% user + 0% kernel / faults: 103 minor 2 major
0% 1//init: 0% user + 0% kernel / faults: 208 minor
0% 349/surfaceflinger: 0% user + 0% kernel
0% 1096/RX_Thread: 0% user + 0% kernel
0% 1136/wpa_supplicant: 0% user + 0% kernel / faults: 1 major
0% 1559/com.yirga.shutapp.Accessibility: 0% user + 0% kernel / faults: 37 minor
0% 13217/kworker/u:1: 0% user + 0% kernel
0% 13271/kworker/0:1: 0% user + 0% kernel
0% 19633/kworker/u:2: 0% user + 0% kernel
0% 20281/kworker/1:1: 0% user + 0% kernel
+0% 21667/kworker/1:2H: 0% user + 0% kernel
65% TOTAL: 13% user + 25% kernel + 26% iowait + 0.3% softirq
CPU usage from 1080ms to 1601ms later:
32% 19742/com.ir.zanis.marketing_manager: 25% user + 7.6% kernel / faults: 8 minor
30% 19742/rketing_manager: 23% user + 7.6% kernel
26% 436/sdcard: 0% user + 26% kernel
15% 436/sdcard: 0% user + 15% kernel
13% 470/sdcard: 0% user + 13% kernel
3.8% 169/mmcqd/0: 0% user + 3.8% kernel
3.8% 988/system_server: 0% user + 3.8% kernel / faults: 1 minor
3.8% 1004/ActivityManager: 0% user + 3.8% kernel
1.9% 438/adbd: 1.9% user + 0% kernel / faults: 48 minor
57% TOTAL: 10% user + 19% kernel + 28% iowait
08-10 13:06:28.840 349-566/? E/libEGL: eglMakeCurrent:671 error 3009 (EGL_BAD_MATCH)
08-10 13:06:28.910 21912-21918/? E/jdwp: Failed sending reply to debugger: Broken pipe
08-10 13:06:29.230 21912-21912/? E/RecyclerView: No adapter attached; skipping layout
08-10 13:06:29.300 21912-21912/? E/RecyclerView: No adapter attached; skipping layout
回答1:
To insert more record in database,You should use transaction with prepared statement that reduced the insertion time. For example:
public void insertFast(int insertCount) {
// you can use INSERT only
String sql = "INSERT OR REPLACE INTO " + tableName + " ( name, description ) VALUES ( ?, ? )";
SQLiteDatabase db = this.getWritableDatabase();
/*
* According to the docs http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
* Writers should use beginTransactionNonExclusive() or beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)
* to start a transaction. Non-exclusive mode allows database file to be in readable by other threads executing queries.
*/
db.beginTransactionNonExclusive();
// db.beginTransaction();
SQLiteStatement stmt = db.compileStatement(sql);
for(int x=1; x<=insertCount; x++){
stmt.bindString(1, "Name # " + x);
stmt.bindString(2, "Description # " + x);
stmt.execute();
stmt.clearBindings();
}
db.setTransactionSuccessful();
db.endTransaction();
db.close();
}
For details, how to use transaction see this tutorial
Use can also see, how to perform all db operation in transaction:
http://www.codota.com/android/methods/android.database.sqlite.SQLiteDatabase/beginTransaction
回答2:
I don't think you should do that many sql writes on the client (especially if this number of 6000 is likely to grow). Why don't you prepare the (compressed) sql db file on the server and send that over to your android client? This will certainly be faster and more battery friendly.
回答3:
I suggest you to insert these records through an another webservice ,firstly. Then update your android local Sqlite db file.
You can also have a look at following codes :
<?php
/*
* PHP SQLite - Create a table and insert rows in SQLite
*/
//Open the database mydb
$db = new SQLite3('db/mydb');
//drop the table if already exists
$db->exec('DROP TABLE IF EXISTS people');
//Create a basic table
$db->exec('CREATE TABLE people (full_name varchar(255), job_title varchar (255))');
echo "Table people has been created \n";
//insert rows
$db->exec('INSERT INTO people (full_name, job_title) VALUES ("John Doe","manager")');
echo "Row inserted \n";
$db->exec('INSERT INTO people (full_name, job_title) VALUES ("Jane Cyrus","assistant")');
echo "Row inserted \n";
?>
回答4:
If you're getting ANR then it is very likely that your code that writes to the database is running in the UI thread. Please keep that part separate and running in another thread.
Use for instance AsyncTask: more info at https://developer.android.com/reference/android/os/AsyncTask.html
来源:https://stackoverflow.com/questions/38867973/insert-over-6000-records-in-sqlite-android