1

要するに、リストビューを標準の SimpleQueryAdapter でフィルタリングしていますが、カスタムの SimplyQueryAdapter 実装を適用しようとすると例外が発生し、理由がわかりません。

カットダウンレベルでは、アイテムをリストするアプリケーションがあります。ユーザーが関連する EditView に入力した内容を介して、これらの結果を「動的に」フィルタリングする方法を実装しようとしています。

テスト目的で、私のコードにはリストの一番上にボタンがあり、ボタンをクリックすると FilterQueryProvider が割り当てられ、ハードコーディングされた制約文字列が提供されます。これは、テキストフィールドに「ob」などを入力する人をエミュレートします。

問題は、カスタム SimpleQueryAdapter を介して入力されたリストに対して実行しようとしたときです。ボタンをクリックするたびにリストが縮小されますが、間違った項目が表示され、「java.lang.IllegalStateException」も発生します。たとえば、「ob」を検索すると、「robert」ではなく「andrew」が表示されます。今のところ、もっと心配なのは例外です。

完全な例外は次のとおりです。

04-15 12:23:25.099: ERROR/2130968577MySimpleCursorAdapter.getView(577): java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT _id, idSite, idSiteUser, idUser, siteName, siteType, siteUrlIcon, dateModified, siteStatus FROM site WHERE idUser=14742 ORDER BY siteName DESC)

Queryadapter に問題があると思われる理由は、非カスタム SimpleQueryAdapter の使用に切り替えようとすると、完全に機能するためです。ただし、遅延アイコンの読み込みなどを使用しているため、カスタムアダプターを実装する必要があります.

フィルターではなく WHERE LIKE ('%blah%') を使用してテーブルを検索したいので、この方法でフィルター処理を行っています。このスレッドでアイデアを見つけました: FilterQueryProvider、filter、ListView

例外に基づいて、カーソルが閉じられているようですが、どこでも close を呼び出していないため、アダプターは StartManagingCursor を介して自動的に管理する必要があります。データベース接続とカーソルに関して何か間違っていますか? 私の FilterQueryProvider の使用は正しく見えますか?

これがコードです。簡潔にするために再構成されています

ここに私のメインListActivityがあります:

        public class ChannelListContainer extends ListActivity {
    Context context;
    private MyDBAdapter db;
    private int dummyUserId = 14742;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = this.getApplicationContext();

        setContentView(R.layout.channellist);    

        /* open database connection */
        db = new MyDBAdapter(context); 
        db.open();        

        Cursor c = db.fetchAllSites(dummyUserId);
        startManagingCursor(c);

        String[] from = new String[] {DBAdapter.KEY_SITE_NAME}; 
        int[] to = new int[] {R.id.channel_name};

        /// Code using my custom SimpleCursorAdapter (does not work). By swapping between my addapter and the standard cursor adapter i can make it work/not work
        MySimpleCursorAdapter channels = new MySimpleCursorAdapter(this, R.layout.list_item, c, from, to);
        setListAdapter(channels);

    /// Code not using my custom SimpleCursorAdapter (works)
        //SimpleCursorAdapter channels = new SimpleCursorAdapter(this, R.layout.list_item, c, from, to);
        //setListAdapter(channels);
    }       

    private void filterList(CharSequence _constraint) { 
        /// Code using my custom SimpleCursorAdapter (does not work)
        //final MySimpleCursorAdapter channels = (MySimpleCursorAdapter) getListAdapter();

        /// Code not using my custom SimpleCursorAdapter (works)
        final SimpleCursorAdapter channels = (SimpleCursorAdapter) getListAdapter();


        final Cursor oldCursor = channels.getCursor();
        Filter filter;

        channels.setFilterQueryProvider(filterQueryProvider);
        filter = channels.getFilter();
        filter.filter(_constraint, new FilterListener() {
            public void onFilterComplete(int count) {
                stopManagingCursor(oldCursor);
                final Cursor newCursor = channels.getCursor();
                startManagingCursor(newCursor);

                if (oldCursor != null && !oldCursor.isClosed()) {
                    oldCursor.close();
                }
            }

        });
    }

    private FilterQueryProvider filterQueryProvider = new FilterQueryProvider() {
        public Cursor runQuery(CharSequence _constraint) {

            db = new MyDBAdapter(context);
            db.open();
            Cursor c = db.fetchAllSitesByName(dummyUserId, (String) _constraint);

            return c;   
        }
    };

    // filter the list when button called. Demo to filter list to "To Do" item.
    public void onClick(View _view) {
        filterList("To Do");
    }   
}

これが私のカスタムSimpleCursorAdapterです:

public class MySimpleCursorAdapter extends SimpleCursorAdapter{
    String[] from;
    Cursor c; 
    private static LayoutInflater inflater=null;

    int INDEX_ROWID = 0; 
    int INDEX_IDSITE = 1;
    int INDEX_IDSITEUSER = 2;
    int INDEX_IDUSER = 3;
    int INDEX_SITE_NAME = 4;
    int INDEX_SITE_TYPE = 5;
    int INDEX_SITE_URL_ICON = 6;
    int INDEX_DATE_MODIFIED = 7;

    public MySimpleCursorAdapter(Activity activity, int layout, Cursor cursor, String[] from, int[] to) {

        super(activity.getApplicationContext(), layout, cursor, from, to);
        this.from = from;
        this.c = cursor;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public static class ViewHolder{
        public TextView channel_name;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;   

        try {
            ViewHolder holder;
            if (this.c.moveToPosition(position)) {
                if(convertView==null){
                    vi = inflater.inflate(R.layout.list_item, null);
                    holder=new ViewHolder(); 
                    holder.channel_name=(TextView)vi.findViewById(R.id.channel_name);
                    vi.setTag(holder); 
                }
                else {
                    holder=(ViewHolder)vi.getTag();
                }                 

                holder.channel_name.setText(c.getString(INDEX_SITE_NAME));

                return vi;  
            }

        } catch (Exception e) {
            Log.e(R.string.app_name + "MySimpleCursorAdapter.getView",e.toString());
        }
        return vi;  
    }
}

データベースを開く:

public MyDBAdapter(Context _context) {
    context = _context;
    dbHelper = new myDbHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
}

public MyDBAdapter open() throws SQLException {
    db = dbHelper.getWritableDatabase();
    return this;
}

どんな助けでも大歓迎です。

ありがとう、ロブ

4

0 に答える 0