Android如何在另一个线程上执行db插入?

时间:2012-07-26 07:52:23

标签: android sqlite csv

我必须将大型在线csv(30k +行)文件导入我的应用程序数据库。我怎么能在另一个线程或asynctask中执行此操作?

我正在研究这段代码。它继续onCreate

final ProgressDialog Dialog = ProgressDialog.show(
            this, "Updating schedule", "This may take a few minutes...", true, false);

    Thread thread = new Thread(new Runnable() {
        public void run() {
            DatabaseHandler db = new DatabaseHandler(MainActivity.this);

            //**How do I begin transaction here?**

            URL myURL;
            try {
                myURL = new URL("http://www.meralco.com.ph/pms/pms.csv");

                BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream()));
                while (true) {
                    String output = so.readLine();
                    if (output != null) {
                        String[] sched = output.split(",");
                        db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
                                sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
                                sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
                                sched[INDEX_DETAILS], sched[INDEX_REASON]);
                    }
                    else {
                        break;
                    }
                }

                //**How do I close transaction here?**
                so.close();
            }
            catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 


            runOnUiThread(new Runnable() {
                public void run() {
                    while (!Dialog.isShowing());
                    Dialog.dismiss();
                }
            });
        }

    });
    thread.start();

DatabaseHandler.java

public class DatabaseHandler{

public static final String KEY_SIN = "sched_sin";
public static final String KEY_CITY = "sched_city";
public static final String KEY_START_TIME = "sched_start_time";
public static final String KEY_START_DATE= "sched_start_date";
public static final String KEY_END_TIME = "sched_end_time";
public static final String KEY_END_DATE = "sched_end_date";
public static final String KEY_DETAILS = "sched_details";
public static final String KEY_REASON = "sched_reason";
public static final String KEY_ROWID = "_id";

private static final String TAG = "DatabaseHandler";
private SQLiteDatabase mDb;

private static final String DATABASE_NAME = "schedule_database";
private static final String DATABASE_TABLE = "schedule";
private static final int DATABASE_VERSION = 1;

private static final String DATABASE_CREATE =
    "create table " + DATABASE_TABLE + " (" + KEY_ROWID + " integer primary key autoincrement, "
    + KEY_SIN +" text not null, " + KEY_CITY + " text not null, " 
    + KEY_START_DATE +" text not null, " + KEY_START_TIME + " text not null, " 
    + KEY_END_DATE +" text not null, " + KEY_END_TIME + " text not null, "
    + KEY_DETAILS +" text not null, " + KEY_REASON + " text not null);";

private final Context mCtx;

public DatabaseHandler(Context ctx) {
    this.mCtx = ctx;

    // create or open the database
    DatabaseHelper helper = new DatabaseHelper(ctx);
    this.mDb = helper.getWritableDatabase();
}

public void addRow(String sin, String city, String start_date, String start_time, 
        String end_date,String end_time, String details, String reason)
{
    // this is a key value pair holder used by android's SQLite functions
    ContentValues values = new ContentValues();

    values.put(KEY_SIN, sin);
    values.put(KEY_CITY, city);
    values.put(KEY_START_DATE, start_date);
    values.put(KEY_START_TIME, start_time);
    values.put(KEY_END_DATE, end_date);
    values.put(KEY_END_TIME, end_time);
    values.put(KEY_DETAILS, details);
    values.put(KEY_REASON, reason);

    // ask the database object to insert the new data 
    try
    {
        this.mDb.insert(DATABASE_TABLE, null, values);
    }
    catch(Exception e)
    {
        Log.e("DB ERROR", e.toString()); // prints the error message to the log
        e.printStackTrace(); // prints the stack trace to the log
    }
}

public ArrayList<ArrayList<Object>> getAllRowsAsArrays()
{
    // create an ArrayList that will hold all of the data collected from
    // the database.
    ArrayList<ArrayList<Object>> dataArrays = new ArrayList<ArrayList<Object>>();

    // this is a database call that creates a "cursor" object.
    // the cursor object store the information collected from the
    // database and is used to iterate through the data.
    Cursor cursor;

    try
    {
        // ask the database object to create the cursor.
        cursor = this.mDb.query(
                DATABASE_TABLE,
                new String[]{KEY_ROWID, KEY_SIN, KEY_CITY, KEY_START_DATE, KEY_START_TIME, KEY_END_DATE, KEY_END_TIME, KEY_DETAILS, KEY_REASON},
                null, null, null, null, null
        );

        // move the cursor's pointer to position zero.
        cursor.moveToFirst();

        // if there is data after the current cursor position, add it
        // to the ArrayList.
        if (!cursor.isAfterLast())
        {
            do
            {
                ArrayList<Object> dataList = new ArrayList<Object>();

                dataList.add(cursor.getLong(0));
                dataList.add(cursor.getString(1));
                dataList.add(cursor.getString(2));
                dataList.add(cursor.getString(3));
                dataList.add(cursor.getString(4));
                dataList.add(cursor.getString(5));
                dataList.add(cursor.getString(6));
                dataList.add(cursor.getString(7));
                dataList.add(cursor.getString(8));

                dataArrays.add(dataList);
            }
            // move the cursor's pointer up one position.
            while (cursor.moveToNext());
        }
    }
    catch (SQLException e)
    {
        Log.e("DB Error", e.toString());
        e.printStackTrace();
    }

    // return the ArrayList that holds the data collected from
    // the database.
    return dataArrays;
}

private static class DatabaseHelper extends SQLiteOpenHelper {  

    DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i(TAG, "Creating DataBase: " + DATABASE_CREATE);
        db.execSQL(DATABASE_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
        onCreate(db);
    }
}
}

修改 此外,我在使用beginTransaction()endTransaction时遇到问题,因为我无法在线程中使用它。它说下面的方法是未定义的....

public void beginTransaction(){
    this.mDb.beginTransaction();
}

public void endTransaction(String sql){
    this.mDb.endTransaction();
}   

2 个答案:

答案 0 :(得分:0)

像:

public final class DownloadFile extends AsyncTask<Void, Long, Boolean> {

private Context context;
private ProgressDialog progressDialog;

public DownloadFile (Context context) {
    this.context = context;
}

/* 
 * @see android.os.AsyncTask#onPreExecute()
 */
@Override
protected void onPreExecute() {
    try {
        progressDialog = ProgressDialog.show(context, "", "message", true);
    } catch (final Throwable th) {
        //TODO
    }
}

protected Boolean doInBackground(Void... arg0) {
    DatabaseHandler db = new DatabaseHandler(context);

            //**How do I begin transaction here?**

        URL myURL;
        try {
            myURL = new URL("http://www.meralco.com.ph/pms/pms.csv");

            BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream()));
            while (true) {
                String output = so.readLine();
                if (output != null) {
                    String[] sched = output.split(",");
                    db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
                            sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
                            sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
                            sched[INDEX_DETAILS], sched[INDEX_REASON]);
                }
                else {
                    break;
                }
            }

            //**How do I close transaction here?**
            so.close();
            return true;
        }
        catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        } 
 }

protected void onPostExecute(Boolean result) {
    progressDialog.dismiss();
}
}

答案 1 :(得分:0)

以下是适合我的代码。我注意到使用Threads代替AsyncTask时下载速度更快,所以我选择了前者。正如@JoxTraex指出的那样,我使用了一个csv解析器(在这种情况下,我使用了OpenCSV的读者)而不是一个完整的工作块。它消除了我在每个逗号中拆分的问题,即使值被包含在一对双引号中也是如此。

Thread downloadThread = new Thread(new Runnable() {

    public void run() {

        db = new DatabaseHandler(MainActivity.this);
        db.beginTransaction();

        try {
            URL url = new URL(csvFileName);

            Log.i("dl", "start");

            InputStream input = url.openStream();
            CSVReader reader = new CSVReader(new InputStreamReader(input));

            String [] sched;
            while ((sched = reader.readNext()) != null) {
                if(sched[INDEX_CITY].equals("")) sched[INDEX_CITY]="OTHERS";
                try {

                    db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
                            sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
                            sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
                            sched[INDEX_DETAILS], sched[INDEX_REASON]);
                } catch (IndexOutOfBoundsException e) {
                    db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
                            sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
                            sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
                            "", sched[INDEX_REASON]);
                    //e.printStackTrace();
                }
            }
            input.close();
            Log.i("dl", "finished");

        } catch (MalformedURLException e) {
            e.printStackTrace();
            db.endTransaction();
        } catch (IOException e) {
            e.printStackTrace();
            db.endTransaction();
        } 
        Log.d("Count", ""+db.count());
        db.setTransactionSuccessful();
        db.endTransaction();

        writeUploadDateInTextFile();

    }

});

在我的数据库处理程序类中,

public void beginTransaction(){
    this.mDb.beginTransaction();
}

public void endTransaction(String sql){
    this.mDb.endTransaction();
}