3

私はAndroidにかなり慣れていないので、フィルタリングされたlistViewと、ランドスケープモードからポートレートモードに、またはその逆に変更する際のアクティビティに問題があります。「drinkSearch」のフィルタリングに使用する editText があります。このフィルタリングは、視野角 (縦と横) を変更しない限り機能します。これは私が得るエラーです:

java.lang.IllegalStateException: 既に閉じられているオブジェクトを再度開こうとしています: SQLiteQuery: SELECT _id、名前 FROM ドリンク

次のコードでわかるように、私は LoaderManager.LoaderCallbacks インターフェイスを使用しています。この概念は私にとっては新しいものであり、どこで問題が発生するのかわかりません。事前に感謝します。

public class Drinks_Fragment extends Fragment implement 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 を要求します。(以下のコード、「return view」が上の部分のすぐ下になるまで、同じ 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

4

4 に答える 4

6

あなたのコードは、書式設定が不十分なため、少しわかりにくいです。

とにかく、提供された回答は実際には修正ではありません。で返されたカーソルはonLoadFinished閉じられないことが保証されている必要があるため、カーソルを間違った方法でロードしています。具体的には、お電話の際に

adapter.getFilter().filter(s.toString());

ここで何が起こっているのかよくわかりませんが、何か他のことをしなければならないことは理解しています。クエリ フィルタをフィールドに格納して実行するだけFragmentですgetLoaderManager().restartLoader(DRINKS_LIST_LOADER, null, this);。クエリを実行するデータが異なるため、restartLoaderではなくを実行することに注意してください。initLoader

ではonCreateLoader、 のインスタンス変数として保存したフィルタを使用する必要がありますselection

いくつかの背景

initLoader以前に実行したことがある場合は、最後の実行で読み込まれたデータを読み込みます。これが、フラグメント/アクティビティの初期化メソッドで呼び出す理由です。これは、向きの変更を再クエリする必要がないため便利です。

restartLoader以前にロードされたデータをクリーンアップしてLoader、(可能性が高い) 別のデータを操作するための新しいデータを取得します。


まだ何をしているのかよくわからない場合は、必ずこの記事を読んでください。これは、あなたが達成したいものと非常によく似たサンプル コードを含む、ローダーに関する非常に優れた入門記事です。ローダーは最初はかなり謎めいたものですが、コツをつかめば順風満帆です。

于 2013-10-21T12:14:59.620 に答える
3

修正しました:

@Override public void onLoadFinished(Loader cursorLoader, Cursor cursor) { if(!cursor.isClosed()){ adapter.swapCursor(cursor); } }

現在、別の問題があります。リストが自動的に更新されません...

于 2013-07-08T11:10:56.437 に答える
2

AndroidManifest にこの行を追加すると、同じ状況で役立ちました。

android:configChanges="keyboardHidden|orientation|screenSize"
于 2014-09-18T19:16:15.753 に答える