1

私のアプリはいくつかのアクティビティで構成されていますが、これまで、アクティビティ間を移動するときにデータベースへのアクセスに問題はありませんでした。ただし、最後のlistActivity(LocationActivity)には、各listViewアイテムに埋め込まれたボタンがあります。

これらのボタンの1つをクリックすると、SpecificationEdit.javaに移動し、ユーザーはそのlistViewアイテム(破損したコンポーネント)の一部のEditTextフィールドに仕様を入力しますが、[保存]をクリックすると、次のエラーメッセージが表示されてクラッシュします(データはデータベースに保存されますok):

java.lang.RuntimeException: Unable to resume activity blah blah
Exception: trying to requery an already closed cursor blah blah

listActivityクラスは次のとおりです。

public class LocationActivity extends ListActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_location);
    setLongClick();

    rmDbHelper = new RMDbAdapter(this);
    rmDbHelper.open();
    getIntents();
    setUpViews();
    setAdapter();               
    setTextChangedListeners();
}

protected void onResume(){
    super.onResume();
    final Cursor locationCursor = (Cursor) rmDbHelper.fetchLocationsForRun(runId);
    startManagingCursor(locationCursor);
    locationCursorSize = locationCursor.getCount();
    setAdapter();
    setTextChangedListeners();
}

そして、これがこのアクティビティのビットで、SpecificationEdit.javaに送信されます。

private void startComponentEdit() {
    Intent i = new Intent(LocationActivity.this, SpecificationEdit.class);
    i.putExtra("Intent_InspectionID", inspectionId);
    i.putExtra("Intent_AreaID", areaId);
    i.putExtra("Intent_RunID", runId);
    i.putExtra("Intent_LocationID", locationId);
    i.putExtra("Intent_Ref", locationRef);
    i.putExtra("Intent_DamagedComponentID", damagedComponentId);
    startActivityForResult(i, ACTIVITY_CREATE);

}

そして、これがSpecificationEdit.javaのOnCreateです。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    rmDbHelper = new RMDbAdapter(this);
    rmDbHelper.open();
    Intent i = getIntent();
    inspectionId = i.getLongExtra("Intent_InspectionID", -1);
    areaId = i.getLongExtra("Intent_AreaID", -1);
    runId = i.getLongExtra("Intent_RunID", -1);
    locationId = i.getLongExtra("Intent_LocationID", -1);
    damagedComponentId = i.getLongExtra("Intent_DamagedComponentID", -1);
    setContentView(R.layout.edit_specification);
    setUpViews();
    populateFields();
    fillSpinner();
    setListeners();
}

保存ボタンをクリックすると起動するコードがあります。

protected void saveDamagedComponentSpec() {  

    String manufacturer = ((Cursor)manufacturerSpinner.getSelectedItem()).getString(1).toString();
    String text1 = specEditText1.getText().toString();
    String text2 = specEditText2.getText().toString();
    String text3 = specEditText3.getText().toString();
    String text4 = specEditText4.getText().toString();
    String notes_spec = specEditTextNotes.getText().toString();

    rmDbHelper.saveDamagedComponentSpec(damagedComponentId, manufacturer, text1, text2, text3, text4, notes_spec);      

    if ("Yes".equals(specSaved)){
        Toast.makeText(getApplicationContext(), "Component specification updated", 
            Toast.LENGTH_SHORT).show();
    }

    else {
        Toast.makeText(getApplicationContext(), "Component specification added", 
                Toast.LENGTH_SHORT).show();

    }

    finish();
}

最後に、データベースヘルパークラスのコードは次のとおりです。

//Constructor - takes the context to allow the database to be opened/created
public RMDbAdapter(Context ctx) {
    this.mCtx = ctx;
}

/**
 * Open the rm database. If it cannot be opened, try to create a new
 * instance of the database. If it cannot be created, throw an exception to
 * signal the failure
 * 
 * @return this (self reference, allowing this to be chained in an
 *         Initialisation call)
 * @throws SQLException if the database could be neither opened or created
 */
public RMDbAdapter open() throws SQLException {
    rmDbHelper = new DatabaseHelper(mCtx);
    rmDb = rmDbHelper.getWritableDatabase();
    return this;
}


public void close() {
    rmDbHelper.close();
}

奇妙なことに、listViewアイテム(埋め込まれたアイテムではなく実際のアイテム)の1つをクリックするか、[新しいコンポーネントを追加]ボタンをクリックすると、非常によく似たインターフェイスを持つ別のアクティビティComponentEdit.javaに移動します(コンポーネント)をSpecificationEditとして指定しますが、終了してもアプリはクラッシュしません。

2つのアクティビティの大きな違いはわかりませんが、LocationActivityに戻ると、1つはこのエラーでクラッシュし、もう1つはそうではありません。

onResumeを削除しようとしましたが、これで違いはありませんでした。これでレンガの壁にぶつかると、気が狂います。

エミュレーターでは問題なく動作していることを追加する必要がありますが、電話(HTC One S)でテストするとクラッシュします。非常に奇妙な..

4

2 に答える 2

0

rmDbHelper.close();を呼び出すことを忘れないでください。別の活動を開始する前に

于 2012-12-17T17:02:49.470 に答える
0

そうです、問題を見つけました(明らかな間違いを見つけてください):

    Cursor componentsCursor = (Cursor) rmDbHelper.fetchDamagedComponentSpecForInspection(inspectionId, componentType);
    startManagingCursor(componentsCursor);

    Intent i = new Intent(this, SpecificationEdit.class);
    i.putExtra("Intent_InspectionID", inspectionId);
    i.putExtra("Intent_AreaID", areaId);
    i.putExtra("Intent_RunID", runId);
    i.putExtra("Intent_LocationID", locationId);
    i.putExtra("Intent_Ref", locationRef);
    i.putExtra("Intent_DamagedComponentID", damagedComponentId);
    startActivityForResult(i, ACTIVITY_CREATE);

    componentsCursor.close();

したがって、これは明らかではありませんでした(componentsCursor.close()の前にブロックされたコードが残っていました)が、SpecifcationEdit.classを終了すると、このアクティビティに戻ってcomponentsCursorを閉じようとしますが、明らかに失敗します。

愚かなことは、私は実際にはまだこのカーソルに何もさせていなかったということです!ドー!

いくつかの追加のアドバイス/気まぐれのため​​だけに; 私のアプリはGoogleのメモ帳の例とは根本的に異なります。実際にはstartActivityForResultを使用していないためです(実際、これらすべてをstartActivityだけに置き換えます)。編集アクティビティでは、(この情報をインテントに渡すのではなく、前のアクティビティに戻ったときにaddinigを実行します。

これは私のコードの領域ではより論理的だと思いますが、このアプローチに関するフィードバックはありますか?

于 2012-12-18T15:34:14.713 に答える