Jawascript
Jawascript

Reputation: 703

Class Cast Exception, inside Adapter from AsyncTask

I am getting a java.lang.ClassCastException when trying to use an Interface and an AsyncTask from inside my adapter. I don't know if this is 'allowed', but I can't see why it wouldn't be as long as everything is kept in context.

The code starts in my Fragment when I try and set my GridView with a custom Adapter.

mSceneGridAdapter = new SceneGridAdapter(getActivity(), mScenesList);

Which leads to my SceneGridAdapter class being called

public class SceneGridAdapter extends BaseAdapter implements HandleProductThumbnail {
    private Context mContext;
    private ArrayList<Scene> mSceneList = null;
    private LayoutInflater mInflater;
    private Drawable mThumbnail;

    public SceneGridAdapter() {}

    public SceneGridAdapter(Context context, ArrayList<Scene> sceneList) {
        super();

        mContext = context;
        if (mSceneList != null) {
            clearData();
        } else {
            mSceneList = sceneList;
        }

        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.scene_cell, null);
        }

        ImageView sceneView = (ImageView) convertView.findViewById(R.id.sceneImage);

        Scene scene = mSceneList.get(position);
        String specifier = scene.getSpecifier() + "/" + scene.getName();
        LoadScenes scenes = new LoadScenes(mContext, specifier);
        scenes.execute();
        sceneView.setBackground(mThumbnail);

        return convertView;

    }

    @Override
    public int getCount() {
        return mSceneList.size();
    }

    @Override
    public Object getItem(int position) {
        return mSceneList.get(position);
    }

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

    public void clearData() {
        mSceneList.clear();
    }

    @Override
    public void handleProductThumbnail(Drawable thumb) {
        mThumbnail = thumb;
    }
}

Which implements my Interface HandleProductThumbnails

public interface HandleProductThumbnail {
        void handleProductThumbnail(Drawable thumb);
}

and then calls my AsyncTask loader class called LoadScenes, which loads the thumbnails and returns them to the adapter.

public class LoadScenes extends AsyncTask<Void, Void, Drawable> {
    private static final String LOADING = "Loading...";
    private static final String PNG = "_ORIGINAL.PNG";

    private Context mContext;
    private HandleProductThumbnail mHandleThumbnail = null;
    private ProgressDialog mProgressDialog;
    private String mSpecifier;

    public LoadScenes () {}

    public LoadScenes (Context context, String specifier) {
        mContext = context;
        mSpecifier = specifier;
    }

    @Override
    public void onPreExecute() {
        mProgressDialog = new ProgressDialog(mContext);
        mProgressDialog.setMessage(LOADING);
        mProgressDialog.show();
    }

    public Drawable doInBackground(Void... v) {
        Drawable productThumbnail = getDrawable(mSpecifier);
        return productThumbnail;
    }

    public void onPostExecute(Drawable productThumbnail) {
        mProgressDialog.dismiss();
        mHandleThumbnail = (HandleProductThumbnail) mContext;
        mHandleThumbnail.handleProductThumbnail(productThumbnail);
    }

    public Drawable getDrawable(String specifier) {
        Bitmap bmp = null;
        Drawable productThumbnail = null;
        specifier = specifier.replace("\\", "/") + PNG;
        try {
            bmp = BitmapFactory.decodeStream(mContext.getAssets().open(specifier));
            if (bmp != null) {
                int width = 300;
                int height = 240;
                bmp = Bitmap.createScaledBitmap(bmp, width, height, true);
                productThumbnail = new BitmapDrawable(mContext.getResources(), bmp);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return productThumbnail;
    }
}

and finally my log

09-30 10:34:35.725: E/AndroidRuntime(22442): java.lang.ClassCastException: com.example.xxx.visualizer.VisualizerActivity cannot be cast to com.example.xxx.interfaces.HandleProductThumbnail
09-30 10:34:35.725: E/AndroidRuntime(22442):    at com.example.xxx.visualizer.LoadScenes.onPostExecute(LoadScenes.java:46)

The Fragment is attached to an Activity called VisualizerActivity, and all the context being passed comes from that Activity. While this problem is somewhat layered, the code is fairly boilerplate. I was wondering if I am just doing something that isn't allowed? From my understanding of Context this should work. Please let me know what I'm doing wrong, why, and if it can be fixed. Thank you

Upvotes: 2

Views: 346

Answers (3)

Azhar Khan
Azhar Khan

Reputation: 99

It is clearly visible that it would create an class cast exception, because mContext is your activity`s object which is not implementing the "HandleProductThumbnail" interface.

Though you rectify your code by right casting, yet it will produce error due to below lines of code in your adapter

    LoadScenes scenes = new LoadScenes(mContext, specifier);
    scenes.execute();
    sceneView.setBackground(mThumbnail);

Because second line is an async call and mThumbnail would be null.You may apply another approach for rendering images from URL at run time.

Upvotes: 0

Blackbelt
Blackbelt

Reputation: 157437

Looks like your activity is not implementing the HandleProductThumbnail, but your custom adapter. In your case, instead of casting, I would rather add a method to the AsyncTask subclass:

   public void setHandleProductThumbnail(HandleProductThumbnail listener) {
           mHandleThumbnail = listener;
   }

and inside OnPostExecute

 public void onPostExecute(Drawable productThumbnail) {
    mProgressDialog.dismiss();
    if (mHandleThumbnail != null)
       mHandleThumbnail.handleProductThumbnail(productThumbnail);
}

Upvotes: 1

2Dee
2Dee

Reputation: 8629

Your problem is here :

mHandleThumbnail = (HandleProductThumbnail) mContext;

You're casting mContext to HandleProductThumbnail whereas mContext is a Context, hence not implementing your custom interface. If you need a reference to the HandleProductThumbnail, pass it as a constructor argument.

Last note : if you're trying to load thumbnails on every list item, I would suggest the use of Picasso, which would make all this much simpler for you.

Upvotes: 0

Related Questions