从游标在Android中填写的ListView [英] Fill ListView from a cursor in Android

查看:159
本文介绍了从游标在Android中填写的ListView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经花了很多时间寻找和阅读类似的职位,但他们似乎真实地反映我的问题,因此我还没有发现任何东西,对我的作品。 我有一个数据库,对我进行查询,它的结果存储在一个游标。有两件事情是: -the查询执行每次一定按钮pressed(这样的查询是OnClickListener内该按钮) -the查询返回两个不同的列与字符串值,必须单独处理(一个列存储必须在ListView被显示的姓名,所述其他商店的路径的图像相关联的TOA行) 我的问题是,我尝试创建一个String []我需要传递给一个Ar​​rayAdapter创作者为ListView,但试图将其指定光标getCount将的大小()崩溃我的活动。我希望code将更多的解释:

  OnClickListener searchListener =新OnClickListener(){
    公共无效的onClick(视图v){
    CardDatabaseOpenHelper帮手=新
    CardDatabaseOpenHelper(DeckEditorScreen1.this);
    SQLiteDatabase DB = helper.getReadableDatabase();

    字符串列[] = {姓名,号码,路径};

    光标C = db.query(卡,列,NULL,NULL,NULL,NULL,数字);
    诠释计数= c.getCount();
    的String [] resultNameStrings;
    如果(!计数= 0)resultNameStrings =新的String [统计]
        其他{resultNameStrings =新的String [1]; resultNameStrings [1] =没有结果;}
        //这是有问题的code
    //注意,如果我分配固定值,resutNameStrings,在code的工作方式
        //精细
        的for(int i = 0; I<计数;我++){
        c.moveToNext();
        INT COL = c.getColumnIndex(姓名);
        字符串s = c.getString(COL);
            //理想情况下我会喜欢的东西:
            // resultNameStrings [i] = S;
        COL = c.getColumnIndex(数字);
        INT兑换= c.getInt(COL);
        COL = c.getColumnIndex(路径);
        字符串s2 = c.getString(COL);
    }
    db.close();

    ArrayAdapter<> sea​​rchResultItemAdapter =新的ArrayAdapter<字符串>
                                                  (DBScreen.this,
                                                  R.layout.search_result_item,
                                                  resultNameStrings);
    ListView控件searchResultList =(ListView控件)
                              DBScreen.this.findViewById(R.id.search_result_list);
    sea​​rchResultList.setAdapter(searchResultItemAdapter);
    }
};
按钮search_button =(按钮)findViewById(R.id.search_button);
sea​​rch_button.setOnClickListener(searchListener);
 

解决方案

EDITED 两次:)

做到这一点在安卓之路......

第一次使用的CursorAdapter(FX:SimpleCursorAdapter与overrided

 公开光标runQueryOnBackgroundThread(CharSequence的约束){
            光标光标= managedQuery(MobileTraderProvider.CONTENT_URI,
                    NULL,NULL,新的String [] {constraint.toString()},NULL);
            返回游标;
        }
 

然后

  customAdapter.getFilter()。过滤器(filterText)
//它会调用runQueryOnBackgroundThread
 

第二次使用的ContentProvider(它会管理curosors你...它甚至会重新查询数据是否改变)

编辑:

第一次真正使用我的意见

第二

 的for(int i = 0; I<计数;我++){
        c.moveToNext();
// ...
 

补充c.moveToFirst();

THRID:使用

 如果(c.moveToNext())
{
  INT COL = c.getColumnIndex(姓名);
// .....休息到这里
}
 

第二个编辑:

MyProvider.java

 公共类MYPROVIDER扩展ContentProvider的{

    静态最后弦乐LTAG =MyAppName;

    公共静态最终乌里CONTENT_URI = Uri.parse(内容://my.app.Content);


    静态最终诠释卡= 1;
    静态最终诠释卡= 2;
    公共静态最后弦乐CARDS_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +/卡;
    公共静态最后弦乐CARD_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE +/卡;
    静态最终UriMatcher匹配=新UriMatcher(UriMatcher.NO_MATCH);
    静态最后的HashMap<字符串,字符串>图=新的HashMap<字符串,字符串>();

    静态{
        //静态的构造
        matcher.addURI(Constants.AUTHORITY,卡,列表);
        matcher.addURI(Constants.AUTHORITY,卡/ *,LIST);
        map.put(BaseColumns._ID,ROWID AS _id);
        map.put(Tables.Cards.C_NAME,Tables.Cards.C_NAME);
        map.put(Tables.Cards.C_NUMBER,Tables.Cards.C_NUMBER);
        map.put(Tables.Cards.C_PATH,Tables.Cards.C_PATH);
    }

    私人CardDatabaseOpenHelper MDB;

    @覆盖
    公共布尔的onCreate(){
        尝试 {
            MDB =新CardDatabaseOpenHelper(的getContext());
        }赶上(例外五){
            Log.e(LTAG,e.getLocalizedMessage());
        }
        返回true;
    }

    公众诠释删除(URI URI,弦乐选择,字符串[] selectionArgs两个){
        字符串表= NULL;
        开关(matcher.match(URI)){
            病例卡:
                //压倒一切的选择和selectionArgs两个
                选择=ROWID =?;
                selectionArgs两个=新的String [] {uri.getPathSegments()获取(1)};
                表= uri.getPathSegments()得到(0)。
                打破;
            案例卡:
                //这个版本将删除所有行,如果你不提供选择和selectionArgs两个
                表= uri.getPathSegments()得到(0)。
                打破;
            默认:
                抛出新抛出:IllegalArgumentException(未知的URL+ URI);
        }
        。INT RET = mDB.getWritableDatabase()删除(表,选择,selectionArgs两个);
        。的getContext()getContentResolver()有NotifyChange(Uri.withAppendedPath(CONTENT_URI,表),空)。
        返回RET;
    }

    @覆盖
    公共字符串的getType(URI URI){
        开关(matcher.match(URI)){
            案例卡:
                返回CARDS_MIME_TYPE;
            病例卡:
                返回CARD_MIME_TYPE;
            默认:
                抛出新抛出:IllegalArgumentException(未知的URL+ URI);
        }
    }

    公众诠释更新(开放的我们的URI,ContentValues​​价值观,选择字符串,字符串[] selectionArgs两个){
        字符串表的rowid;
        开关(matcher.match(URI)){
            病例卡:
                //压倒一切的选择和selectionArgs两个
                选择=ROWID =?;
                selectionArgs两个=新的String [] {uri.getPathSegments()获取(1)};
                表= uri.getPathSegments()得到(0)。
                打破;
            案例卡:
                //如果你不提供选择和selectionArgs两个该版本将更新所有行
                表= uri.getPathSegments()得到(0)。
                打破;
            默认:
                抛出新抛出:IllegalArgumentException(未知的URL+ URI);
        }
        INT RET = mDB.getWritableDatabase()更新(表值,选择selectionArgs两个)。
        。的getContext()getContentResolver()有NotifyChange(Uri.withAppendedPath(CONTENT_URI,表),空)。
        返回RET;
    }

    公众开放的插入(URI URI,ContentValues​​值){
        字符串表= NULL;
        开关(matcher.match(URI)){
            案例卡:
                表= uri.getPathSegments()得到(0)。
                打破;
            默认:
                抛出新抛出:IllegalArgumentException(未知的URL+ URI);
        }
        mDB.getWritableDatabase()插入(表,空,价值观)。
        。的getContext()getContentResolver()有NotifyChange(Uri.withAppendedPath(CONTENT_URI,表),空)。
        返回null;
    }

    公共光标查询(URI URI,字符串[]投影,串选择,
            的String [] selectionArgs两个,串排序顺序){
        SQLiteQueryBuilder建设者=新SQLiteQueryBuilder();
        开关(matcher.match(URI)){
            案例卡:
                builder.setTables(uri.getPathSegments()得到(0));
                打破;
            病例卡:
                builder.setTables(uri.getPathSegments()得到(0));
                选择=ROWID =?;
                selectionArgs两个=新的String [] {uri.getPathSegments()获取(1)};
            默认:
                抛出新抛出:IllegalArgumentException(未知的URL+ URI);
        }
        builder.setProjectionMap(图)
        光标光标= builder.query(mDB.getReadableDatabase(),投影,选择,selectionArgs两个,NULL,NULL,排序顺序);
        如果(光标== NULL){
            返回null;
        }
        cursor.setNotificationUri(的getContext()getContentResolver(),URI);
        返回游标;
    }
}
 

CardCursorAdapter.java

 类CardCursorAdapter扩展SimpleCursorAdapter {

    公共MyCursorAdapter(上下文的背景下,INT布局,光标C,
            的String []从,INT []键){
        超(背景下,布局,C,从,到);
    }

@覆盖
公共光标runQueryOnBackgroundThread(CharSequence的约束){
    //在cards.name搜索
    串选择= Tables.Cards.C_NAME +怎么样?;
    的String [] selectionArgs两个=新的String [] {%+ constraint.toString()+%};
    光标光标= managedQuery(Uri.withAppendedPath(MyProvider.CONTENT_URI,Tables.Cards.Name)
        getCursor()getColumnNames(),选择,selectionArgs两个,空)。
    返回游标;
}
}
 

Tables.java

 公共静态类表{
    //表定义
    公共静态接口卡{
        公共静态最终字符串名称=卡;
        公共静态最后弦乐C_NAME =名;
        公共静态最后弦乐C_NUMBER =号;
        公共静态最后弦乐C_PATH =路径;
    }
    //其他表放在这里
}
 

AndroidManifest.xml中

 < /舱单>
        < /用途>
            <  - !......其他的东西......  - >
            <提供机器人:名称=MYPROVIDER安卓当局=my.app.Content/>
        < /用途>
< /舱单>
 

然后在活动

 的onCreate(...){

    listView.setAdapter(新CardCursorAdapter(这一点,R.layout.listrow,
        managedQuery(Uri.withAppendedPath(MyProvider.CONTENT_URI,Tables.Cards.NAME)
            新的String [] {BaseColumns._ID,Tables.Cards.C_NAME,Tables.Cards.C_NUMBER,Tables.Cards.C_PATH},
            NULL,NULL,数量),
        新的String [] {Tables.Cards.C_NAME,Tables.Cards.C_NUMBER,Tables.Cards.C_PATH},
        新的INT [] {R.id.tName,R.id.tNumber,R.id.tPath}));
}


OnClickListener searchListener =新OnClickListener(){
    公共无效的onClick(视图v){
        。DeckEditorScreen1.this.listView.getAdapter()用getFilter()过滤器(文本中卡表的名称列搜索设为我清空所有行);
    }
}
 

I've spent a lot of hours searching and reading similar posts, but none of them seem to truly reflect my problem and thus I haven't found anything that works for me. I've got a database, on which I perform a query, the results of which are stored in a cursor. There's two things to that: -the query is performed everytime a certain button is pressed (thus the query is inside the OnClickListener for that Button) -the query returns two different columns with String values, which must be treated separately (one column stores the names which must be shown in the ListView, the other stores the paths to the image associated toa row) My problem is, I try to create a String[] which I need to pass to the ArrayAdapter creator for the ListView, but trying to assign it a size of Cursor getCount() crashes my activity. I hope the code will be more of an explanation:

OnClickListener searchListener = new OnClickListener() {
    public void onClick(View v) {
    CardDatabaseOpenHelper helper = new 
    CardDatabaseOpenHelper(DeckEditorScreen1.this);
    SQLiteDatabase db = helper.getReadableDatabase();

    String columns[] = {"name","number","path"};

    Cursor c = db.query("cards", columns, null, null, null, null, "number");
    int count = c.getCount();
    String[] resultNameStrings;
    if (count != 0) resultNameStrings = new String[count];
        else {resultNameStrings = new String[1]; resultNameStrings[1] = "No results";} 
        // This is the offending code
    //Note that if I assign fixed values to resutNameStrings, the code works just
        //fine
        for (int i = 0; i < count; ++i) {
        c.moveToNext();
        int col = c.getColumnIndex("name");
        String s = c.getString(col);
            //Ideally here I would to something like:
            //resultNameStrings[i] = s;
        col = c.getColumnIndex("number");
        int conv = c.getInt(col);
        col = c.getColumnIndex("path");
        String s2 = c.getString(col);
    }
    db.close();

    ArrayAdapter<?> searchResultItemAdapter = new ArrayAdapter<String>
                                                  (DBScreen.this,
                                                  R.layout.search_result_item,
                                                  resultNameStrings);
    ListView searchResultList = (ListView)
                              DBScreen.this.findViewById(R.id.search_result_list);
    searchResultList.setAdapter(searchResultItemAdapter);
    }
};
Button search_button = (Button) findViewById(R.id.search_button);
search_button.setOnClickListener(searchListener);

解决方案

EDITED twice :)

do it in "Android Way" ...

first use CursorAdapter (fx.: SimpleCursorAdapter with overrided

public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
            Cursor cursor = managedQuery(MobileTraderProvider.CONTENT_URI,
                    null, null, new String[] { constraint.toString() }, null);
            return cursor;
        }

then

customAdapter.getFilter().filter(filterText) 
// it will call runQueryOnBackgroundThread

second use ContentProvider(it will manage curosors for you ... it will even requery if data changed)

EDIT:

first really use my advice

second before

for (int i = 0; i < count; ++i) {
        c.moveToNext();
//...

add c.moveToFirst();

thrid: use

if(c.moveToNext()) 
{ 
  int col = c.getColumnIndex("name"); 
//..... rest goes here
}

SECOND EDIT:

MyProvider.java

public class MyProvider extends ContentProvider {

    static final String LTAG = "MyAppName";

    public static final Uri CONTENT_URI = Uri.parse("content://my.app.Content");


    static final int CARDS = 1;
    static final int CARD = 2;
    public static final String CARDS_MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/Cards";
    public static final String CARD_MIME_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/Cards";
    static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    static final HashMap<String, String> map = new HashMap<String, String>();

    static {
        //static "Constructor"
        matcher.addURI(Constants.AUTHORITY, "Cards", LISTS);
        matcher.addURI(Constants.AUTHORITY, "Cards/*", LIST);
        map.put(BaseColumns._ID, "ROWID AS _id");
        map.put(Tables.Cards.C_NAME, Tables.Cards.C_NAME);
        map.put(Tables.Cards.C_NUMBER, Tables.Cards.C_NUMBER);
        map.put(Tables.Cards.C_PATH, Tables.Cards.C_PATH);
    }

    private CardDatabaseOpenHelper mDB;

    @Override
    public boolean onCreate() {
        try {
            mDB = new CardDatabaseOpenHelper(getContext());
        } catch (Exception e) {
            Log.e(LTAG, e.getLocalizedMessage());
        }
        return true;
    }

    public int delete(Uri uri, String selection, String[] selectionArgs) {
        String table = null;
        switch (matcher.match(uri)) {
            case CARD:
                //overriding selection and selectionArgs
                selection = "ROWID=?";
                selectionArgs = new String[] { uri.getPathSegments().get(1) };
                table = uri.getPathSegments().get(0);
                break;
            case CARDS: 
                //this version will delete all rows if you dont provide selection and selectionargs
                table = uri.getPathSegments().get(0);
                break;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
        int ret = mDB.getWritableDatabase().delete(table, selection, selectionArgs);
        getContext().getContentResolver().notifyChange(Uri.withAppendedPath(CONTENT_URI, table), null);
        return ret;     
    }

    @Override
    public String getType(Uri uri) {
        switch (matcher.match(uri)) {
            case CARDS:
                return CARDS_MIME_TYPE;
            case CARD:
                return CARD_MIME_TYPE;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
    }

    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        String table, rowid;
        switch (matcher.match(uri)) {
            case CARD:
                //overriding selection and selectionArgs
                selection = "ROWID=?";
                selectionArgs = new String[] { uri.getPathSegments().get(1) };
                table = uri.getPathSegments().get(0);
                break;
            case CARDS: 
                //this version will update all rows if you dont provide selection and selectionargs
                table = uri.getPathSegments().get(0);
                break;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
        int ret = mDB.getWritableDatabase().update(table, values, selection, selectionArgs);
        getContext().getContentResolver().notifyChange(Uri.withAppendedPath(CONTENT_URI, table), null);
        return ret;
    }

    public Uri insert(Uri uri, ContentValues values) {
        String table = null;
        switch (matcher.match(uri)) {
            case CARDS:
                table = uri.getPathSegments().get(0);
                break;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
        mDB.getWritableDatabase().insert(table, null, values);
        getContext().getContentResolver().notifyChange(Uri.withAppendedPath(CONTENT_URI, table), null);
        return null;
    }

    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
        switch (matcher.match(uri)) {
            case CARDS:
                builder.setTables(uri.getPathSegments().get(0));
                break;
            case CARD:
                builder.setTables(uri.getPathSegments().get(0));
                selection = "ROWID=?";
                selectionArgs = new String[] { uri.getPathSegments().get(1) };  
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
        }
        builder.setProjectionMap(map);
        Cursor cursor = builder.query(mDB.getReadableDatabase(), projection, selection, selectionArgs, null, null, sortOrder);
        if (cursor == null) {
            return null;
        }
        cursor.setNotificationUri(getContext().getContentResolver(), uri);
        return cursor;      
    }       
}

CardCursorAdapter.java

class CardCursorAdapter extends SimpleCursorAdapter {

    public MyCursorAdapter(Context context, int layout, Cursor c,
            String[] from, int[] to) {
        super(context, layout, c, from, to);
    }

@Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
    //search in cards.name
    String selection = Tables.Cards.C_NAME + " LIKE ?";
    String[] selectionArgs = new String[] {"%" + constraint.toString() + "%"};
    Cursor cursor = managedQuery(Uri.withAppendedPath(MyProvider.CONTENT_URI, Tables.Cards.Name), 
        getCursor().getColumnNames(), selection, selectionArgs, null);
    return cursor;
}
}

Tables.java

public static class Tables {
    //table definition
    public static interface Cards {
        public static final String NAME = "cards";
        public static final String C_NAME = "name";
        public static final String C_NUMBER = "number";
        public static final String C_PATH = "path";
    }
    //other tables go here
}

AndroidManifest.xml

</manifest> 
        </application>
            <!-- ....... other stuff    ....... -->
            <provider android:name="MyProvider" android:authorities="my.app.Content" />
        </application>
</manifest>

then in activity

onCreate(...){

    listView.setAdapter(new CardCursorAdapter(this, R.layout.listrow, 
        managedQuery(Uri.withAppendedPath(MyProvider.CONTENT_URI, Tables.Cards.NAME),
            new String[] { BaseColumns._ID, Tables.Cards.C_NAME, Tables.Cards.C_NUMBER, Tables.Cards.C_PATH },
            null,null, number), 
        new String[] { Tables.Cards.C_NAME, Tables.Cards.C_NUMBER, Tables.Cards.C_PATH  }, 
        new int[] { R.id.tName, R.id.tNumber, R.id.tPath }));
}


OnClickListener searchListener = new OnClickListener() {
    public void onClick(View v) {
        DeckEditorScreen1.this.listView.getAdapter().getFilter().filter("text for search in name column of card table set me to empty for all rows");
    }
}

这篇关于从游标在Android中填写的ListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