【问题标题】:Images in SimpleCursorAdapterSimpleCursorAdapter 中的图像
【发布时间】:2011-10-06 08:04:49
【问题描述】:

我正在尝试使用SimpleCursorAdapterViewBinder 从数据库中获取图像并将其放入我的ListView 项目视图中。这是我的代码:

private void setUpViews() {
    mNewsView = (ListView) findViewById(R.id.news_list);

    Cursor cursor = getNews();
    SimpleCursorAdapter curAdapter = new SimpleCursorAdapter(
            getApplicationContext(), R.layout.cursor_item, cursor,
            new String[] { "title", "content", "image" },
            new int[] { R.id.cursor_title, R.id.cursor_content,
                    R.id.news_image });
    
    ViewBinder viewBinder = new ViewBinder() {
        
        public boolean setViewValue(View view, Cursor cursor,
                int columnIndex) {
            ImageView image = (ImageView) view;
            byte[] byteArr = cursor.getBlob(columnIndex);
            image.setImageBitmap(BitmapFactory.decodeByteArray(byteArr, 0, byteArr.length));
            return true;
        }
    };
    ImageView image = (ImageView) findViewById(R.id.news_image);
    viewBinder.setViewValue(image, cursor, cursor.getColumnIndex("image"));
    curAdapter.setViewBinder(viewBinder);
    mNewsView.setAdapter(curAdapter);
}

我得到:

android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 60

在执行byte[] byteArr = cursor.getBlob(columnIndex); 时。有谁知道我做错了什么?

【问题讨论】:

    标签: android blob indexoutofboundsexception android-cursor android-viewbinder


    【解决方案1】:

    我扩展了 SimpleCursorAdapter,虽然我没有使用 ViewBinder,但这里是我的代码,用于在列表视图的 sqlite 数据库中使用存储为 blob 的图像。这是改编自我读过的一篇文章here

    我的一行布局文件是:

    row_layout_two_line.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/select_item">
    
    <ImageView 
        android:id="@+id/pic"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginLeft="10dp"
        android:contentDescription="@string/imagedesc"
        android:src="@drawable/icon"
        android:layout_gravity="center_vertical">
    </ImageView>
    
    <LinearLayout
        android:id="@+id/linearLayout0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical" 
        android:orientation="vertical" >
    
        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
    
            <TextView
                android:id="@+id/label"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="@+id/label"
                android:textStyle="bold"
                android:textColor="#000"
                android:textSize="20sp" >
            </TextView>
    
            <TextView
                android:id="@+id/label1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:text="@+id/label1"
                android:textStyle="bold"
                android:textColor="#000"
                android:textSize="20sp" >
            </TextView>
    
        </LinearLayout>
    
        <TextView
            android:id="@+id/label2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="35dp"
            android:text="@+id/label2"
            android:textColor="#000"
            android:textSize="15sp" >
        </TextView>
    </LinearLayout>
    

    调用代码

    ...
        adapter = null;
        mCursor = search();
    
        startManagingCursor(mCursor);
        // Now create a new list adapter bound to the cursor.
        BaseAdapter adapter = new ImageCursorAdapter(this, // Context.
                R.layout.row_layout_two_line, // Specify the row template
                                                        // to use (here, two
                                                        // columns bound to the
                                                        // two retrieved cursor
                                                        // rows).
                mCursor, // Pass in the cursor to bind to.
                // Array of cursor columns to bind to.
                new String [] {"personImage", "firstName", "lastName", "title"},
                // Parallel array of which template objects to bind to those
                // columns.
                new int[] { R.id.pic, R.id.label, R.id.label1, R.id.label2 });
    
    
        // Bind to our new adapter.
        setListAdapter(adapter);
    ...
    

    ImageCursorAdapter.java

    import android.content.Context;
    import android.database.Cursor;
    import android.graphics.BitmapFactory;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.SimpleCursorAdapter;
    import android.widget.TextView;
    
    public class ImageCursorAdapter extends SimpleCursorAdapter {
    
        private Cursor c;
        private Context context;
    
    public ImageCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
        super(context, layout, c, from, to);
        this.c = c;
        this.context = context;
    }
    
    public View getView(int pos, View inView, ViewGroup parent) {
           View v = inView;
           if (v == null) {
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = inflater.inflate(R.layout.row_layout_two_line, null);
           }
           this.c.moveToPosition(pos);      
           String firstName = this.c.getString(this.c.getColumnIndex("firstName"));
           String lastName = this.c.getString(this.c.getColumnIndex("lastName"));
           String titleStr = this.c.getString(this.c.getColumnIndex("title"));
           byte[] image = this.c.getBlob(this.c.getColumnIndex("personImage"));
           ImageView iv = (ImageView) v.findViewById(R.id.pic);
           if (image != null) {
               // If there is no image in the database "NA" is stored instead of a blob 
               // test if there more than 3 chars "NA" + a terminating char if more than
               // there is an image otherwise load the default
               if(image.length > 3)
               {
                   iv.setImageBitmap(BitmapFactory.decodeByteArray(image, 0, image.length));
               }
               else
               {
                   iv.setImageResource(R.drawable.icon);
               }
           }
               TextView fname = (TextView) v.findViewById(R.id.label);
               fname.setText(firstName);
    
               TextView lname = (TextView) v.findViewById(R.id.label1);
               lname.setText(lastName);
    
               TextView title = (TextView) v.findViewById(R.id.label2);
               title.setText(titleStr);
           return(v);
    }
    

    }

    这是最后的样子

    【讨论】:

    • 如果我要在 getView 中手动构建视图,那么使用 SimpleCursorAdapter 并告诉它来自列的意义何在????
    【解决方案2】:

    我认为 cursor.moveToFirst() 尚未被调用,因此光标正在抛出 android.database.CursorIndexOutOfBoundsException.

    在使用cursor 之前,您应该始终通过调用cursor.moveToFirst() 检查光标是否为空。这也会将光标定位在第一个位置。

    【讨论】:

      【解决方案3】:

      联系人列表使用 ListView 和 SimpleCusorAdapter 以及联系人照片和过滤器/搜索

      我一直在寻找一个更简单的解决方案,我的最终解决方案与 Daniel 在这里提到的解决方案非常接近,所以我想我应该在这里分享我的解决方案。我正在使用 Fragment 将设备联系人显示为带有图片的名称列表。结果与 Daniel 的结果非常相似,但仅显示名称。了解代码后,可以很容易地显示更多信息。

      在我的例子中,我使用 PHOTO_URI 从 ContactsContract 获取姓名和图片,因此我不必像 Daniel 那样扩展 SimpleCursorAdapter

      我的示例还包括过滤联系人列表作为SearchView 中的用户类型以查找联系人

      我有一个名为FragmentContacts 的片段和两个布局文件,第一个是主布局frag_contacts.xml,第二个是每个联系人行list_row_contact

      frag_contacts.xml

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">
          <FrameLayout
              android:layout_width="fill_parent"
              android:layout_height="0dp"
              android:layout_weight="1"
              android:background="@android:color/holo_blue_light"
              android:padding="8dip">
      
              <android.support.v7.widget.SearchView
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:background="@android:color/white"
                  android:id="@+id/searchView"/>
          </FrameLayout>
          <LinearLayout
              android:id="@+id/ll_contactList"
              android:layout_width="fill_parent"
              android:layout_height="0dp"
              android:layout_weight="9"
              android:orientation="vertical" >
              <ListView
                  android:id="@+id/lv_ContactList"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:divider="#aaaaaa"
                  android:dividerHeight="1dp" >
              </ListView>
          </LinearLayout>
      </LinearLayout>
      

      list_row_contact.xml

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:orientation="horizontal"
          android:descendantFocusability="blocksDescendants">
      
          <FrameLayout
              android:layout_height="match_parent"
              android:layout_width="0dp"
              android:layout_weight="1"
              android:gravity="center">
      
              <ImageView
                  android:id="@+id/imgContact"
                  android:layout_width="35dip"
                  android:layout_height="35dip"
                  android:layout_gravity="center"
                  android:layout_margin="5dip" />
          </FrameLayout>
      
          <TextView
              android:id="@+id/contact_name"
              android:layout_height="match_parent"
              android:layout_width="0dp"
              android:layout_weight="6"
              android:gravity="center_vertical"
              android:textSize="18sp"
              android:paddingLeft="10dip">
          </TextView>
      </LinearLayout>
      

      FragmentContacts.java

      public class FragmentContacts extends Fragment
      implements LoaderManager.LoaderCallbacks<Cursor>{
          private ListView lv_ContactList;
          private SearchView searchView;
          private SimpleCursorAdapter mCursorAdapter;
      
          private static final String DISPLAY_NAME = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME;
      
          private static final String[] contactsColumns = {    Contacts._ID, Contacts.LOOKUP_KEY, DISPLAY_NAME, Contacts.PHOTO_URI    };
          private final String contactsFilter = "(" +Contacts.HAS_PHONE_NUMBER+ "='1') AND (" + Contacts.IN_VISIBLE_GROUP + "='1')";
          private final String contactsSortOrder = DISPLAY_NAME + " COLLATE LOCALIZED ASC";
      
          private final static String[] listDisplayColumns = { DISPLAY_NAME, Contacts.PHOTO_URI   };
          private final static int[] listDataViewIDs = { R.id.contact_name, R.id.imgContact };
      
          String[] mSelectionArgs;
      
         @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
              View view = inflater.inflate(R.layout.frag_contacts, null);
              lv_ContactList = (ListView)view.findViewById(R.id.lv_ContactList);
              searchView = (SearchView)view.findViewById( R.id.searchView);
              return view;
          }
      
          @Override
          public void onResume(){
              super.onResume();
      
              mCursorAdapter= new SimpleCursorAdapter( getActivity(), R.layout.list_row_contact, null, listDisplayColumns, listDataViewIDs, 0);
              lv_ContactList.setAdapter(mCursorAdapter);
              getLoaderManager().initLoader(0, null, this);
              searchView.setOnQueryTextListener( new SearchView.OnQueryTextListener() {
                  @Override
                  public boolean onQueryTextSubmit( String query ) {return false;}
                  @Override
                  public boolean onQueryTextChange( String newText ) {
                      if( newText.isEmpty() ) mSelectionArgs = null;
                      else mSelectionArgs = new String[]{ "%"+newText.trim()+"%"};
                      getLoaderManager().restartLoader( 0, null, FragmentContacts.this );
                      return false;
                  }
              } );
          }
      
          @Override
          public Loader<Cursor> onCreateLoader( int id, Bundle args ) {
              if(mSelectionArgs == null)
                  return new CursorLoader( getActivity(), Contacts.CONTENT_URI, contactsColumns, contactsFilter, null, contactsSortOrder );
              else
                  return new CursorLoader( getActivity(), Contacts.CONTENT_URI, contactsColumns, contactsFilter + " AND (" + DISPLAY_NAME+" LIKE ?)", mSelectionArgs, contactsSortOrder );
          }
          @Override
          public void onLoadFinished( Loader<Cursor> loader, Cursor data ) {
              mCursorAdapter.swapCursor(data);
          }
          @Override
          public void onLoaderReset( Loader<Cursor> loader ) {
              mCursorAdapter.swapCursor(null);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-10-31
        • 1970-01-01
        • 2014-09-28
        • 2013-04-14
        • 1970-01-01
        • 2011-12-28
        • 1970-01-01
        • 1970-01-01
        • 2010-12-25
        相关资源
        最近更新 更多