Skip to content

Instantly share code, notes, and snippets.

@kkuivi
Last active January 17, 2017 15:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kkuivi/d49d7d832013b2b15e28cf20706a013a to your computer and use it in GitHub Desktop.
Save kkuivi/d49d7d832013b2b15e28cf20706a013a to your computer and use it in GitHub Desktop.
ReferenceMap- Datastructure that makes it possible to pass objects between activities for Android development.
package com.goeshow.barcodescanner.utils.objectReferenceMap;
import android.content.Context;
import android.support.v4.app.Fragment;
import java.util.HashMap;
/**
* Created by ekuivi on 8/24/16.
*
* Singleton object that makes it easy to pass object references between activities
*/
public class ReferenceMap {
public class ReferenceList {
private HashMap<String, Object> mReferenceList;
private ReferenceList(){
mReferenceList = new HashMap<String, Object>();
}
public void put(String key, Object object){
mReferenceList.put(key, object);
}
public Object get(String key){
if(!mReferenceList.containsKey(key))
return null;
return mReferenceList.get(key);
}
}
private HashMap<String, ReferenceList> mRefListMap;
private static ReferenceMap mSingleInstance = null;
ReferenceMap(){
mRefListMap = new HashMap<String, ReferenceList>();
}
public static ReferenceMap getInstance(){
if(mSingleInstance == null)
mSingleInstance = new ReferenceMap();
return mSingleInstance;
}
private String getActivityNameFrom(Context context){
return context.getClass().getCanonicalName();
}
private String getFragmentNameFrom(Fragment fragment){
return fragment.getClass().getCanonicalName();
}
private String getActivityNameFrom(Class activity){
return activity.getCanonicalName();
}
public ReferenceList getReferenceList(Context context){
String activityName = getActivityNameFrom(context);
if(!mRefListMap.containsKey(activityName))
return null;
return mRefListMap.get(activityName);
}
public ReferenceList getReferenceList(Fragment fragment){
String fragmentName = getFragmentNameFrom(fragment);
if(!mRefListMap.containsKey(fragmentName))
return null;
return mRefListMap.get(fragmentName);
}
private void createActivityRefList(String activityName){
mRefListMap.put(activityName, new ReferenceList());
}
public void putObjectReference(Class activity, String objectKey, Object object){
String activtyName = getActivityNameFrom(activity);
if(!mRefListMap.containsKey(activtyName))
createActivityRefList(activtyName);
ReferenceList referenceList = mRefListMap.get(activtyName);
referenceList.put(objectKey, object);
}
public void releaseActivityRefList(Context context){
String activityName = getActivityNameFrom(context);
if(mRefListMap.containsKey(activityName))
mRefListMap.remove(activityName);
}
public void releaseFragmentRefList(Fragment fragment){
String fragmentName = getFragmentNameFrom(fragment);
if(mRefListMap.containsKey(fragmentName))
mRefListMap.remove(fragmentName);
}
}
@kkuivi
Copy link
Author

kkuivi commented Sep 29, 2016

Passing objects between activities in Android development is pretty tedious. You can make use of the Parcelable but rules on the order in which the object values should be inserted makes it pretty rigid and easy to make errors.

With this ReferenceMap data structure, passing objects between activities is a bit more flexible. To pass an object to an activity, first copy this class into your project. Then, you just need to use the putObjectReference method of the ReferenceMap. For example, to pass a Contact object called mContact to a SampleActivity.java activity:
ReferenceMap.getInstance().putObjectReference(SampleActivity.class, "ContactKey", mContact);

To retrieve the object in the SampleActivity.java class:
ReferenceMap.ActivityReferenceList refList = ReferenceMap.getInstance().getActivityReferenceList(this);
Contact prevContact = (Contact) reflist.get("ContactKey");

Finally, to prevent memory leaks, make sure to call the releaseActivityRefList() method in SampleActivity.java's onStop() method:
@OverRide
protected void onStop() {
super.onStop();
ReferenceMap.getInstance().releaseActivityRefList(this);
}

@eduardb
Copy link

eduardb commented Oct 15, 2016

This is a very wrong approach, from my point of view. First of all, you'll be dependent on a global state, which is a singleton, a very bad practice in general. Then, you are also using Class.getSimpleName() as a key on your Map, which may lead to collisions. If you have ProGuard with obfuscation enabled, classes from different packages can end up with the same name, like a or b for instance. Thus, different activities will have the same simple name, and you'll overwrite and loose values in your map.

If you want to use Parcelables in a manner that is not error-prone, you can use AutoValue library from Google with an extension like https://github.com/rharter/auto-value-parcel.

@kkuivi
Copy link
Author

kkuivi commented Jan 17, 2017

Thanks, changed getSimpleName() to getCanonicalName(). This should solve the problem explained above. New version here (https://gist.github.com/kkuivi/161f254374a4007ae6014f67ae45789e)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment