简体   繁体   中英

ClassCastException: android.graphics.Bitmap & ArrayList<>

I just don't understand why this exception is occurring. I have a custom adapter for my GridView , where I use a model to create a type PhotoGridItem class for my ArrayList<PhotoGridItem> , which is just a bunch of Bitmap images I pull from my SD card.

Compile time there are no errors, but when I run, I get java.lang.ClassCastException: android.graphics.Bitmap cannot be cast to org.azurespot.cutecollection.PhotoGridItem . Yet the line it points out is this: PhotoGridItem photoGridItem = photos.get(position); , where there are no Bitmaps by reference, the photos variable is a reference to ArrayList<PhotoGridItem> and the get() simply gets the PhotoGridItem object at that position.

Now... the items inside PhotoGridItem are all Bitmap (as shown by the model class), but that's not what Android Studio thinks (at compile time). It definitely considers photos.get(position); to be a PhotoGridItem object in my ArrayList . So I don't know why this exception is coming up or how to fix it.

I basically need a Bitmap for the lines that follow, this one: holder.image.setImageBitmap(bm); but it won't accept photos.get(position); (because at compile time it thinks it's a PhotoGriditem object!) So this feels like Android Studio is a little schizophrenic to me. Please help, thanks!

GridViewPhotoAdapter

package org.azurespot.cutecollection;

/**
* Created by mizu on 2/5/15.
*/
// package org.azurespot.cutecollection;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

import org.azurespot.R;

import java.util.ArrayList;

/**
 * Created by mizu on 2/5/15.
 */
public class GridViewPhotoAdapter extends ArrayAdapter {

    public Context context;
    private int resourceId;
    private ArrayList<PhotoGridItem> photos = new ArrayList<>();


    public GridViewPhotoAdapter(Context context, int layoutResourceId, ArrayList<PhotoGridItem> photos) {
        super(context, layoutResourceId, photos);
        this.context = context;
        this.resourceId = layoutResourceId;
        this.photos = photos;
    }


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

        View row = convertView;
        ViewHolder holder;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(resourceId, parent, false);
            holder = new ViewHolder();
            holder.image = (ImageView) row.findViewById(R.id.photo_grid_view);
            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag();
        }



        PhotoGridItem photoGridItem = photos.get(position);

        Bitmap bm = photoGridItem.getImage();

        holder.image.setImageBitmap(bm);

        return row;

    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return photos.size();
    }

    @Override
    public PhotoGridItem getItem(int position) {
        // TODO Auto-generated method stub
        return photos.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    static class ViewHolder {
        ImageView image;
    }

}

PhotoGridItem

package org.azurespot.cutecollection;

import android.graphics.Bitmap;

/**
 * Created by mizu on 3/19/15.
 */
public class PhotoGridItem {

    private Bitmap image;

    public PhotoGridItem(Bitmap image) {
        super();
        this.image = image;
    }

    public Bitmap getImage() {
        return image;
    }

    public void setImage(Bitmap image) {
        this.image = image;
    }

}

PhotoTab.java

package org.azurespot.cutecollection;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.GridView;

import org.azurespot.R;

import java.io.File;
import java.util.ArrayList;

/**
 * Created by mizu on 2/8/15.
 */
public class PhotoTab extends Fragment {

    private GridView gridView;
    File[] files;
    ArrayList<PhotoGridItem> photoList = new ArrayList<>();
    ArrayAdapter adapter;

    public PhotoTab() {
        super();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.photo_tab, container, false);

        // with fragments, make sure you include the rootView when finding id
        gridView = (GridView) v.findViewById(R.id.photo_grid);
        adapter = new GridViewPhotoAdapter(getActivity(), R.layout.photo_grid_item,
                loadSDCard());
        // Set the Adapter to GridView
        gridView.setAdapter(adapter);

        // add the default icons remaining, to GridView, if less than 24 files on SD card
        for (int i = 0; i < (24 - photoList.size()); i++) {

            adapter.add(BitmapFactory.decodeResource(getResources(), R.drawable.ic_photo_placeholder));
            adapter.notifyDataSetChanged();
            i++;
        }

