OSM 데이터를 사용하여 주어진 위치 집합의 사용자에게 경로를 제공하는 Android 앱을 개발 중입니다. 사용자는 SearchView로 들어가기를 원하는 위치를 입력 할 수 있으며, 사용자 유형에 따라 검색 결과를 필터링하여 결과를 좁히면 드롭 다운 ListView에서 대상을 선택할 수 있습니다. 이 필터링은 onQueryTextChange()를 사용하여 수행됩니다. ContentProvider를 사용하여 데이터베이스에서이 데이터를 쿼리하고 LoaderManager.LoaderCallbacks 인터페이스를 구현하여 ContentProvider를 다시 쿼리하고 사용할 어댑터에 대한 새 데이터를 제공합니다.CursorLoader를 사용하여 ContentProvider에서 데이터를로드하는 중 오류가 발생했습니다.
이 모든 것들은 광대하고 대부분의 시간 동안 작동하며 예상대로 정확하게 수행됩니다. 그러나, 드물게, 응용 프로그램이 다음 스택 추적으로 중단됩니다. 나는 사용자가 입력됩니다로 발생 다른 검색과 다른 시간을 입력합니다 SearchView을 취소 할 때
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteQuery: SELECT _id, suggest_text_1, suggest_intent_data FROM Locations WHERE (suggest_text_1 LIKE ?)
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:58)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:152)
at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:124)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:214)
at android.database.CursorWrapper.moveToPosition(CursorWrapper.java:162)
at android.support.v4.widget.CursorAdapter.getItemId(CursorAdapter.java:225)
at android.widget.AdapterView.rememberSyncState(AdapterView.java:1195)
at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:811)
at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6280)
at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
at android.support.v4.widget.CursorAdapter.swapCursor(CursorAdapter.java:347)
at android.support.v4.widget.SimpleCursorAdapter.swapCursor(SimpleCursorAdapter.java:326)
at android.support.v4.widget.CursorAdapter.changeCursor(CursorAdapter.java:315)
at android.support.v4.widget.CursorFilter.publishResults(CursorFilter.java:68)
at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
는 일반적으로이 오류가 발생합니다.
편집 : 부분적인 ContentProvider가 포함되어 삽입, 삭제 및 업데이트가 생략됩니다.
public class SearchContentProvider extends ContentProvider {
private DbHelper helper;
private static final String AUTH = "com.dgh1.Navigation.SearchContentProvider";
private static final String LOCATIONS_PATH = "Location";
private static final String GEOFENCES_PATH = "Fences";
private static final String PEOPLE_PATH = "People";
public static final Uri LOCATION_URI = Uri.parse("content://" + AUTH + "/" + LOCATIONS_PATH);
public static final Uri GEOFENCE_URI = Uri.parse("content://" + AUTH + "/" + GEOFENCES_PATH);
public static final Uri PEOPLE_URI = Uri.parse("content://" + AUTH + "/" + PEOPLE_PATH);
private static final int LOCATIONS = 10;
private static final int NAME_LOCATION = 11;
private static final int NODE_LOCATION = 20;
private static final int GEOFENCES = 30;
private static final int MARKERS = 40;
private static final int GEOFENCE = 50;
private static final int PEOPLE = 60;
private static final int PERSON = 70;
private static final String URI_ERROR = "Unknown URI: ";
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
matcher.addURI(AUTH, LOCATIONS_PATH, LOCATIONS);
matcher.addURI(AUTH, GEOFENCES_PATH, GEOFENCES);
matcher.addURI(AUTH, PEOPLE_PATH, PEOPLE);
matcher.addURI(AUTH, LOCATIONS_PATH + "/#", NODE_LOCATION);
matcher.addURI(AUTH, GEOFENCES_PATH + "/#", GEOFENCE);
matcher.addURI(AUTH, PEOPLE_PATH + "/#", PERSON);
matcher.addURI(AUTH, LOCATIONS_PATH + "/*", NAME_LOCATION);
}
@Override
public boolean onCreate() {
helper = new DbHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Cursor cursor = null;
int uriType = matcher.match(uri);
switch (uriType) {
case LOCATIONS:
if (selectionArgs == null) {
cursor = helper.getAllLocations();
} else {
cursor = helper.getSuggestionsData(projection, selection, selectionArgs);
}
break;
case NODE_LOCATION:
cursor = helper.getSingleLocationById(uri.getLastPathSegment());
break;
case NAME_LOCATION:
cursor = helper.getSingleLocationByName(selectionArgs[0]);
break;
case MARKERS:
cursor = helper.getAllMarkers();
break;
case GEOFENCES:
cursor = helper.getAllFences();
break;
case PEOPLE:
if (selectionArgs == null) {
cursor = helper.getAllPeople();
} else {
cursor = helper.findPersonById(selectionArgs[0]);
}
break;
default:
Log.d(URI_ERROR, uri.toString());
}
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
.
.
.
}
로더 Initialsing 어댑터 설정 :
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.options_menu, menu);
SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
MenuItem item = menu.findItem(R.id.action_search);
SearchView view = (SearchView) MenuItemCompat.getActionView(item);
view.setIconified(false);
view.setSearchableInfo(
manager.getSearchableInfo(getComponentName()));
view.setSuggestionsAdapter(adapter);
view.setOnQueryTextListener(this);
getSupportLoaderManager().initLoader(1, null, this);
return true;
}
LoaderManager.LoaderCallbacks 구현 :
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
return new CursorLoader(this, SearchContentProvider.CONTENT_URI, new String[] { DbHelper.ID, DbHelper.LOCATION_NAME, DbHelper.LOCATION_NODE_ID },
DbHelper.LOCATION_NAME + " LIKE ?", new String[] { "%" + cursorFilter + "%"}, null);
}
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
if (!(cursor.isClosed()))
adapter.swapCursor(cursor);
}
}
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
adapter.swapCursor(null);
}
OnQueryTextchange()에서 DbHel
@Override
public boolean onQueryTextChange(String s) {
cursorFilter = !TextUtils.isEmpty(s) ? s : null;
getSupportLoaderManager().restartLoader(0, null, this);
return true;
}
선언 당 :에서 onCreate (에서
public static final String LOCATION_TABLE = "Locations";
public static final String LOCATION_NAME = SearchManager.SUGGEST_COLUMN_TEXT_1;
public static final String LOCATION_NODE_ID = SearchManager.SUGGEST_COLUMN_INTENT_DATA;
선언) :
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, new String[] { DbHelper.LOCATION_NAME },
new int[] { android.R.id.text2 }, 0);
내 질문은 누군가가 전에 이것을 경험, 그렇다면, 당신은 해결책을 발견있다? 아니면 단순히 구현에 잘못 되었습니까?
'query()'의'cursor.setNotificationUri()'다음에'db.close'를 사용하십시오. 함수가 끝나면 데이터베이스 연결을 항상 닫습니다. –
@RohanKandwal 도움을 주셔서 감사합니다, 나는 그 변화를 넣었지만 불행히도 문제를 해결하지는 못합니다. – user3168815
@ user3168815 ContentProvider (Sqlite), LoaderManager 및 CursorAdapter에서도 비슷한 문제가 발견되었습니다. 어떤 해결책을 찾았습니까? – ensecoz