Android AsyncTask和SQLite数据库实例

Mar*_*rqs 8 sqlite android android-asynctask sqliteopenhelper

我有一个问题,我不知道如何处理它.我的应用中的一项活动有多个AsyncTasks访问单个SQLiteOpenHelper.我初始化并打开帮助程序onCreate(),我正在关闭它onStop().我还检查它是否已经初始化onResume().

由于我已经发布了我的应用程序,因此doInBackground在尝试访问数据库帮助程序时,我收到了Null Exception错误的数量.我知道这是因为DB onStop()doInBackground被调用之前就已经关闭了(公平).

我的问题是,我应该在哪里关闭数据库连接?在Activity中使用DB帮助程序的单个实例并从多个线程(AsyncTasks)访问它是正确的吗?或者我应该为每个使用单独的DB帮助程序实例AsyncTask

这是我活动的简化骨架:

public class MyActivity extends Activity{
    private DbHelper mDbHelper;
    private ArrayList<ExampleObject> objects;

    @Override
    public void onStop(){
        super.onStop();
        if(mDbHelper != null){
            mDbHelper.close();
            mDbHelper = null;
        }
    }

    @Override
    public void onResume(){
        super.onResume();
        if(mDbHelper == null){
            mDbHelper = new DbHelper(this);
            mDbHelper.open();
        }
    }

    @Override 
    public void onCreate(Bundle icicle) { 
        super.onCreate(icicle); 
        DbHelper mDbHelper = new DbHelper(this);
        mDbHelper.open();
    }

    private class DoSomething extends AsyncTask<String, Void, Void> {

        @Override
        protected Void doInBackground(String... arg0) {
            objects = mDbHelper.getMyExampleObjects();
            return null;
        }

        @Override
        protected void onPostExecute(final Void unused){
            //update UI with my objects
        }
    }

    private class DoSomethingElse extends AsyncTask<String, Void, Void> {

        @Override
        protected Void doInBackground(String... arg0) {
            objects = mDbHelper.getSortedObjects();
            return null;
        }

        @Override
        protected void onPostExecute(final Void unused){
            //update UI with my objects
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dmi*_*nko 11

您不需要为每个活动管理数据库连接.您可以在android.app.Application的实例中执行此操作,并使用此实例访问db.像这样的东西:

public class MyApplication extends Application {

    // Synchronized because it's possible to get a race condition here
    // if db is accessed from different threads. This synchronization can be optimized
    // thought I wander if it's necessary
    public synchronized static SQLiteDatabase db() {
        if(self().mDbOpenHelper == null) {
            self().mDbOpenHelper = new MyDbOpenHelper();
        }
        return self().mDbOpenHelper.getWritableDatabase();
    }

    public static Context context() {
        return self();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mSelf = this;
    }

    private static MyApplication self() {
        if (self == null) throw new IllegalStateException();
        return mSelf;
    }

    private MyDbOpenHelper mDbOpenHelper;

    private static MyApplication mSelf;
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以确定Db始终可以访问.

是的,有一个Db助手的实例是一个很好的做法.默认情况下,线程同步是为您完成的.


Ovi*_*tcu 5

使用单个是好的DB Helper.问题是,当用户离开时,ActivityDB仍然关闭但AsyncTask可能仍在运行.因此,DB当您尝试访问它时,应该检查它是否为空,如果是null这样,则可能意味着您Activity已被销毁并且cancel该任务.


小智 1

您提到在关闭数据库之前取消 AsyncTask。但您应该记住,取消 AsyncTask 只是发出要取消任务的信号,您需要检查 doInBackground() 中的 isCancelled() 并执行必要的操作来停止数据库操作。

在关闭数据库之前,您需要检查 getStatus() 以确保 AsyncTask 已停止。