8

私には問題があり、それにどのようにアプローチすればよいかわかりません。私のアプリのアクティビティには、AsyncTask単一の にアクセスする複数の がありますSQLiteOpenHelper。でヘルパーを初期化して開き、でonCreate()閉じていonStop()ます。で初期化されているかどうかも確認しonResume()ます。

アプリを公開してdoInBackgroundから、DB ヘルパーにアクセスしようとしたところ、Null Exception で多数のエラーを受け取りました。が呼び出されるonStop()直前にDB が閉じられている () ため、これが発生することはわかっています。doInBackground

私の質問は、どこで DB 接続を閉じる必要があるかということです。アクティビティで DB ヘルパーの 1 つのインスタンスを使用し、複数のスレッドからアクセスすることは正しい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
        }
    }
}
4

3 に答える 3

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

このようにして、Db が常にアクセス可能であることを確認できます。

はい、Db ヘルパーのインスタンスを 1 つ持つことは良い習慣です。デフォルトでは、スレッドの同期が自動的に行われます。

于 2011-09-22T11:44:40.207 に答える
5

単品使いもいいですねDB Helper。問題は、ユーザーが を離れたときにActivityDB閉じられても、AsyncTaskがまだ実行されている可能性があることです。DBそのため、アクセスしようとするときに null でないことを確認する必要があります。null である場合は、そのタスクが破棄されたnullことを意味する可能性があります。Activitycancel

于 2011-09-22T11:35:34.237 に答える
1

DBを閉じる前にAsyncTaskをキャンセルするとおっしゃいました。ただし、AsyncTask をキャンセルすると、タスクがキャンセルされるように通知されるだけであり、doInBackground() で isCancelled() を確認し、DB 操作を停止するために必要なことを行う必要があることに注意してください。

DB を閉じる前に、getStatus() をチェックして、AsyncTask が停止していることを確認する必要があります。

于 2011-09-22T12:03:51.447 に答える