我对android很新,我对过滤的listView和从横向模式更改为纵向模式或反之亦然的活动有一些问题。我有一个editText用于过滤“drinkSearch”,只要我不改变视角(人像与风景),这个过滤就有效。这是我得到的错误:
java.lang.IllegalStateException:尝试重新打开已经关闭的 object:SQLiteQuery:SELECT _id,name FROM drinks
正如您在下面的代码中看到的,我使用的是LoaderManager.LoaderCallbacks接口,这个概念对我来说有点新,我不确定 出了问题。我将非常感谢所有的帮助,在此先感谢!
public class Drinks_Fragment extends Fragment实现LoaderManager.LoaderCallbacks {
private static final int DRINKS_LIST_LOADER = 0x01;
private SimpleCursorAdapter adapter;
private ListView drinksList;
private String LOG;
private EditText drinkSearch;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.drinks_list, container, false);
drinkSearch = (EditText)view.findViewById(R.id.drinkInputSearch);
drinksList = (ListView) view.findViewById(R.id.drinksList);
drinksList.setEmptyView(view.findViewById(R.id.empty_list_view));
String[] from = {DrinksTable.COLUMN_NAME};
int[] to = {R.id.drinkName};
getLoaderManager().initLoader(DRINKS_LIST_LOADER, null, this);
adapter = new SimpleCursorAdapter(getActivity().getApplicationContext(), R.layout.drinks_list_item,null, from, to, 0);
drinksList.setAdapter(adapter);
在这部分中,我根据searchDrink editText中输入的字符串向contentProvider询问新的Cursor。 (以下代码,直到“返回视图”正好在上面的部分下方,同样的onCreateView方法)
drinkSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int arg1, int arg2, int arg3) {
// When user changed the Text
adapter.getFilter().filter(s.toString());
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
String value = "%"+constraint.toString()+"%";
ContentResolver content = getActivity().getContentResolver();
return content.query(CupProvider.DRINKS_URI,new String[]{DrinksTable.COLUMN_ID,DrinksTable.COLUMN_NAME},DrinksTable.COLUMN_NAME + " LIKE ?",new String[]{value},null);
}
});
return view;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu,v,menuInfo);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.drink_actions,menu);
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
String[] projection = {DrinksTable.COLUMN_ID, DrinksTable.COLUMN_NAME};
CursorLoader cursorLoader = new CursorLoader(getActivity(), CupProvider.DRINKS_URI, projection, null, null, null);
return cursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
adapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
// data is not available anymore, delete reference
adapter.swapCursor(null);
}
}
以下是2张图片,展示了当下的情况:http://oi42.tinypic.com/dfc702.jpg http://oi43.tinypic.com/2ylqkqa.jpg
答案 0 :(得分:6)
由于格式不佳,您的代码有点难以理解。
无论如何,提供的答案实际上不是解决方法。应保证在onLoadFinished
返回的光标不会被关闭,因此您以错误的方式加载光标。具体来说,当你打电话
adapter.getFilter().filter(s.toString());
我真的不明白这里发生了什么,但我明白你应该做点什么。只需将查询过滤器存储在Fragment
中的字段中,然后运行getLoaderManager().restartLoader(DRINKS_LIST_LOADER, null, this);
即可。请注意,您运行的是restartLoader
,而不是initLoader
,因为您要查询的数据不同。
在onCreateLoader
中,您应该使用存储的过滤器作为selection
的实例变量。
initLoader
加载上次运行中加载的数据(如果之前已运行过)。这就是你在Fragment / Activity的初始化方法中调用的原因。这很方便,因为您不必重新查询方向更改。
restartLoader
清理以前加载的数据,以便您获得一个新的Loader
来处理(可能)不同的数据。
如果您还不确定自己在做什么,请务必阅读this article,这是一篇关于Loaders的非常好的介绍性文章,其示例代码非常类似于您想要实现的内容。装载机起初非常神秘,但是一旦掌握了它,它就会顺利进行。
答案 1 :(得分:2)
修正了它:
@覆盖 public void onLoadFinished(Loader cursorLoader,Cursor cursor){ 如果(!cursor.isClosed()){ adapter.swapCursor(光标); } }
我现在有另一个问题,我的列表没有自动更新...
答案 2 :(得分:1)
在AndroidManifest中添加这一行帮助了我同样的情况:
android:configChanges="keyboardHidden|orientation|screenSize"
答案 3 :(得分:1)
这是因为在过滤之后,原始游标被关闭,因为调用了changeCursor。覆盖changeCursor:
super.swapCursor(cursor)
SimpleCursorAdapter中的确保原始游标由CursorLoader管理。