0

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

我注意到,由于空指针异常,在我进行更改后重新运行代码时,我的应用程序崩溃了。

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

方法。

根据文档

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

但是,新的常用方法是使用CursorLoader,但如果你只是使用普通的 sqllite 恐怕你不能

于 2012-12-27T22:51:38.660 回答
0

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

于 2012-12-28T17:46:58.537 回答