不用序列化Activity间传值

    在两个Activity间传递Java Object 对象时,需要进行序列化,实现Serializable 或者Parcelable 接口,

作为一个JavaWeb转过来的程序员,我比较有强迫症,一看到序列化,我马上联想到JAVA RMI。心里很不情愿实现这些接口,


为什么我同一个程序的在两个对象间传递对象要这么繁琐呢。。。。。。。


然后发现,Android的设计把四个组件的启动,调用全部用Intent来完成,这种封装对使用者来说有着统一的调用传参方式,使用起来很简单,代码简洁,更容易接受。但是在内部组织的时候存在个问题,那就是不同的组件可能是不同进程中的,比如Activity和Service,他们存在在不同进程中。


同一个进程间的不同线程可以共享内存,直接调用对象就可以了,但是不同进程间无法直接调用,这就需要进程间通信。其实我们使用http协议发送请求也是不同进程间通信的一个方式,这种通信是基于Socket的。只不过http发送的是文本参数。


不同进程间的对象参数传递,android要求java对象序列化。而且在Intent启动不同组件的时候保持一致,不管是不是同一进程的组件,android都要进行序列化,然后传递。


如果我们的程序在不同Activity间传递java对象,那么它们属于同一个进程,在同一个进程间调用,我实在是不想序列化了。我们可以借助全局对象Application,把参数值保存在Application中,我们在get得到参数后要把对象及时删除,防止内存泄露。


但是我们对所有参数都在Application中加入一个成员变量,每个变量加一个set get方法,这样的话代码看起来有点糟糕了,难于维护。


   我们考虑使用HashMap,存储的参数对象作为值value,key键我们可以随意定,这个时候我们可以借鉴一下ThreadLocal的设计


用ThreadLocal对象的一个实例作为一个key键,ThreadLocal提供set(T value)方法,

把this实例对象作为key ,T value作为值,存储在Thread的hashmap中,ThreadLocal提供get()方法,

得到Thread 的hashmap中ThreadLocal.this实例的value值。


    这种设计的好处就是完全隐藏hashmap.put(key,value),hashmap.get(key),使用的时候


ThreadLocal key = new  ThreadLocal();

key.put(object);


   我们只要保持key的引用,通过key.get()就可以得到对应的参数了。


仿照ThreadLocal,我写了ActivityLocal对象,其实应该分别叫做ThreadLocalVariable  和ActivityLocalVariable

代码如下:

public class ActivityLocal {
    private Context context = null;


    public ActivityLocal(Context context){
        this.context = context;
    }
    
    public T get(){
        Iapplication application = (Iapplication) ((Activity)this.context).getApplication();
        Intent intent = (Intent)((Activity)this.context).getIntent();
        String key = intent.getExtras().getString("activitylocal");
        ActivityLocal local = application.get(key);
        return  (T) application.get(local);
    }
    
    public void set(T value){
        Iapplication application = (Iapplication) ((Activity)this.context).getApplication();
        application.set(this, value);
        application.set(String.valueOf(this.hashCode()), this);
    }
}


因为我们要在两个Activity间得到同一个key即同一个ActivityLocal实例,我们把ActivityLocal实例也保存在Application中,用固定字符串"activitylocal"作为key,Iapplication的实现代码如下:

public class Iapplication extends Application{

    private HashMap localMap = new HashMap();
    private HashMap activityMap = new HashMap();

    public ActivityLocal get(String key){
        return this.localMap.remove(key);
    }
    
    public void set(String key,ActivityLocal activityLocal){
        this.localMap.put(key, activityLocal);
    }
    
    public Object get(ActivityLocal activityLocal){
        return this.activityMap.remove(activityLocal);
    }
    
    public void set(ActivityLocal activityLocal,Object value){
        this.activityMap.put(activityLocal, value);
    }
}



具体传递的时候

Intent intent = new Intent(ActivityA.this, lActivityB.class);

        ActivityLocal al = new ActivityLocal(this);

Object value = new Object();
       
 al.set(value );

  Bundle bundle = new Bundle();
        bundle.putString("activitylocal",String.valueOf(al.hashCode()));

        intent.putExtras(bundle);
        this.startActivity(intent);


这样就把参数对象value传递了

在另一个Activity中获取就很简单了:

ActivityLocal local = new ActivityLocal(this);
        Obejct value = local.get();


开始的时候我想把Intent的实例作为key,来存储ActivityLocal的实例,但是调试发现Intent内容会变化,就是equals不相等,没有找到更好的办法,就把ActivityLocal的hashCode传递到ActivityB中,通过这个hashCode,在Application中得到刚才的ActicityLocal实例,进一步得到参数Object。


因为涉及到了在不同Activity来传递ActivityLocal对象实例,所以这个方式的缺点就是只能传递一个ActivityLocal对象实例,也就是说不同Activity间的参数也只能传递一个,但是大多数情况下也足够了,不行的话,可以用hashmap或者list存储,然后作为整个的参数传递过去。

你可能感兴趣的:(不用序列化Activity间传值)