IllegalStateException - 使用 AutocompleteTextView 支持 LoaderManager
Posted
技术标签:
【中文标题】IllegalStateException - 使用 AutocompleteTextView 支持 LoaderManager【英文标题】:IllegalStateException - Support LoaderManager with AutocompleteTextView 【发布时间】:2012-08-13 12:10:08 【问题描述】:我认为使用 CursorLoaders 和 Loadermanagers 的好处之一是您无需手动管理光标的生命周期。所以我使用 loadermanager 将适配器绑定到使用支持包的 AutoCompleteTextView。
它工作得很好,除了它随机抛出一个错误说“IllegalStateException - 尝试重新打开一个已经关闭的对象”。如果我们使用加载器管理器,这肯定不应该发生吗?
代码如下:
package com.bhagwad.tennis;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter.CursorToStringConverter;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import com.bhagwad.tennis.TennisSchedule.TennisScheduleColumns;
public class WidgetConfiguration extends FragmentActivity implements OnClickListener, LoaderCallbacks<Cursor>
Button mSaveWidget;
AutoCompleteTextView mPlayerName;
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
String mSelection ="";
SimpleCursorAdapter mAdapter;
public static String PREFS = "com.bhagwad.tennis.appwidget";
public static final String PREFS_PREFIX_KEY = "prefix_";
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.widget_configuration);
mPlayerName = (AutoCompleteTextView) findViewById(R.id.edit_filter);
mPlayerName.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
if (!s.equals(""))
mSelection = s.toString();
else
mSelection = "";
getSupportLoaderManager().restartLoader(0, null, WidgetConfiguration.this);
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after)
// TODO Auto-generated method stub
@Override
public void afterTextChanged(Editable s)
// TODO Auto-generated method stub
);
// Set up the adapter
mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, new String[] TennisScheduleColumns.PLAYER_NAME, new int[] android.R.id.text1, 0);
mAdapter.setCursorToStringConverter(new CursorToStringConverter()
@Override
public CharSequence convertToString(Cursor c)
return c.getString(c.getColumnIndexOrThrow(TennisScheduleColumns.PLAYER_NAME));
);
mPlayerName.setAdapter(mAdapter);
getSupportLoaderManager().initLoader(0, null, this);
@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1)
return new CursorLoader(this, TennisScheduleColumns.CONTENT_URI_PLAYERS, new String[] TennisScheduleColumns._ID, TennisScheduleColumns.PLAYER_NAME, TennisScheduleColumns.PLAYER_NAME + " LIKE ?", new String[] "%"+mSelection+"%", null);
@Override
public void onLoaderReset(Loader<Cursor> arg0)
mAdapter.swapCursor(null);
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data)
mAdapter.swapCursor(data);
这是错误堆栈:
08-16 22:21:23.244: E/AndroidRuntime(25475): java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT _id, player_name FROM players WHERE (player_name LIKE ?))
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:33)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:82)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:164)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:147)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:178)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.database.CursorWrapper.moveToPosition(CursorWrapper.java:162)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.support.v4.widget.CursorAdapter.getItem(CursorAdapter.java:213)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.buildImeCompletions(AutoCompleteTextView.java:1113)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.showDropDown(AutoCompleteTextView.java:1072)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.updateDropDownForFilter(AutoCompleteTextView.java:950)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.AutoCompleteTextView.onFilterComplete(AutoCompleteTextView.java:932)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:285)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.os.Handler.dispatchMessage(Handler.java:99)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.os.Looper.loop(Looper.java:137)
08-16 22:21:23.244: E/AndroidRuntime(25475): at android.app.ActivityThread.main(ActivityThread.java:4507)
对可能出现的问题有任何想法吗?
【问题讨论】:
虽然我仍然没有解决方案,但我只是扩展了 AutoCompleteTextView,在围绕“super”语句的 try/catch 循环中捕获了 onFilterComplete 中的错误,忽略它并继续前进。我不知道它为什么会发生或如何处理它。问题解决了。虽然很乱。希望有更优雅的解决方案。 我在这里做类似的事情!! ***.com/questions/12854336/… @BhagwadJalPark 我已经解决了这个问题。 Tony 提出的解决方案(检查 OnLoadFinished 中的关闭状态)对我不起作用。这是我根据您的见解编写的包装类:gist.github.com/esilverberg/5606551 【参考方案1】:OnLoadFinished 似乎有时会被一个死游标调用 - 如果你在你通过的游标上对 isClosed() 进行测试,你会发现它在一次(大量)尝试中关闭。
不幸的是,放在 OnLoadFinished 中的“标准”代码会立即在适配器上执行 changeCursor(),然后接下来是混乱、堆栈转储、瘟疫等。
我的解决方案并不比你的 try/catch 更漂亮。忽略虚假的 OnLoadFinished 并冒最终用户获得空白 UI 的风险。
【讨论】:
谢谢你的花絮。对于这种特殊情况,我完全抛弃了 loadermanager/cursorloaer,并使用 setfilterqueryprovider 实现了另一种方法来执行此操作。但是您的解决方案似乎是最好的方法。也许我们可以在某处提交错误报告?以上是关于IllegalStateException - 使用 AutocompleteTextView 支持 LoaderManager的主要内容,如果未能解决你的问题,请参考以下文章
IllegalStateException:无法订阅。处理器已终止
Java.lang.IllegalStateException:已附加
转:java.lang.IllegalStateException异常产生的原因及解决办法
java.lang.IllegalStateException:片段未附加到活动