具有2个布局的适配器中的ClassCastException

时间:2014-12-01 18:10:45

标签: android android-listview android-adapter android-viewholder

我有一个适配器,它有两个布局(一个用于分隔符,一个用于普通项目),但是当我运行应用程序时,我在logCat中得到它:

java.lang.ClassCastException: com.myapp.android.adapter.ModelItemAdapter$ViewHolderSeparator cannot be cast to com.myapp.android.adapter.ModelItemAdapter$ViewHolderItem
            at com.myapp.android.adapter.ModelItemAdapter.getView(ModelItemAdapter.java:84)
            at android.widget.AbsListView.obtainView(AbsListView.java:2019)
            at android.widget.ListView.makeAndAddView(ListView.java:1772)
            at android.widget.ListView.fillDown(ListView.java:672)
            at android.widget.ListView.fillGap(ListView.java:636)
            at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4567)
            at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:2866)
            at android.widget.AbsListView.onTouchEvent(AbsListView.java:3121)
            at android.view.View.dispatchTouchEvent(View.java:5564)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2052)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1813)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827)
            at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2058)
            at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1827)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1931)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1390)
            at android.app.Activity.dispatchTouchEvent(Activity.java:2364)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1879)
            at android.view.View.dispatchPointerEvent(View.java:5766)
            at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:2890)
            at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2466)
            at android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:845)
            at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2475)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4441)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
            at dalvik.system.NativeStart.main(Native Method)

这是我的代码:

public class ModelItemAdapter extends ArrayAdapter<ListModelItem> {

    // == constants ==
    public static final String TAG = ModelItemAdapter.class.getSimpleName();

    // == attributes ==
    private final Context context;
    private final List<ListModelItem> modelsArrayList;
    private LayoutInflater inflater;

    // == constructor ==
    public ModelItemAdapter(Context context, ModelItemsList modelItemsList) {
        super(context, R.layout.list_item_row, modelItemsList.getItems());
        this.context = context;
        this.modelsArrayList = new ArrayList<ListModelItem>(modelItemsList.getItems());
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }


    // == public methods ==
    @Override
    public int getCount() {
        return modelsArrayList.size();
    }

    @Override
    public ListModelItem getItem(int position) {
        return modelsArrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount();
    }

    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        Log.d(TAG, "pos= " + position + " parent= " + parent);
        Log.d(TAG, "item= " + getItem(position));


        ListModelItem itemAtPos = modelsArrayList.get(position);


        View rowView = convertView;
        ViewHolderItem holder;

        if (!itemAtPos.isParentOrMyObject() ) {


            if (rowView == null) {
                rowView=inflater.inflate(R.layout.list_item_row, parent, false);
                holder = new ViewHolderItem();

                holder.imgView = (ImageView) rowView.findViewById(R.id.item_icon);
                holder.titleView = (TextView) rowView.findViewById(R.id.item_title);
                holder.counterView = (TextView) rowView.findViewById(R.id.item_counter);
                rowView.setTag(holder);
            } else {
                holder = (ViewHolderItem) rowView.getTag();
            }


            Log.d(TAG, "modelType= " + itemAtPos.getModelType());

            Integer resIconId = itemAtPos.getIconResId();
            Log.d(TAG, "resIconId= " + resIconId);

            if (itemAtPos.hasIcon()) {
                holder.imgView.setImageResource(resIconId);
            }

            String itemTitle = context.getString(itemAtPos.getDisplayValueResId());
            holder.titleView.setText(itemTitle);
            holder.counterView.setText(itemAtPos.getTotalCountString());

        } else {
            ViewHolderSeparator separator;
            if (rowView == null) {
                rowView = inflater.inflate(R.layout.title_item_row, parent, false);
                separator = new ViewHolderSeparator();
                separator.title = (TextView) rowView.findViewById(R.id.header);
                rowView.setTag(separator);
            } else {
                separator = (ViewHolderSeparator) rowView.getTag();
            }

            // assume that it is company.
            String title = itemAtPos.getCompanyName();

            if (itemAtPos.isMyObject()) {
                title = context.getString(itemAtPos.getDisplayValueResId());
            }

            separator.title.setText(title);
        }

        return rowView;
    }

    // == view holder ==
    static class ViewHolderItem {
        ImageView imgView;
        TextView titleView;
        TextView counterView;
    }

    static class ViewHolderSeparator {
        TextView title;
    }
}

2 个答案:

答案 0 :(得分:1)

附加到循环视图(convertView)的视图保持器不保证与当前位置的项目类型相同。例如,视图+视图持有者可能是循环使用的Item,但当前索引位置正在尝试膨胀或显示Separator

您必须检查回收视图的项类型是否与当前项类型不同,如果不同则重新注释/重新标记视图(与convertView为null时相同) )。

或者,您可以切换到一个布局&amp;一个视图持有者类,有选择地隐藏或显示布局的某些部分,具体取决于它的类型。

答案 1 :(得分:0)

更改getViewTypeCountgetItemViewType的实施方式,如:

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int position) {
        if (getItem(position).isParentOrMyObject()) {
                return 0;
        }
        return 1;
    }

这样你就会得到两个不同的convertView。当0返回true时索引为isParentOrMyObject()的那个,返回false时索引为1的那个