3

DownloadAndSaveから拡張するクラスがありAsyncTaskます。そのdoInBackgroundメソッドでは、http 接続からデータを取得し、OrmLite を使用してデータを保存しますが、データベースから古いエントリも消去します。したがって、次のようなものです。

doInBackground()
{
  clearDb();
  dataList = fetchDataFromHttp();
  saveToDb(dataList);
}

DB 例外が頻繁に発生します。

すでに閉じたオブジェクトを再度開こうとしています:SQLiteDatabase

clearDb() および saveToDb() 関数で。

の前の呼び出しからの古いデータが からDownloadAndSaveの新しいデータと混合されるため、これは悪いことDownloadAndSaveです。

私の意見では、スレッドを開始するときに、DownloadAndSaveクラスの他のすべてのスレッドが終了していることを確認する必要があります。つまり、一度に多くても の 1 つのインスタンスを実行する必要がありますDownloadAndSave。問題は、あるDownloadAndSave時点で のインスタンスが 1 つだけ実行されるようにするにはどうすればよいかということです。

4

4 に答える 4

3

オプション 1。上に移動:

clearDb();
dataList = fetchDataFromHttp();
saveToDb(dataList);

クラスオブジェクトに対して同期する別のクラスで:

public class WorkerClass {
    private WorkerListener workerListener;

    public static interface WorkerListener {
        public void publishWorkProgress(String data);
    }

    public WorkerClass(WorkerListener workerListener) {
        this.workerListener = workerListener;
    }

    public void performWork() {
        synchronized (WorkerClass.class) {
             clearDb();
             publish("Cleared DB");
             dataList = fetchDataFromHttp();
             publish("Got http data");
             saveToDb(dataList);
             publish("There! saved!");
        }
    }

    private void publish(String message) {
        if(workerListener != null) {
            workerListener.publishWorkProgress(message);
        }
    }

}

あなたの活動から:

public class SampleActivity extends Activity {

    public void doTheThing() {
        new MyAsyncTask().execute();
    }

    private static class MyAsyncTask extends AsyncTask<Void, String, Void> implements WorkerListener {
        @Override
        protected Void doInBackground(Void... params) {
            new WorkerClass(this).performWork();
            return null;
        }

        @Override
        public void publishWorkProgress(String data) {
            publishProgress(data);
        }
    }
}

オプション 2 : 上記のコードを IntentService に移動します。

public class WorkerIntentService extends IntentService {
   public WorkerIntentService() {
       super(null);
   }

   @Override
    protected void onHandleIntent(Intent intent) {
       clearDb();
       dataList = fetchDataFromHttp();
       saveToDb(dataList);
    }
}

IntentService を使用すると、タスクが連続して実行されることが保証されます。

于 2013-10-08T12:02:45.383 に答える
0

doInBackground で db 操作を使用する場合、1 つのスレッドに対して db をロックする必要があります。

public void insertToDb(){
 SQliteDatabase db;
 ...
 db.beginTransaction();
 ...//operation
 db.yieldIfContendedSafely();
 db.setTransactionSuccessful();
 db.endTransaction();
}
于 2013-10-08T12:02:00.673 に答える