在两个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
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
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
private 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存储,然后作为整个的参数传递过去。