1

I have a class I use for managing bitmaps in my application. It needs to have a context passed to it to be able to use getResources(). Problem is I believe you can't use Context inside of a Parcelable class.

Anyone have any ideas for a solution? Below is my code:

public class ImageManager implements Parcelable {

    private static final long serialVersionUID = 66;
    private HashMap<Integer, Bitmap> mBitmaps;
    private HashMap<Integer, Drawable> mDrawables;
    //private Context mContext;

    private boolean mActive = true;

    public ImageManager(Context c) {
        mBitmaps = new HashMap<Integer, Bitmap>();
        mDrawables = new HashMap<Integer, Drawable>();
        //mContext = c;
    }

    public ImageManager(Parcel in) {
        // TODO Auto-generated constructor stub
    }


    public Bitmap getBitmap(int resource) {
        if (mActive) {
            if (!mBitmaps.containsKey(resource)) {
                mBitmaps.put(resource,
                   BitmapFactory.decodeResource(mContext.getResources(), resource));
            }
            return mBitmaps.get(resource);
        }
        return null;
    }

    public Drawable getDrawable(int resource) {
        if (mActive) {
            if (!mDrawables.containsKey(resource)) {
                mDrawables.put(resource, mContext.getResources().getDrawable(resource));
            }
            return mDrawables.get(resource);
        }
        return null;
    }

    public void recycleBitmaps() {
        Iterator itr = mBitmaps.entrySet().iterator();
        while (itr.hasNext()) {
            Map.Entry e = (Map.Entry)itr.next();
            ((Bitmap) e.getValue()).recycle();
        }
        mBitmaps.clear();
    }

    public ImageManager setActive(boolean b) {
        mActive = b;
        return this;
    }

    public boolean isActive() {
        return mActive;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        // TODO Auto-generated method stub
        dest.writeValue(mBitmaps);
        dest.writeValue(mDrawables);
        //dest.writeValue(mContext);
        dest.writeByte((byte) (mActive ? 0x01 : 0x00));

    }

    public static final Parcelable.Creator<ImageManager> CREATOR = new Parcelable.Creator<ImageManager>() {
        public ImageManager createFromParcel(Parcel in) {
            return new ImageManager(in);
        }

        public ImageManager[] newArray(int size) {
            return new ImageManager[size];
        }
    };


}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
odds0cks
  • 141
  • 4
  • 11

3 Answers3

2

A "manager" normally can't be Parcelable or Serializable.

Parcelable or Serializable objects are kind of objects that just hold some data and don't perform any operations on it and don't need to reference Context.

When you pass objects as a Parcelable, the object received will be recreated so this way you can't preserve the same instance.

To solve your task, make ImageManager a singleton.

public final class ImageManager {

    public static synchronized ImageManager getInstance(final Context context) {
        if (sInstance == null) {
            sInstance = new ImageManager(context.getApplicationContext());
        }
        return sInstance;
    }

    private static ImageManager sInstance;

    private final Context mContext;

    private ImageManager(Context c) {
        mBitmaps = new HashMap<Integer, Bitmap>();
        mDrawables = new HashMap<Integer, Drawable>();
    }

And whenever you need it in Activity, call

ImageManager imageManager = ImageManager.getInstance(this);

This way the same ImageManager will be accessible in all Activities.

Yaroslav Mytkalyk
  • 16,950
  • 10
  • 72
  • 99
0

You can create your own Application implementation and add static getter.

public class Application extends android.app.Application {

    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = this;
    }

    public static Context getContext(){
        return context;
    }
}

And use it everywhere you need:

Application.getContext();

But in general I thing it's not the best idea.

eleven
  • 6,779
  • 2
  • 32
  • 52
0

I suggest turning your class into a helper class by making the methods you need static and then passing Context as a parameter as well, like so:

public Bitmap getBitmap(int resource, Context context) { ... }

Don't store that reference to Context in your helper class, if you do you will most likely be leaking it.

jpalvarezl
  • 325
  • 2
  • 8