所以我有一些不同的活动,它们将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();
}
}
答案 0 :(得分:1)
如果您想确保根据您的活动生命周期正确处理光标,我建议您使用
startManagingCursor()
方法
此方法允许活动根据活动的生命周期为您管理给定的Cursor生命周期。也就是说,当活动停止时,它将自动调用给定Cursor上的deactivate(),稍后重新启动它将为您调用requery()。当活动被销毁时,所有托管游标将自动关闭
但是,新的通常建议的方法是使用 CursorLoader ,但如果你只是使用普通的sqllite,我担心你不能
答案 1 :(得分:0)
我最终只是将光标设为全局,并在cursor.close()
@Override中调用onDestroy()
。