0

そのため、ListView に SimpleCursorAdapter を使用するいくつかの異なるアクティビティがあります。現在の私の主な懸念は、メモリリークなどです。カーソルが閉じているはずのときに閉じていることを確認する必要があります。

nullpointerexception が原因で変更を行った後にコードを再実行すると、アプリがクラッシュすることに気付きました。

誰かが私のアクティビティの 1 つのコードを見て、カーソルが適切に閉じられないという問題があるかどうかを教えてもらえますか? または、メモリ リークや ANR を引き起こす可能性のあるその他の問題はありますか?

RoutinesActivity.java:

package com.gauvion.gfit;

import android.annotation.SuppressLint;
import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class RoutinesActivity extends ListActivity {

    private RoutinesDataSource datasource;
    private SimpleCursorAdapter dataAdapter;
    private boolean isEditing = false;
    private Toast toast_deleted;
    private String[] columns = new String[] { MySQLiteHelper.COLUMN_NAME };
    private int[] to;

    @SuppressLint("ShowToast")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_routines);
        getActionBar().setDisplayHomeAsUpEnabled(true);

        toast_deleted = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        datasource = new RoutinesDataSource(this);
        datasource.open();

        Cursor cursor = datasource.fetchAllRoutines();
        to = new int[] { R.id.listitem_routine_name };
        dataAdapter = new SimpleCursorAdapter(this, R.layout.listitem_routine, cursor, columns, to, 0);
        setListAdapter(dataAdapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.activity_routines, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {     
        Cursor cursor = datasource.fetchAllRoutines();
        switch (item.getItemId()) {
        case android.R.id.home:
            this.finish();
            return true;

        case R.id.button_routines_add:
            Intent startRoutineAdd = new Intent(this, RoutineAddActivity.class);
            this.startActivity(startRoutineAdd);
            return true;

        case R.id.button_routines_edit:
            to = new int[] { R.id.listitem_routine_edit_name };
            dataAdapter = new SimpleCursorAdapter(this, R.layout.listitem_routine_edit, cursor, columns, to, 0);
            setListAdapter(dataAdapter);

            isEditing = true;
            invalidateOptionsMenu();
            return true;

        case R.id.button_routines_edit_done:
            to = new int[] { R.id.listitem_routine_name };
            dataAdapter = new SimpleCursorAdapter(this, R.layout.listitem_routine, cursor, columns, to, 0);
            setListAdapter(dataAdapter);

            isEditing = false;
            invalidateOptionsMenu();
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        menu.findItem(R.id.button_routines_edit).setVisible(!isEditing);
        menu.findItem(R.id.button_routines_edit_done).setVisible(isEditing);

        return true;
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long thisID)
    {       
        Cursor cursor = ((SimpleCursorAdapter)l.getAdapter()).getCursor();
        cursor.moveToPosition(position);
        long id = cursor.getLong(cursor.getColumnIndex(MySQLiteHelper.COLUMN_ID));
        String name = cursor.getString(cursor.getColumnIndex(MySQLiteHelper.COLUMN_NAME));

        if (!isEditing) {
            Intent startDaysActivity = new Intent(this, DaysActivity.class);
            startDaysActivity.putExtra("routineDataID", id);
            startDaysActivity.putExtra("routineDataName", name);
            this.startActivity(startDaysActivity);
        }
    }

    public void onClick(View view) {        
        ListView l = getListView();
        int position = l.getPositionForView(view);

        Cursor cursor = ((SimpleCursorAdapter)l.getAdapter()).getCursor();
        cursor.moveToPosition(position);
        long id = cursor.getLong(cursor.getColumnIndex(MySQLiteHelper.COLUMN_ID));
        String name = cursor.getString(cursor.getColumnIndex(MySQLiteHelper.COLUMN_NAME));

        switch (view.getId()) { 
        case R.id.button_routine_edit:
            Intent startRoutineEdit = new Intent(this, RoutineEditActivity.class);
            startRoutineEdit.putExtra("routineDataID", id);
            startRoutineEdit.putExtra("routineDataName", name);
            this.startActivity(startRoutineEdit);
            break;

        case R.id.button_routine_delete:
            toast_deleted.setText(getString(R.string.toast_routine_deleted));
            toast_deleted.show();
            datasource.deleteRoutine(id);
            onResume();
            break;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        datasource.open();
        Cursor cursor = datasource.fetchAllRoutines();
        dataAdapter.changeCursor(cursor);
    }

    @Override
    protected void onPause() {
        super.onPause();
        datasource.close();
    }

} 
4

2 に答える 2

1

アクティビティのライフサイクルに従ってカーソルが正しく処理されることを確認したい場合は、使用することをお勧めします

startManagingCursor()

方法。

ドキュメントによると:

このメソッドを使用すると、アクティビティのライフサイクルに基づいて、指定された Cursor のライフサイクルをアクティビティで管理できます。つまり、アクティビティが停止されると、指定された Cursor で自動的に activate() が呼び出され、後で再開されると requery() が呼び出されます。アクティビティが破棄されると、管理されているすべてのカーソルが自動的に閉じられます

ただし、一般的に提案されている新しいアプローチはCursorLoaderを使用することですが、単純な sqllite を使用しているだけではできないのではないかと心配しています。

于 2012-12-27T22:51:38.660 に答える
0

cursor.close()カーソルをグローバルにして、 @Overrideを呼び出すだけになりましたonDestroy()

于 2012-12-28T17:46:58.537 に答える