PDA

Visualizza la versione completa : Android - problema cursore sql


use®
20-08-2017, 10:00
Ciao, ho seguito passo dopo passo questo tutorial ‘Database e SQLite (http://www.html.it/pag/49180/database-e-sqlite/)’ (vostro) e quando avvio il programma di prova (sia emulato che su dispositivo fisico) ottengo il seguente errore:


FATAL EXCEPTION: main
Process: it.appdiprova, PID: 4417


android.database.StaleDataException: Attempting to access a closed CursorWindow.Most probable cause: cursor is deactivated prior to calling this method.



... eccetera.


Onestamente, nel codice “copiato dal tutorial” non riesco ad intravedere nessun codice di chiusura es: cursore.close() tanto meno un’eventuale chiusura del database db.close().



L’errore si presenta sia quando salvo i dati inseriti sia quando cancello un dato precedentemente inserito (non succede se è presente solo un dato).


Ad ogni modo l’errore che si presenta è sempre lo stesso.


Qualcuno può illuminarmi cortesemente?


Sto utilizzando l’ultima versione di Android Studio 2.3.3

oregon
20-08-2017, 10:57
Meglio mostrare il codice completo, che ne pensi?

Altrimenti non posso che essere d'accordo con l'errore e basta ,,,

use®
20-08-2017, 18:53
Ciao, non ho inserito il codice perché è praticamente identico.

La main:

public class MainActivity extends AppCompatActivity {
private DbManager db = null;
private CursorAdapter adapter;
private ListView listView = null;

private View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {

int position = listView.getPositionForView(view);
long id = adapter.getItemId(position);
if (db.delete(id))
adapter.changeCursor(db.query());
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

db = new DbManager(this);
listView = (ListView)findViewById(R.id.listview);
final Cursor crs = db.query();
adapter = new CursorAdapter(this, crs, 0) {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

View v = getLayoutInflater().inflate(R.layout.lista_activit y, null);
return v;
}

@Override
public void bindView(View view, Context context, Cursor cursor) {

String oggetto = crs.getString(crs.getColumnIndex(DatabaseString._S UBJECT));
TextView txt = (TextView)view.findViewById(R.id.txt_subject);
txt.setText(oggetto);

String data = crs.getString(crs.getColumnIndex(DatabaseString._D ATE));
txt = (TextView)view.findViewById(R.id.txt_date);
txt.setText(data);

ImageButton imgBtn = (ImageButton)view.findViewById(R.id.btn_delete);
imgBtn.setOnClickListener(clickListener);
}

@Override
public long getItemId(int position) {

Cursor crs = adapter.getCursor();
crs.moveToPosition(position);
return crs.getLong(crs.getColumnIndex(DatabaseString._ID) );
}
};

listView.setAdapter(adapter);
}

public void salva(View v) {

EditText sub = (EditText)findViewById(R.id.oggetto);
EditText txt = (EditText)findViewById(R.id.testo);
EditText date = (EditText) findViewById(R.id.data);

if (sub.length() > 0 && date.length() > 0) {
db.save(sub.getEditableText().toString(), txt.getEditableText().toString(), date.getEditableText().toString());
adapter.changeCursor(db.query());
}
}
}

La classe helper:

public class DBHelper extends SQLiteOpenHelper {

public static final String DBNAME = "BILLBOOK";

public DBHelper(Context context) {
super(context, DBNAME, null, 1);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {

String query = "CREATE TABLE " + DatabaseString._DEADLINES +
"( _id INTEGER PRIMARY KEY AUTOINCREMENT," +
DatabaseString._SUBJECT + " TEXT," +
DatabaseString._TEXT + " TEXT," +
DatabaseString._DATE + " TEXT)";

sqLiteDatabase.execSQL(query);
}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

}
}

La classe manager del db:

public class DbManager {

private DBHelper dbHelper;

public DbManager(Context context) {
dbHelper = new DBHelper(context);
}

public void save(String sub, String txt, String date) {

SQLiteDatabase db = dbHelper.getWritableDatabase();

ContentValues cv = new ContentValues();
cv.put(DatabaseString._SUBJECT, sub);
cv.put(DatabaseString._TEXT, txt);
cv.put(DatabaseString._DATE, date);
try {
db.insert(DatabaseString._DEADLINES, null, cv);
} catch (SQLiteException sqle) {
System.out.println("SQLiteException in 'save' -> " + sqle.getMessage());
}
}

public boolean delete(long id) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
try {
if (db.delete(DatabaseString._DEADLINES, DatabaseString._ID+"=?",
new String[]{Long.toString(id)}) > 0)
return true;
return false;
} catch (SQLiteException sqle) {
System.out.println("SQLiteException in 'delete' -> " + sqle.getMessage());
return false;
}
}

public Cursor query() {

Cursor crs = null;
try {
SQLiteDatabase db = dbHelper.getReadableDatabase();
crs = db.query(DatabaseString._DEADLINES, null, null, null, null, null, null);
} catch (SQLiteException sqle) {
System.out.println("SQLiteException in 'query' -> " + sqle.getMessage());
return null;
}
return crs;
}

}

