Android提供了一套叫Intent的消息机制,组件之间可以用Intent来通信,包括我们启动一个Activity,启动Service,发广播都是用的Intent。可以说Intent这套机制很好的解决了传统软件开发中的依赖问题,用Intent来给各组件解耦,是Android开发的最佳实践。这个也与Android的生命周期管理有关,Android的设计处处都体现了内存管理的特色,也就是任何东西在内存不存的时候都可能被杀掉,应用应该设计为随时准备被杀后能正确的恢复。依赖关系一复杂,会导致内存回收上的困难,甚至发生内存泄漏,影响整个系统的稳定性。
我最近看了一些代码,可能开发人员是从传统编程快速切换到Android开发的,把组件当成普通的类,在Activity,Service和Broadcast Receiver这三大组件中互相持有引用,耦合在一起,导致程序结构不清晰,维护困难,这种设计编码上也很麻烦,只有坏处,没有任何好处。有人说这样做方便,其实写下来也不方便,代码量并不会少。
来看是怎么做的,比如说两个Activity(Service和Receiver也差不多):
public class ActivityA extends Activity {
private ActivityB b;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
b = ActivityB.instance;
}
}
public class ActivityB extends Activity {
public static ActivityB instance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
instance = this;
}
}
ActivityB提供一个公开的静态变量指向自己,这样ActivityA就能取得并且持有ActivityB的引用,问题来了,因为ActivityB的实例并不一定是活的,所以在ActivityB的被调用方法里面,要状态instance是否为null,如果不为null,则用startActivity()启动自己。但是又不能够有多个实例,所以launchMode设为singleInstance。可以看到,这种方式不仅麻烦,主要是各组件生命周期不可控,用到的时候都要判断是否存在,不存在则要启动它,逻辑不清晰,而且搞不好会有内存泄漏。
从两个角度来分析这个问题:
1、组件A依赖组件B,A要B做事情或者是共享变量。
2、组件A依赖组件B,A要更新B的状态。
总结下来有以下这几种处理方式:
我们要把做这个事情的代码剥离到一个普通的类里面去,这个类根据实际情况可以是静态的或者是单例的。
如果是共享变量,则应该继承Application,在使用变量的时候,用getApplicationContext()来获取。
共享变量可以用Application,也可以用单例或静态,相关讨论另外写文。
如果是依赖Activity,不应该依赖于目标是否存在,应该在目标Activity的onStart或onResume里面,判断共享的变量来执行操作。
根据实际情况,使用singleTask和singleInstance,用onNewIntent来做变更也可以。
Activity之间互相传递数据可以用startActivityForResult()。
Activity调用Service方法,应该使用Bind。
Service要通知Activity,应该用广播。
Receiver要通知Activity和Service,应该用广播。