Android从AsyncTask进行SQLiteOpenHelper调用时冻结

时间:2013-01-23 18:21:12

标签: android sqlite android-asynctask

如果我有一个SQLiteOpenHelper类,其中包含用于将对象插入到我的数据库中的方法,如果我从AsyncTask中调用此方法,那么对DB的调用是在单独的线程上还是在主UI中完成的线程?

我认为DB调用将在后台线程上进行。我是否错误地理解了asynctask类?我是否必须在SQLiteOpenHelper中重写所有数据库调用才能使用asynctasks?

目前,我在Android设备上遇到了很多延迟,并且上面写着一条消息:

The application may be doing too much work on its main thread.

我正在调用一个web服务,它响应一个json字符串,我正在我的doinbackground方法中解析,然后将项目插入到数据库中。

public class DB_Async {
public void replaceDeck(String jsonString, Delegate d){
    ReplaceDeck del = new ReplaceDeck();
    del.setDelegate(d);
    del.addParameter("json", jsonString);
    del.execute();
}
private class ReplaceDeck extends AsyncTask<String, Object, String> {

    private Delegate delegate;
    private Exception error;
    private Hashtable<String, String> parameters = new Hashtable<String, String>();

    public void setDelegate(Delegate d){
        delegate = d;
    }

    public void addParameter(String key, String value){
        parameters.put(key, value);
    }

    @Override
    protected void onPreExecute() {                     //Main Thread
        super.onPreExecute();

        if(delegate != null)
            delegate.onStart();
    }

    @Override
    protected void onPostExecute(String result) {       //Main Thread
        super.onPostExecute(result);
        if(delegate != null)
            delegate.onResult(result, error);
    }

    protected String doInBackground(String... params){  //BACKGROUND THREAD
        String currDate = new Date().toString();
        SQLdataHelper mDataHelper = SQLdataHelper.getInstance();
        String result = null;
        String jsonString = parameters.get("json");
        try {
            JSONObject jsonObj    = new JSONObject(jsonString);    
            JSONArray  jsonDecks = jsonObj.getJSONArray("decks");   
            for(int i = 0; i < jsonDecks.length(); i++){
                Deck newDeck = new Deck();
                int new_deck_id =  mDataHelper.addDeck(newDeck); // call to SQLOpenHelper
            }           
        } catch (JSONException e) {
            e.printStackTrace();
        }catch(Exception e)
        {
            System.out.println(e);
            result = e.getMessage();
            error = e;
        }
        return result;
    }
}

我的数据库只是在我的Decks列中插入一个新行:

 public synchronized long addDeck(Deck deck){
    String currDate = new Date().toString();
    ContentValues values = new ContentValues();
    values.put(DB_DECK_UID_COLUMN, deck.student_id);
    values.put(DB_DECK_NAME_COLUMN, deck.name);
    values.put(DB_DECK_DESC_COLUMN, deck.description);
    values.put(DB_DECK_DIFFICULTY_COLUMN, deck.difficulty);
    values.put(DB_DECK_COUNT_COLUMN, deck.cardCount);
    values.put(DB_DECK_RATING_COLUMN, deck.rating);
    values.put(DB_DECK_CREATED_COLUMN, currDate);
    values.put(DB_DECK_UPDATED_COLUMN, currDate);
    values.put(DB_DECK_WEBID_COLUMN, deck.web_id);
    values.put(DB_DECK_NEED_SYNC, 0);
    long deck_id = mDB.insert(DB_DECK_TABLE, null, values);
    return deck_id;
}

要调用此方法,我创建一个新委托并调用我的ReplaceDeck。

DB_Async.Delegate asyncDelegate = new DB_Async.Delegate() {
        @Override
        public void onStart() {
            // TODO Auto-generated method stub
        }
        @Override
        public void onResult(String result, Exception e) {
            Toast.makeText(mContext, "Successful Download", Toast.LENGTH_SHORT).show();
        }
    };
    try{
        DB_Async bf = new DB_Async(mContext);
        bf.replaceDeck(jsonString, asyncDelegate);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

1 个答案:

答案 0 :(得分:0)

  

我正在调用一个以json字符串响应的web服务   我正在我的doinbackground方法中解析然后插入   将项目放入数据库。

表示您尝试在UI Thread上进行webservice调用,然后将其作为参数传递给replaceDeck以启动AsyncTask并在doinbackground中解析它。

您还需要将webservice调用相关代码放在AsyncTask的doinbackground方法中。为此,您可以使用两个AsyncTask来调用webservice来获取数据,第二个用于在数据库中插入数据。