SQLiteDatabase に行を追加する必要があり、その結果、行の新しく作成された ID を取得したいと考えています。このタスクをバックグラウンド スレッドで実行するために、AsyncTask クラスを拡張しました。
private class InsertLangTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
try {
if (mDB.isOpen()) {
try {
mId = mDB.insertOrThrow(DBS.D.TN, null, mCV);
}
catch (SQLException e) {
StringBuilder query = new StringBuilder();
query.append("SELECT " + BaseColumns._ID + " FROM " + DBS.D.TN + " WHERE ");
Object[] bindArgs = new Object[mCV.size()];
int i = 0;
for (Map.Entry<String, Object> entry: mCV.valueSet()) {
query.append((i > 0) ? " AND " : "");
query.append(entry.getKey());
query.append(" = ?");
bindArgs[i++] = entry.getValue();
}
SQLiteStatement statement = mDB.compileStatement(query.toString());
for (i = 0; i < bindArgs.length; i++) {
DatabaseUtils.bindObjectToProgram(statement, i + 1, bindArgs[i]);
}
try {
mId = statement.simpleQueryForLong();
} finally {
statement.close();
}
}
}
}
catch (NullPointerException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
if (mActivity != null) { mActivity.onLangInserted(mId); }
super.onPostExecute(result);
}
}
この InsertLangTask クラスは、onCreate()、onAttach()、および onDetach() のみを実装する Fragment クラスに含まれています。また、メンバーを初期化するメソッドを内部に作成します (Fragment クラスでは空でなければならないため、コンストラクターでは実行できません)。この Fragment クラスで AsyncTask をラップして、mId メンバーを保持し、構成が変更されてアクティビティが破棄された場合でもそれをアクティビティに戻します。長期運用の場合は必ずしもそうではないことはわかっていますが、そうなる可能性があります。このクラスのパーツは次のとおりです。
public class InsertLangFragment extends Fragment {
public static interface OnLangInsertedListener {
void onLangInserted(long id);
}
SQLiteDatabase mDB = null;
ContentValues mCV = null;
private OnLangInsertedListener mActivity = null;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = activity;
}
public void RunTask(SQLiteDatabase db, ContentValues cv) {
new InsertLangTask().execute();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
}
そして、私のアクティビティでは、このプロセスを開始したいときにこれを書くだけです:
InsertLangFragment fragment = new InsertLangFragment();
getFragmentManager().beginTransaction().add(fragment, "insertTaskFragment").commit();
fragment.RunTask(mSQLiteDatabase, mContentValues);
実装されたコールバックで mId を取得する
public void onLangInserted(long id) {
}
setRetainInstance(true) を使用したため、このフラグメントは破棄されず (戻るボタンを除く)、常にメモリ内に配置されます。問題は、フラグメントインスタンスを適切に破棄するにはどうすればよいですか? 考えられる結果は 3 つあります
。1) このフラグメントを破壊する必要はありません。
2) アクティビティの onLangInserted() の最後に getFragmentManager().remove("insertTaskFragment").commit() を配置する必要があります。
3) AsyncTask の onPostExecute() の最後に setRetainInstance(false) を配置する必要があります。
この Fragment を適切に管理する方法を教えてください。
ありがとうございました。あまり厳しくしないでください、私はここの初心者です。