Questo è tutto, grazie per la cortesia Oregon.

use®
20-08-2017, 19:01
Azz, per caso ti riferivi al codice di errore? Beh, nel dubbio inserisco anche quello...

FATAL EXCEPTION: main
Process: it.appdiprova, PID: 4990
android.database.StaleDataException: Attempting to access a closed CursorWindow.Most probable cause: cursor is deactivated prior to calling this method.
at android.database.AbstractWindowedCursor.checkPosit ion(AbstractWindowedCursor.java:139)
at android.database.AbstractWindowedCursor.getString( AbstractWindowedCursor.java:50)
at it.appdiprova.MainActivity$3.bindView(MainActivity .java:104)
at android.support.v4.widget.CursorAdapter.getView(Cu rsorAdapter.java:273)
at android.widget.AbsListView.obtainView(AbsListView. java:2363)
at android.widget.ListView.measureHeightOfChildren(Li stView.java:1326)
at android.widget.ListView.onMeasure(ListView.java:12 33)
at android.view.View.measure(View.java:19857)
at android.view.ViewGroup.measureChildWithMargins(Vie wGroup.java:6083)
at android.widget.LinearLayout.measureChildBeforeLayo ut(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(Linear Layout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout .java:640)
at android.view.View.measure(View.java:19857)
at android.view.ViewGroup.measureChildWithMargins(Vie wGroup.java:6083)
at android.widget.FrameLayout.onMeasure(FrameLayout.j ava:185)
at android.support.v7.widget.ContentFrameLayout.onMea sure(ContentFrameLayout.java:139)
at android.view.View.measure(View.java:19857)
at android.view.ViewGroup.measureChildWithMargins(Vie wGroup.java:6083)
at android.support.v7.widget.ActionBarOverlayLayout.o nMeasure(ActionBarOverlayLayout.java:391)
at android.view.View.measure(View.java:19857)
at android.view.ViewGroup.measureChildWithMargins(Vie wGroup.java:6083)
at android.widget.FrameLayout.onMeasure(FrameLayout.j ava:185)
at android.view.View.measure(View.java:19857)
at android.view.ViewGroup.measureChildWithMargins(Vie wGroup.java:6083)
at android.widget.LinearLayout.measureChildBeforeLayo ut(LinearLayout.java:1464)
at android.widget.LinearLayout.measureVertical(Linear Layout.java:758)
at android.widget.LinearLayout.onMeasure(LinearLayout .java:640)
at android.view.View.measure(View.java:19857)
at android.view.ViewGroup.measureChildWithMargins(Vie wGroup.java:6083)
at android.widget.FrameLayout.onMeasure(FrameLayout.j ava:185)
at com.android.internal.policy.DecorView.onMeasure(De corView.java:689)
at android.view.View.measure(View.java:19857)
at android.view.ViewRootImpl.performMeasure(ViewRootI mpl.java:2275)
at android.view.ViewRootImpl.measureHierarchy(ViewRoo tImpl.java:1366)
at android.view.ViewRootImpl.performTraversals(ViewRo otImpl.java:1619)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl .java:1254)
at android.view.ViewRootImpl$TraversalRunnable.run(Vi ewRootImpl.java:6337)
at android.view.Choreographer$CallbackRecord.run(Chor eographer.java:874)
at android.view.Choreographer.doCallbacks(Choreograph er.java:686)
at android.view.Choreographer.doFrame(Choreographer.j ava:621)
at android.view.Choreographer$FrameDisplayEventReceiv er.run(Choreographer.java:860)
at android.os.Handler.handleCallback(Handler.java:751 )
at android.os.Handler.dispatchMessage(Handler.java:95 )
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.jav a:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCa ller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit .java:776)

Questa è la riga 104:
String oggetto = crs.getString(crs.getColumnIndex(DatabaseString._S UBJECT));

use®
22-08-2017, 08:22
Meglio mostrare il codice completo, che ne pensi?

Altrimenti non posso che essere d'accordo con l'errore e basta ,,,

Quindi?

use®
24-08-2017, 09:54
Ieri sera ho creato un piccolo database di prova e ho trovato la causa del mio errore... Questo è quanto può accadere quando si esegue un copia e incolla. ;-)

Mi concentravo su altri possibili problemi senza rendermi conto che bastava osservare i nomi delle variabili. Errore piuttosto banale.

@Override
public void bindView(View view, Context context, Cursor cursor) {

String oggetto = crs.getString(crs.getColumnIndex(DatabaseString._S UBJECT));
TextView txt = (TextView)view.findViewById(R.id.txt_subject);
txt.setText(oggetto);

String data = crs.getString(crs.getColumnIndex(DatabaseString._D ATE));
txt = (TextView)view.findViewById(R.id.txt_date);
txt.setText(data);

ImageButton imgBtn = (ImageButton)view.findViewById(R.id.btn_delete);
imgBtn.setOnClickListener(clickListener);
}

...è bastato correggere cursor in crs

Ovviamente ho fatto altro, non sono stato 1 settimana a scemare, però devo ammettere che qualche oretta l'ho persa.

Loading