关于一个App的架构思考

对于一个App来说,不管大小,我们在开发的过程中或多或少,都会碰到下面罗列的各种模块,需要我们去处理。

  • 业务处理,对用户输入的校验和展现判断等
  • 统计处理,对当前App或者对业务的数据统计等
  • UI效果,包括主题配置,按钮,输入框,动画效果,自定义控件等
  • 更新升级,当前App的检查更新等
  • 服务器通信,与服务器通信获取数据,心跳连接等
  • 数据解析,比如对json,对xml等的解析等
  • 分享处理,分享到微信朋友圈
  • 通知消息,Notification处理
  • 数据存储,包括SharedPerference和SQLiteDatabase
  • 文件处理,对SDCard的读写
  • 异常处理,对DefaultUncaughtExceptionHandler的使用

这么多的模块,如何对这些模块进行设计,使得各模块间只需要负责自己的业务即可,比如在Activity中,只需要负责展现数据,至于这些数据是通过数据库,还是通过网络获取而来的,并不需要关心,而服务器通信模块,它也只需要去负责去服务器获取数据,并将数据给出去,同样,也不需要关心这数据给谁,它是怎么展现的,这就是所谓的解耦。

First

Created with Raphaël 2.1.0 Activity Activity HttpService HttpService 嘿,我要数据,这是id 稍等,这就去拿, loading by id 数据已拿到了,请拿去处理吧 嗯,可以更新界面了

这是我们所理解的流程,Activity直接调用HttpService,而HttpService直接跟服务器通信,然后获取数据,并告诉Activity,可以更新了,而Activity则拿到数据后,进行界面的更新,Done。

但是我们在代码中会在Activity中直接创建一个HttpService,然后调用HttpService.getData,比如下面这样

HttpService hs = new HttpService();
List data = hs.getData(id);
updateUI(data);

以上,我在做第一个App的时候,我就是这么做的。

Second

很显然,不会,作为Activity,我们不想知道你数据是怎么来的,我们只想知道有数据来,把数据给我们,让我们处理一下即可。
所以,我们会引入一个中间层 MsgDispatcher,它负责转发消息。
首先,声明两个消息,比如叫 MSG_GET_DATAMSG_GET_DATA_RESULT
之后,步骤如下:

  1. HttpService会绑定消息MSG_GET_DATA, 并将自己在MsgDispatcher上登记。
  2. 而 Activity则会绑定消息MSG_GET_DATA_RESULT,并将自己也在MsgDispatcher上登记。

大概就像下面这样:

Created with Raphaël 2.1.0 Activity Activity MsgDispatcher MsgDispatcher HttpService HttpService 绑定消息MSG_GET_DATA_RESULT 注册 绑定消息MSG_GET_DATA 注册

实际业务处理,我们的流程可能会是这样:

Created with Raphaël 2.1.0 Activity Activity MsgDispatcher MsgDispatcher HttpService HttpService MSG_GET_DATA MSG_GET_DATA -> HttpService MSG_GET_DATA handling MSG_GET_DATA_RESULT MSG_GET_DATA_RESULT -> Activity MSG_GET_DATA_RESULT

步骤讲解如下:
1. Activity调用MsgDispatcher发送了个消息 MSG_GET_DATA
2. MsgDispatcher查看谁注册了MSG_GET_DATA, 发现HttpService注册了这个消息,实际上有可能存在多个模块注册了多个消息
3. MsgDispatcher将这个消息发送给HttpService,有可能包含参数
4. HttpService处理完这个消息之后,再调用MsgDispatcher发送消息MSG_GET_DATA_RESULT
5. MsgDispatcher查看谁注册了MSG_GET_DATA_RESULT, 发现Activity注册了这个消息
6. MsgDispatcher将这个消息发送给Activity,有可能包含了处理结果
7. Activity处理这个消息,对界面进行更新

这样的话,我们就实现了HttpService和Activity的解耦,不过由于Android的消息传递,基本上都是通过Handler来实现的,所以在Activity和Service中,每一个Activity和Service中,我们都需要定义一个Handler来接收消息并进行处理。

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_GET_DATA_RESULT:
                    ...
                    break;

以上,我在帮朋友做一个App的时候,就是这么做的。

Third

在上面第二个版本的时候,就会发现,每个Activity,只要需要跟其他模块交互,就必须在当前Activity,实现一个Handler,而如果消息一旦多了,就会发现Handler的处理逻辑特别啰嗦,于是在后面的实现中,我想到又引入了一个中间件,叫CallbackRegister。

CallbackRegister做什么事情呢?就是给Activity注册回调接口中使用的,流程如下:

Created with Raphaël 2.1.0 Activity Activity CallbackRegister CallbackRegister MsgDispatcher MsgDispatcher HttpService HttpService addCallback MSG_GET_DATA -> HttpService MSG_GET_DATA handling getCallbacks handleCallback

具体步骤如下:

  • CallbackRegister定义了一套接口:
public class CallbackRegister {

    public static final int KEY = 1;

    public void addCallback(ActivityCallback, key);

    public void removeCallback(key);

    public List<ActivityCallback> getCallbacks(key);

    public interface ActivityCallback{
        void handleCallback();
    }
}
  • Activity实现这个接口,并将自己注册到CallbackRegister之中
public class Activity implements ActivityCallback {

    public void onCreate() {
        CallbackRegister.addCallack(this, KEY);
    }

    public void onDestroy() {
        CallbackRegister.removeCallback(this, KEY);
    }

    public void handleCallback() {
        //something to do
    }

}
  • Activity调用MsgDispatcher发送了个消息 MSG_GET_DATA
  • MsgDispatcher将这个消息发送给HttpService
  • HttpService处理完之后,从CallbackRegister中获取 key所注册的Callbacks
  • 调用Callback的handleCallback方法
  • 最后注销掉此Callback

OK, 这样的话,Activity就不需要去实现Handler了,取而代之的是, 每新增一个接口,我们需要在CallbackRegister中新增回调接口,然后在我们的Activity中实现即可。

这一种处理方式,本质上,跟Handler实现方式没有什么不一样,所以没有孰优孰劣的说法,看个人喜欢。而实际上,在业内的开发框架中,其实并没有最好的架构,只有自己在开发中慢慢体会,觉得最方便,最喜欢的架构。

一切都是在变化的。

目前业内很流行的EventBus,其实处理原理也是一样的,唯一不同的是,EventBus利用反射在Activity中寻找有固定命名的方法,也是挺不错的。

你可能感兴趣的:(android,模块化,架构)