【问题标题】:View Binder and ClassCastException查看 Binder 和 ClassCastException
【发布时间】:2013-08-16 05:52:24
【问题描述】:

您好,我在取景器方面遇到了一些问题,想知道是否有人可以提供帮助。

我有一个 SQLite 数据库,它很好,我将小的缩略图图像作为 blob 存储在其中。我知道 blob 正在保存,因为我可以在我的应用程序的另一个区域中检索它们。

现在,我正在尝试使用 ViewBinder 将数据库中的图像绑定到我的自定义列表视图。 (您可以将其视为联系人管理器的布局,其中我有一个带有相应图像的姓名和号码列表。)

我尝试了几种不同的方法,包括使用简单的光标适配器,从我的研究来看,创建我自己的视图活页夹似乎是一种方法。代码没有错误,但是在运行时我得到了 ClassCastException。

下面是我的主列表活动的代码

  listViewCards = (ListView) findViewById(android.R.id.list); 
    Cursor cursor = dbhelper.getAllContacts();



    SimpleCursorAdapter myAdapter = new SimpleCursorAdapter(
        getApplicationContext(), 
        R.layout.listview_each_item, 
        cursor, 
        new String[] { SQLiteAdapter.KEY_NAME,SQLiteAdapter.KEY_PHONE, SQLiteAdapter.KEY_COMPANYNAME}, 
        new int[] { R.id.list_item_name,R.id.list_item_phone, R.id.list_item_companyname  },0);

    ImageView image = (ImageView) findViewById(R.id.list_item_image);
    MyViewBinder mvb = new MyViewBinder();
    mvb.setViewValue(image, cursor, cursor.getColumnIndex(SQLiteAdapter.KEY_IMAGE));
    myAdapter.setViewBinder(mvb);
    listViewCards.setAdapter(myAdapter);

对于我的自定义视图活页夹

 public class MyViewBinder implements ViewBinder{

@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
    ImageView image = (ImageView) view;
    cursor.moveToFirst();
    byte[] byteArray = cursor.getBlob(columnIndex);
    if(image !=null){
    image.setImageBitmap(BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length));
    return false;
    }
    return true;
}

现在是 logcat

08-14 11:01:15.275: E/AndroidRuntime(2669): FATAL EXCEPTION: main
08-14 11:01:15.275: E/AndroidRuntime(2669): java.lang.ClassCastException: android.widget.TextView cannot be cast to android.widget.ImageView
08-14 11:01:15.275: E/AndroidRuntime(2669):     at          com .example.npacards.MyViewBinder.setViewValue(MyViewBinder.java:14)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.widget.SimpleCursorAdapter.bindView(SimpleCursorAdapter.java:146)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.widget.CursorAdapter.getView(CursorAdapter.java:250)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.widget.AbsListView.obtainView(AbsListView.java:2457)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.widget.ListView.measureHeightOfChildren(ListView.java:1250)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.widget.ListView.onMeasure(ListView.java:1162)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.view.View.measure(View.java:15473)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.widget.RelativeLayout.measureChild(RelativeLayout.java:602)
08-14 11:01:15.275: E/AndroidRuntime(2669):     at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:415)

我认为活页夹中的第 14 行是

    ImageView image = (ImageView) view; 

谁能帮我理解为什么这会产生一个classCastExeption,因为正在传递给我的视图活页夹的视图是

  ImageView image = (ImageView) findViewById(R.id.list_item_image);

非常感谢任何想法。

【问题讨论】:

    标签: android android-listview android-viewbinder


    【解决方案1】:

    ViewBinder 将为在创建适配器时传递的 to(适配器的构造函数)数组中声明的每个视图调用。现在你没有通过ImageView(通过它的id)所以ViewBinder不会被ImageView调用,它只会被id为R.id.list_item_name的视图调用,R.id.list_item_phoneR.id.list_item_companyname。这就是为什么你得到ClassCastException,因为你错误地认为传递给ViewBinder 的视图是ImageView(这是你犯的另一个错误,因为你没有查看传递给的视图的ID ViewBinder 以查看此时哪个视图设置为与来自Cursor 的数据绑定。

    要解决它,您需要让适配器知道您还希望绑定行中的 ImageView(注意额外的列和 id):

    SimpleCursorAdapter myAdapter = new SimpleCursorAdapter(
            getApplicationContext(), 
            R.layout.listview_each_item, 
            cursor, 
            new String[] { SQLiteAdapter.KEY_NAME,SQLiteAdapter.KEY_PHONE, SQLiteAdapter.KEY_COMPANYNAME, SQLiteAdapter.KEY_IMAGE}, 
            new int[] { R.id.list_item_name,R.id.list_item_phone, R.id.list_item_companyname,  R.id.list_item_image},0);
    

    然后更改ViewBinder 来处理设置图像,让适配器自己绑定其他视图:

    @Override
    public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
        if (view.getId() == R.id.list_item_image) { // we have our ImageView so bind the image
            byte[] byteArray = cursor.getBlob(columnIndex);
            ((ImageView)view).setImageBitmap(BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length));
            return true; // return true to let the adapter know that we handled this view on our own
        }
        return false; // return false for any other view so the adapter will bind the data on its own
    }
    

    这个:

    mvb.setViewValue(image, cursor, cursor.getColumnIndex(SQLiteAdapter.KEY_IMAGE));
    

    不正确。您不会自己调用setViewValue(),适配器将在getView() 方法中为每个具有to 数组中的ID 的视图调用它,以设置它们的数据。

    【讨论】:

    • 感谢您的精彩回答。这是一个复制粘贴错误,当我试图测试它为什么不起作用时,我错过了将密钥和 id 放入到数组和从数组中。但无论如何,你的答案比我能找到的任何东西都清晰,包括 android 文档!所有这方面都在充分发挥作用。感谢,而不仅仅是一个复制粘贴解决方案,我现在正确理解了该方法的工作原理。
    【解决方案2】:

    当一个简单的光标适配器试图构建一个视图时,它会检查一个视图绑定器是否可用。如果是这样,它首先调用 setViewValue,而不管正在呈现的视图的类型。基于从这个函数返回的值,setViewText 或 setViewImage被调用。在你的情况下,第一个映射来自 SQLiteAdapter.KEY_NAME => R.id.list_item_name,我想它是一个 textView。所以当它尝试渲染时,一个视图活页夹可用,所以它被一个 textView 调用.但是在你的viewbinder中,你既不检查传递的视图类型也不检查列索引。你只是将它转换为imageView。所以只有ClassCastException来了。

    【讨论】:

    • 这可能足以继续解决,但 Luksprogs 的答案显然更完整。谢谢你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 2014-10-20
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多