        return v;
    }

    private ArrayList<PhotoGridItem> loadSDCard() {

        try {
            // gets directory CutePhotos from sd card
            File baseDir = Environment.getExternalStorageDirectory();
            File cutePhotoDir = new File(baseDir, "/Documents/CutePhotos");
            // lists all files in CutePhotos, loads in Files[] array
            files = cutePhotoDir.listFiles();


            for (File singleFile : files) {
                String filePath = singleFile.getAbsolutePath();
                Bitmap bitmap = BitmapFactory.decodeFile(filePath);
                photoList.add(new PhotoGridItem(bitmap));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return photoList;
    }
}

Logcat

3218-3218/org.azurespot E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: org.azurespot, PID: 3218
    java.lang.ClassCastException: android.graphics.Bitmap cannot be cast to org.azurespot.cutecollection.PhotoGridItem
            at org.azurespot.cutecollection.GridViewPhotoAdapter.getView(GridViewPhotoAdapter.java:57)
            at android.widget.AbsListView.obtainView(AbsListView.java:2791)
            at android.widget.GridView.onMeasure(GridView.java:1065)
            at android.view.View.measure(View.java:17619)
            at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
            at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:17619)
            at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1456)
            at android.view.View.measure(View.java:17619)
            at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
            at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.support.v7.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:453)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5428)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2588)
            at android.view.View.measure(View.java:17619)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2317)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1412)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1613)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1270)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6691)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:813)
            at android.view.Choreographer.doCallbacks(Choreographer.java:613)
            at android.view.Choreographer.doFrame(Choreographer.java:583)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:799)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5731)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
            at dalvik.system.NativeStart.main(Native Method)

I would first suggest you to add a type for your Array Adapter

public class GridViewPhotoAdapter extends ArrayAdapter<PhotoGridItem> {
...
}

also in your PhotoTab.java

ArrayAdapter<PhotoGridItem> adapter;

After these two steps, you would probably get some errors or warnings now. If not, check this line in your PhotoTab.java

adapter.add(BitmapFactory.decodeResource(getResources(), R.drawable.ic_photo_placeholder));

This line looks especially suspicious for me, because you're adding a Bitmap to and Array Adapter of PhotoGridItem. I guess what you want is:

adapter.add(new PhotoGridItem(BitmapFactory.decodeResource(getResources(), R.drawable.ic_photo_placeholder)));

Update

I would also suggest you not to pass in an ArrayList in your constructor, because ArrayAdapter already backed by an array. I didn't test the following code, but to illustrate my idea, here is the code:

public class GridViewPhotoAdapter extends ArrayAdapter<PhotoGridItem> {

    public Context context;
    private int resourceId;

    public GridViewPhotoAdapter(Context context, int layoutResourceId) {
        super(context, layoutResourceId, photos);
        this.context = context;
        this.resourceId = layoutResourceId;
    }

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

        View row = convertView;
        ViewHolder holder;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(resourceId, parent, false);
            holder = new ViewHolder();
            holder.image = (ImageView) row.findViewById(R.id.photo_grid_view);
            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag();
        }


        PhotoGridItem photoGridItem = getItem(position);
        Bitmap bm = photoGridItem.getImage();
        holder.image.setImageBitmap(bm);

        return row;
    }

    static class ViewHolder {
        ImageView image;
    }
}

And then in your PhotoTab.java:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.photo_tab, container, false);

    // with fragments, make sure you include the rootView when finding id
    gridView = (GridView) v.findViewById(R.id.photo_grid);
    adapter = new GridViewPhotoAdapter(getActivity(), R.layout.photo_grid_item);
    // Set the Adapter to GridView
    gridView.setAdapter(adapter);

    adapter.addAll(loadSDCard());

    // add the default icons remaining, to GridView, if less than 24 files on SD card
    for (int i = 0; i < (24 - photoList.size()); i++) {
        adapter.add(
            new PhotoGridItem(
                BitmapFactory.decodeResource(getResources(), R.drawable.ic_photo_placeholder)));
    }

    adapter.notifyDataSetChanged();

    return v;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM