确保我的光标已关闭

时间:2012-12-27 21:57:37

标签: android cursor

所以我有一些不同的活动,它们将SimpleCursorAdapter用于ListView。我现在主要担心的是内存泄漏等等。我需要确保光标在应该是的时候关闭。

我发现当我因为nullpointerexception而进行更改后重新运行代码时,我的应用程序崩溃了。

有人可以查看我的代码以查看我的某个活动,并告诉我光标是否存在未正确关闭的问题?或者您看到的任何其他可能导致内存泄漏或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();
    }

} 

2 个答案:

答案 0 :(得分:1)

如果您想确保根据您的活动生命周期正确处理光标,我建议您使用

startManagingCursor()

方法

根据documentation

  

此方法允许活动根据活动的生命周期为您管理给定的Cursor生命周期。也就是说,当活动停止时,它将自动调用给定Cursor上的deactivate(),稍后重新启动它将为您调用requery()。当活动被销毁时,所有托管游标将自动关闭

但是,新的通常建议的方法是使用 CursorLoader ,但如果你只是使用普通的sqllite,我担心你不能

答案 1 :(得分:0)

我最终只是将光标设为全局,并在cursor.close() @Override中调用onDestroy()