Diese Anwendung, an der ich gearbeitet habe, verfügt über Datenbanken mit mehreren Megabyte Daten, die durchsucht werden sollen. Viele der Aktivitäten sind lediglich ListViews, die durch verschiedene Datenebenen innerhalb der Datenbanken ablaufen, bis wir "Dokumente" erreichen, was nur HTML ist, das aus den DBs entnommen und auf dem Telefon angezeigt wird. Das Problem, das ich habe, ist, dass einige dieser Aktivitäten die Fähigkeit haben müssen, die Datenbanken zu durchsuchen, indem sie Tastenanschläge erfassen und die Abfrage mit einem "like% blah%" erneut ausführen. Dies funktioniert ziemlich schnell, außer wenn der Benutzer zuerst die Daten lädt und wenn der Benutzer zuerst einen Tastenanschlag eingibt. Ich benutze ein ResourceCursorAdapter und ich erzeuge den Cursor in einem Hintergrundthread, aber um eine listAdapter.changeCursor() zu machen, muss ich einen Handler verwenden, um es in den Haupt-UI-Thread zu posten. Dieser spezielle Anruf friert dann den UI-Thread gerade lang genug ein, um den gefürchteten ANR-Dialog aufzurufen. Ich bin gespannt, wie ich dies vollständig auf einen Hintergrund-Thread abladen kann, so dass die Benutzeroberfläche reaktionsschnell bleibt und keine ANR-Dialoge auftauchen.Android CursorAdapters, ListViews und Hintergrundthreads
Nur zur vollständigen Offenlegung, ich ursprünglich eine ArrayList der benutzerdefinierten Modellobjekte und die Verwendung eines ArrayAdapter zurück, aber (verständlicherweise) der Kunde wies darauf hin, es war schlechte Speicher-Management und ich war nicht mit der Leistung sowieso zufrieden. Ich möchte wirklich eine Lösung zu vermeiden, in denen ich riesige Listen von Objekten bin zu erzeugen und dann ein listAdapter.notifyDataSetChanged/Invalidated tun()
Hier ist der Code in Frage:
private Runnable filterDrugListRunnable = new Runnable() {
public void run() {
if (filterLock.tryLock() == false) return;
cur = ActivityUtils.getIndexItemCursor(DrugListActivity.this);
if (cur == null || forceRefresh == true) {
cur = docDb.getItemCursor(selectedIndex.getIndexId(), filter);
ActivityUtils.setIndexItemCursor(DrugListActivity.this, cur);
forceRefresh = false;
}
updateHandler.post(new Runnable() {
public void run() {
listAdapter.changeCursor(cur);
}
});
filterLock.unlock();
updateHandler.post(hideProgressRunnable);
updateHandler.post(updateListRunnable);
}
};
Bevor ich den changeCursor Anruf hinzugefügt, alles war glücklich und im Hintergrund lief. Einmal habe ich hinzugefügt, um diese: updateHandler.post (neu Runnable() { public void run() { listAdapter.changeCursor (Aktuell); } }); Alles ging schnell kaputt. – MattC
Ungerade Frage: Was ist FilterLock in Ihrem obigen Code? Stößt du möglicherweise in eine tödliche Umarmung oder eine Sackgasse? – CommonsWare
Es ist nur eine Sperre, die wir erwartet hatten, falls der Benutzer während der ersten Abfrage weiter tippte. Durch den tatsächlichen Code des CursorAdapter, ChangeCursor ruft notifyDataSetChanged() und das ist, wo es hängt. – MattC