使用 SQLiteDatabase 为 AutoCompleteTextView 迁移到 CursorLoader 和 LoaderManager
Migrating to CursorLoader & LoaderManager for AutoCompleteTextView with SQLiteDatabase
我有一个 AutoCompleteTextView
,它显示了从 SQLiteDatabase
查询中获得的建议下拉列表。目前它使用 SimpleCursorAdapter
,但是它有几个问题(我在这里有一个关于这个问题的单独问题:SimpleCursorAdapter issue - "java.lang.IllegalStateException: trying to requery an already closed cursor")。
不过,建议我往CursorLoader
和LoaderManager
的方向看,我试过了,还是不行.如果有人 guide/recommend/show 将我的代码迁移到 CursorLoader/LoaderManager 概念的正确方法,我将不胜感激。非常感谢任何形式的帮助!
mAdapter = new SimpleCursorAdapter(this,
R.layout.dropdown_text,
null,
new String[]{CITY_COUNTRY_NAME},
new int[]{R.id.text}, 0);
mAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
cityCountryName = cursor.getString(cursor.getColumnIndexOrThrow(CITY_COUNTRY_NAME));
mAutoCompleteTextView.setText(cityCountryName);
JSONWeatherTask task = new JSONWeatherTask();
task.execute(new String[]{cityCountryName});
}
});
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence sequence) {
String constraint = sequence.toString();
String queryString = "SELECT " + ID + ", " + CITY_ID + ", " + CITY_COUNTRY_NAME + " FROM " + TABLE_1;
constraint = constraint.trim() + "%";
queryString += " WHERE " + CITY_COUNTRY_NAME + " LIKE ?";
String params[] = {constraint};
try {
Cursor cursor = database.rawQuery(queryString, params);
if (cursor != null) {
startManagingCursor(cursor);
cursor.moveToFirst();
return cursor;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
});
mAutoCompleteTextView.setAdapter(mAdapter);
这是供参考的整个项目(如果你愿意,你可以在那里提出拉取请求):Open Weather App
不幸的是,在 SO 上没有人提出解决方案,但一位同事(他没有 SO 帐户)提出了一个包含迁移修复的拉取请求。它工作得很好,我决定 post 这里也给出正确答案。
如果您对这些改进在实际代码中的表现感兴趣,欢迎访问 GitHub 上的原始开源项目页面:Open Weather App
这是新适配器:
mAdapter = new SimpleCursorAdapter(this,
R.layout.dropdown_text,
null,
new String[]{CITY_COUNTRY_NAME},
new int[]{R.id.text},0);
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
if (constraint != null) {
if (constraint.length() >= 3 && !TextUtils.isEmpty(constraint)) {
Bundle bundle = new Bundle();
String query = charArrayUpperCaser(constraint);
bundle.putString(CITY_ARGS, query);
getLoaderManager().restartLoader(0, bundle, MainActivity.this).forceLoad();
}
}
return null;
}
});
这是 onCreateLoader()
回调:
@Override
public android.content.Loader<Cursor> onCreateLoader(int id, Bundle args) {
String s = args.getString(CITY_ARGS);
WeatherCursorLoader loader = null;
if (s != null && !TextUtils.isEmpty(s)) {
loader = new WeatherCursorLoader(this, database, s);
}
return loader;
}
自定义CursorLoader
本身:
private static class WeatherCursorLoader extends CursorLoader {
private SQLiteDatabase mSQLiteDatabase;
private String mQuery;
WeatherCursorLoader(Context context, SQLiteDatabase cDatabase, String s) {
super(context);
mSQLiteDatabase = cDatabase;
mQuery = s + "%";
Log.d(TAG, "WeatherCursorLoader: " + mQuery);
}
@Override
public Cursor loadInBackground() {
return mSQLiteDatabase.query(TABLE_1, mProjection,
CITY_COUNTRY_NAME + " like ?", new String[] {mQuery},
null, null, null, "50");
}
}
我有一个 AutoCompleteTextView
,它显示了从 SQLiteDatabase
查询中获得的建议下拉列表。目前它使用 SimpleCursorAdapter
,但是它有几个问题(我在这里有一个关于这个问题的单独问题:SimpleCursorAdapter issue - "java.lang.IllegalStateException: trying to requery an already closed cursor")。
不过,建议我往CursorLoader
和LoaderManager
的方向看,我试过了,还是不行.如果有人 guide/recommend/show 将我的代码迁移到 CursorLoader/LoaderManager 概念的正确方法,我将不胜感激。非常感谢任何形式的帮助!
mAdapter = new SimpleCursorAdapter(this,
R.layout.dropdown_text,
null,
new String[]{CITY_COUNTRY_NAME},
new int[]{R.id.text}, 0);
mAutoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
cityCountryName = cursor.getString(cursor.getColumnIndexOrThrow(CITY_COUNTRY_NAME));
mAutoCompleteTextView.setText(cityCountryName);
JSONWeatherTask task = new JSONWeatherTask();
task.execute(new String[]{cityCountryName});
}
});
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence sequence) {
String constraint = sequence.toString();
String queryString = "SELECT " + ID + ", " + CITY_ID + ", " + CITY_COUNTRY_NAME + " FROM " + TABLE_1;
constraint = constraint.trim() + "%";
queryString += " WHERE " + CITY_COUNTRY_NAME + " LIKE ?";
String params[] = {constraint};
try {
Cursor cursor = database.rawQuery(queryString, params);
if (cursor != null) {
startManagingCursor(cursor);
cursor.moveToFirst();
return cursor;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
});
mAutoCompleteTextView.setAdapter(mAdapter);
这是供参考的整个项目(如果你愿意,你可以在那里提出拉取请求):Open Weather App
不幸的是,在 SO 上没有人提出解决方案,但一位同事(他没有 SO 帐户)提出了一个包含迁移修复的拉取请求。它工作得很好,我决定 post 这里也给出正确答案。
如果您对这些改进在实际代码中的表现感兴趣,欢迎访问 GitHub 上的原始开源项目页面:Open Weather App
这是新适配器:
mAdapter = new SimpleCursorAdapter(this,
R.layout.dropdown_text,
null,
new String[]{CITY_COUNTRY_NAME},
new int[]{R.id.text},0);
mAdapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
if (constraint != null) {
if (constraint.length() >= 3 && !TextUtils.isEmpty(constraint)) {
Bundle bundle = new Bundle();
String query = charArrayUpperCaser(constraint);
bundle.putString(CITY_ARGS, query);
getLoaderManager().restartLoader(0, bundle, MainActivity.this).forceLoad();
}
}
return null;
}
});
这是 onCreateLoader()
回调:
@Override
public android.content.Loader<Cursor> onCreateLoader(int id, Bundle args) {
String s = args.getString(CITY_ARGS);
WeatherCursorLoader loader = null;
if (s != null && !TextUtils.isEmpty(s)) {
loader = new WeatherCursorLoader(this, database, s);
}
return loader;
}
自定义CursorLoader
本身:
private static class WeatherCursorLoader extends CursorLoader {
private SQLiteDatabase mSQLiteDatabase;
private String mQuery;
WeatherCursorLoader(Context context, SQLiteDatabase cDatabase, String s) {
super(context);
mSQLiteDatabase = cDatabase;
mQuery = s + "%";
Log.d(TAG, "WeatherCursorLoader: " + mQuery);
}
@Override
public Cursor loadInBackground() {
return mSQLiteDatabase.query(TABLE_1, mProjection,
CITY_COUNTRY_NAME + " like ?", new String[] {mQuery},
null, null, null, "50");
}
}