Reputation: 3152
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)
Upvotes: 1
Views: 1528
Reputation: 535
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)));
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;
}
Upvotes: 2