Android项目重构之路:架构篇

原创文章,转载请注明:转载自Keegan小钢
并标明原文链接:http://keeganlee.me/post/android/20150605
微信订阅号:keeganlee_me
写于2015-06-05


Android项目重构之路:架构篇
Android项目重构之路:界面篇
Android项目重构之路:实现篇


去年10月底换到了新公司,做移动研发组的负责人,刚开始接手android项目时,发现该项目真的是一团糟。首先是其架构,是按功能模块进行划分的,本来按模块划分也挺好的,可是,他却分得太细,总共分为了17个模块,而好几个模块也就只有两三个类而已。但应用本身其实比较简单,要按功能模块来分的话,最多五个模块就够了。另外,有好多模块划分也很模糊,也有很多类按其功能其实可以属于多个模块的,也有些类定义不明确,做了不该做的事。有时候,我要找一个界面的Activity,按照其功能应该属于A模块的,可是在A模块里却找不到,于是,我只好去AndroidManifest文件里找了,找到才发现原来在B模块里。也有时候,我要找另一个界面的Activity,可我看遍了所有模块,也没看出这个界面应该属于哪个模块,没法子,又只能去AndroidManifest文件里找了,找到才发现竟然在C模块里。代码也是又乱又臭,导致出现一大堆bug又不好找,改好一个bug又出现另一个。整个项目从架构到代码都是又臭又乱,开发人员只是不停地改bug,根本没法做新功能,更别谈扩展了。当时,公司已经有为不同客户定制化app的需求,而现有的架构完全无法满足这样的需求。因此,我决定重构,搭建一个易维护、易扩展、可定制的项目。

我将项目分为了四个层级:模型层、接口层、核心层、界面层。模型层定义了所有的模型;接口层封装了服务器提供的API;核心层处理所有业务逻辑;界面层就处理界面的展示。几个层级之间的关系如下图所示:

下面展开说明具体的每个层次:

接口层

接口层封装了网络底层的API,并提供给核心层调用。刚开始,为了简单,该层的核心类我只定义了4个:

  1. PostEngine,请求引擎类,对请求的发送和响应结果进行处理;
  2. Response,响应类,封装了Http请求返回的数据结构;
  3. Api,接口类,定义了所有接口方法;
  4. ApiImpl,接口实现类,实现所有接口方法。

PostEngine将请求封装好发送到服务器,并对响应结果的json数据转化为Response对象返回。Response其实就是响应结果的json数据实体类,json数据是有固定结构的,分为三类,如下:

{"event": "0", "msg": "success"}
{"event": "0", "msg": "success", "obj":{...}}
{"event": "0", "msg": "success", "objList":[{...}, {...}], "currentPage": 1, "pageSize": 20, "maxCount": 2, "maxPage": 1}

event为返回码,0表示成功,msg则是返回的信息,obj是返回的单个数据对象,objList是返回的数据对象数组,currentPage表示当前页,pageSize则表示当前页最多对象数量,maxCount表示对象数据总量,maxPage表示总共有多少页。根据此结构,Response基本的定义如下:

public class Response<T> {
    private String event;
    private String msg;
    private T obj;
    private T objList;
    private int currentPage;
    private int pageSize;
    private int maxCount;
    private int maxPage;
    
    //getter和setter方法
    ...    
}

每个属性名称都要与json数据对应的名称相一致,否则无法转化。obj和objList用泛型则可以转化为相应的具体对象了。

Api接口类定义了所有的接口方法,方法定义类似如下:

public Response<Void> login(String loginName, String password);
public Response<VersionInfo> getLastVersion();
public Response<List<Coupon>> listNewCoupon(int currentPage, int pageSize);

ApiImpl则实现所有Api接口了,实现代码类似如下:

@Override
public Response<Void> login(String loginName, String password) {
    try {
        String method = Api.LOGIN;
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("loginName", loginName));
        params.add(new BasicNameValuePair("password", EncryptUtil.makeMD5(password)));
        TypeToken<Response<Void>> typeToken = new TypeToken<Response<Void>>(){};
        return postEngine.specialHandle(method, params, typeToken);
    } catch (Exception e) {
        //异常处理
    }
}

实现中将请求参数和返回的类型定义好,调用PostEngine对象进行处理。
接口层的核心基本上就是这些了。

核心层

核心层介于接口层和界面层之间,主要处理业务逻辑,集中做数据处理。向上,给界面层提供数据处理的接口,称为Action;向下,调用接口层向服务器请求数据。向上的Action中定义的方法类似如下:

public void getCustomer(String loginName, CallbackListener<Customer> callbackListener);

这是一个获取用户信息的方法,因为需要向接口层请求服务器Api数据,所以添加了callback监听器,在callback里对返回的数据结果进行操作。CallbackListener就定义了一个成功和一个失败的方法,代码如下:

public interface CallbackListener<T> {
    /**
     * 请求的响应结果为成功时调用
     * @param data  返回的数据
     */
    public void onSuccess(T data);

    /**
     * 请求的响应结果为失败时调用
     * @param errorEvent 错误码
     * @param message    错误信息
     */
    public void onFailure(String errorEvent, String message);
}

接口的实现基本分为两步:

  1. 参数检查,检查参数的合法性,包括非空检查、边界检查、有效性检查等;
  2. 使用异步任务调用接口层的Api,返回响应结果。

需要注意的是,Action是面向界面的,界面上的数据可能需要根据不同情况调用不同的Api。
后续扩展可以在这里添加缓存,但也要视不同情况而定,比如有些变化太快的数据,添加缓存就不太适合了。

界面层

界面层处于最上层,其核心就是负责界面的展示。
因为公司有为不同商户定制不同app的需求,因此,这里就需要建立多个app的界面,这是一个很麻烦的事情,还好,Android Studio提供了很方便的方法可以大大减少工作量,主要通过设置Gradle,不同app可以添加不同的productFlavors。
界面层package的定义我也并不按照旧版的功能模块划分,而根据不同类型划分,主要分为以下几个包:

其中,activity、adapter、fragment各自都有一个基类,做统一的处理,比如定义了一些共用的常量、对象和方法等。
界面层是最复杂,最容易变得混乱不堪,最容易出问题的层级。所以,从架构到代码,很多东西都需要设计好,以及规范好,才能保证程序易维护、易扩展。后续的文章里将会详细分享下我在这方面的经验。

模型层

模型层横跨所有层级,封装了所有数据实体类,基本上也是跟json的obj数据一致的,在接口层会将obj转化为相应的实体类,再通过Action传到界面层。另外,模型层还定义了一些常量,比如用户状态、支付状态等。在Api里返回的是用1、2、3这样定义的,而我则用枚举类定义了这些状态。用枚举类定义,就可以避免了边界的检查,同时也更明了,谁会记得那么多1、2、3都代表什么状态呢。然而用枚举类定义的话,就必须能将1、2、3转化为相应的枚举常量。这里,我提供两种实现方式:
1.使用gson的@SerializedName标签,比如0为FALSE,1为TRUE,则可以如下定义:

public enum BooleanType {
    @SerializedName("0")
    FALSE,
    @SerializedName("1")
    TRUE
}

2.通过定义一个value,如下:

public enum BooleanType {
    FALSE("0"),
    TRUE("1");
    
    private String value;

    BooleanType(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

通过gson的方式,直接访问TRUE或FALSE就会自动序列化为1或0;如果通过第二种方式,因为没有序列化,则需要通过getValue方式获取1或0。

结束

以上就是最基本的架构了,讲得比较简单,只列了几个核心的东西。并没有进一步去扩展,扩展是下一步的事情了,后续的文章里会慢慢展开。


扫描以下二维码即可关注订阅号。

Comments
Write a Comment
  • bdll reply

    很好,楼主总结的全面,有几个个人建议

    1、接口层的返回objList我觉得是多余了,多多少少包含了业务逻辑,有obj我觉得足够了

    2、为什么是在接口层转化相应的实体类?应该由核心层吧,这样接口层不会有什么耦合

    如果楼主把基础架构开源讨论就更好了

  • Keegan小钢 reply

    @bdll,谢谢你的建议。

    1、首先obj和objList并不是我定义的,是我们的后台人员早定义好的;当然,如果由我来定义,我会更喜欢命名为data,那样显得更明了。

    2、首先,接口层是要根据Api协议文档去封装接口的,包括哪个接口返回什么对象,如果转化移到了核心层,那等于核心层也要去看Api协议文档,这样才知道哪个接口要转化为哪个对象,这样就达不到分层的作用了。核心层不应该还要去看协议文档,这是接口层做的事情。

    最后,开源的建议很好,这样的话我还需要再花些时间将其调整为通用的架构才行。

  • wjj reply

    谢谢楼主分享,现在我们的项目主要分为接口层,界面层,模型层,我们将核心层的代码写在了界面层,界面层做的就是拿到数据,检查数据,请求接口,显示数据更新ui,现在想代码重构,不太明白核心层这块怎么搞,菜鸟一枚,谢谢!

  • Keegan小钢 reply

    @wjj 你可以把拿数据,检查数据,请求接口都放到核心层,显示数据更新UI才在界面层做。

  • wjj reply

    @keegan704 核心层这块写个DAO,DAOImpl,接口中写个监听回调(失败,成功,空),核心层这块主要就是数据检查,请求接口,回调界面层。(但有个困惑,我们以前将这块放在界面层的原因是Android这块逻辑不怎么多,暂时不涉及缓存什么的,目前这种情况觉得再分个层累赘,核心层这块如果这么做的话基本就是个检查数据,回调界面层更新ui)

  • Keegan小钢 reply

    @wjj 你觉得Android这块逻辑不多,那可能是你们有很多东西还没做,或者是现在代码还不多。等东西多了,可能就会觉得有些乱了。分层就是为了能有更好的可读性、维护性、扩展性,减低耦合性。界面层就应该只关心界面如何展示,对于数据怎么检查,是从缓存还是网络取数据,这些交给核心层去做就好了。另外,如果你们团队以后扩展了,分层好的话那就可以有人专门做界面,有人专门做数据逻辑。

  • wjj reply

    谢谢,希望楼主有时间把基础架构开源学习学习

  • Robin reply

    @keegan704 楼主的架构网络请求能用线程吗?怎么用?

  • Keegan小钢 reply

    @Robin 在核心层用自定义的异步任务请求网络,异步任务继承自AsyncTask完成的

  • Robin reply

    @keegan704 楼主的架构网络请求能用线程吗?怎么用?

  • Robin reply

    @keegan704 哦,谢谢,刚才刷新界面,自动重发了一遍问题,可以删掉

  • ssd reply

    新手来阅读,谢谢!

  • Gao reply

    非常期待楼主能做成一个通用的架构,学习一下

  • Keegan小钢 reply

    @Gao 授人以鱼不如授人以渔,我写这个系列的文章是为了教一些新手怎么去构建,而不是直接拿来用。现在也只在写实现篇,写完也会将源代码开源。

  • Gao reply

    @keegan704 倒不是直接拿来用,主要是有代码更能深入理解,期待楼主

  • 为什么不考虑使用现有的开源框架呢?

  • Keegan小钢 reply

    @aspen 你说什么框架呢?

  • cuixbo reply

    请问你们的service,receiver,application放在哪些包里呢

  • enjoyzhao reply

    先对博主赞一个,我大致搜索了好多都是介绍单个实例的,只有这个博上面介绍项目框架的,给了我很大帮助。不过我最近看到一个类似也不错的框架,分享给有需要的人 共同学习 实例地址:https://github.com/saulmm/Material-Movies

  • Keegan小钢 reply

    @cuixbo service,receiver,application这些也是android组件元素,当然和activity一样是放在界面层。

  • Keegan小钢 reply

    @enjoyzhao Material-Movies我看了一下,其框架的确也挺不错,可以学习学习

  • 先对博主无私的分享点个赞,我感觉这个架构设计还是有少许瑕疵,把这个架构放在一个项目上看不出问题,但有多个项目去开发使用接口类,我感觉移植性可能会差点。如果吧接口层与模型层解偶后可能会更好点!一点建议,仅供参考!

  • Keegan小钢 reply

    @core 谢谢你的建议。我们现有的架构已经是支持多个项目的,因为每个层次都是分离的,并不存在移植性的问题。不过这系列文章没有提到怎么适配多个项目的情况。这系列文章只是讲架构的一些基础东西,所以没有考虑那么多,根据实际情况也是需要做些调整的。这系列文章更重要的其实是想传达一些如何架构的思想。

  • fly-tiger reply

    真不错,Response 这个看不太懂,返回的Type类型是不是多余的,建议楼主把登录啊,版本检查,错误检查,分享功能,拿数据等等这些抽象出来弄个通用框架我们深入了解一下

  • 不知道博主有没有接触过Eventbus.如果针对架构方面来讲.处理网络层次可以通过他来解耦.不捆绑Act/Fra/Service.大概方式为在baseAct/baseFra/baseService中进行Event的注册.并且在onMainThread的方法中传baseEvent事件.执行期performance(Context context,Fragement fragment)方法.有一個常驻的EventManger来单例出来负责post/注册/注销事件.有一個baseEvent抽象类.如创建一個HelloEvent.同时会创建与其逻辑相关的接口(用以实际的Act/Fra/Service调用).HelloInterface.当post HelloEvent事件的时候.在其实现BaseEvent的performance方法.通过形参传输过来的Act/Fra.判断该传过来的Act/Fra是否实现了和我们的HelloInterface.同时把Act/Fra强转为HelloInterface然后调用其定义的方法.这样完全一套逻辑代码就完成了很好的sdk开发.话说的有点多.有点乱.不知道博主能否理解我的表述.

  • Keegan小钢 reply

    @chenzj 的确是有点乱,但我看不出“处理网络层次可以通过他来解耦”是怎么解耦的?EventBus本身是一个组件之间的通信库,怎么处理网络层次呢?

  • @keegan704 其实刚好是在我公司项目实际运用了.因为我可能多个Act/Fra都需要访问同一个接口.每次如果用类似博主的方式回调回来再处理.相对来讲感觉在不同的Act/Fra中要写不少代码.如果类似我上述讲的方式.如果我们是在做sdk.我们使用的时候只需要调用一下网络接口的方法.然后同时实现对应逻辑的接口即可.甚至Eventbus本来就在主线程中跑.我们不需要类似平常回调那样又在Handler中进行处理.相关数据的处理全部都在我们sdk中实现了.使用者只需要收到List/Bean后对UI进行改动即可.个人感觉这样用的会挺好的样子..

  • Keegan小钢 reply

    @chenzj 我还是不清楚你们具体是怎样的实现,我的理解就是,你们这套东西更多的是界面层的优化。如果有兴趣细聊,可以发信息到我的微信订阅号。

  • peak reply

    "模型层横跨所有层级"

    -博主没有理解层的概念

  • Keegan小钢 reply

    @peak 那你解释下层的概念?

  • peak reply

    可以参考tcp/ip协议分层的架构:

    1.每一层有自己的职责。

    2.上层不知道下层的实现细节,只知道下层提供的功能接口。

    3.下层不知道上层的存在。

    所以不存在有一层可以横跨所有层级。

    你对model层的理解更像是一个模块,所有的其他模块都可以访问依赖,这种方式很常见但不可靠。model layer是一个app架构最重要的一环,如果所有的类都对model layer有读写权限,model layer相当于不存在,只是把model的类放到了一个工程目录里。

  • peak reply

    再啰嗦几句。

    我在网上翻过很多关于架构的文章,android也好,iOS也好,谈的更多的都是对工程结构的划分,涉及架构的部分非常少。

    很多移动项目都有自己的架构方式,很难分出好坏高低。但只要谈到架构,都不是简单分个层,划个模块就了事。架构是一种规范和强约束,是结合具体项目之后用工程的思维去搭建代码的方式。要符合所有组员包括架构师自己的理解,大家能认同在这一套方式之下一起开发搭建业务。这种前提之下,代码是谁写的并不重要,所有的代码理解起来都像自己写的一样自然。

    个人觉得一个好的架构要能清晰的回答以下几个问题:

    1. 如何让model layer稳定,一致,可靠?

    a. 稳定是指限制model的写权限,如果一个model向全局变量一样谁都可以改,调试维护起来必然麻烦。

    b. 一致性,应用层不同模块由相同的model驱动。不能出现activity A界面更新了,activity B展示的还是老数据。

    c. 可靠,model与db的交互方式,所有的增删改都不能丢失。

    2. 如何让应用层代码合理的解耦内聚?

    无论是iOS的controller还是android的activity,都容易变成fat MVC。怎么样找到一种方式去拆分这部分代码很重要。如果一个工程师能清楚的知道他每一个函数该放到哪一个类,这样应用层才好维护。 关于这一块有很多成熟的方案了,mvc,mvvm,mvp等等,但这些是方案,细节还需要架构师自己敲定。

    3. 要有清晰的data flow。

    一个app说到底是关于data的变化和展现。从用户输入采集数据,上报服务器,加工再展示。这个流程能不能在你的架构里看出清晰的data flow很重要。工程师在遇到bug的时候第一反应是查数据是不是出了问题,头脑里有data flow就能快速的定位问题。

    希望博主后续文章能阐述下上面几个问题。

  • Keegan小钢 reply

    @peak Thx for ur questions! 问题很有深度。

    首先,关于model层,更准确地来说,的确是一个模块,之所以叫层,主要是因为它和其他三个层属于平级的概念,所以就简单点也称为了层。

    接着,我想说说目前的一些现状和看法。就如你说的,网上关于移动项目的架构方面的文章非常少,更多的只是说说工程结构而已。为什么会这样呢?主要是因为目前大部分的移动项目还是比较小,开发团队的人员也不多,所以并不需要考虑太多解耦、扩展之类的问题,同样也不需要谈什么架构了。另外,在移动端这一块,懂得架构的人也不多。而且,移动端的架构,并不是将后端架构直接移植过来就适用的。因此,目前对移动端架构的需求其实还是比较小的。但是,随着移动技术的发展,像淘宝、微信之类的超级app会越来越多,对移动端架构的需求也会越来越多,分层解耦、自动化测试、持续交付等等需求会越来越多。在这样的大背景下,广大的移动端程序猿们就有必要学学移动端的架构。而我这三篇系列文章,只是移动端架构的入门篇,力求简单,而没有考虑太多优化。

    好了,扯得有点多,最后再来说说你的三个问题:

    1、目前这个入门架构,model layer的稳定、一致、可靠性还是有保障的,model的数据是在接口层写入的,再从API传到数据层再传到界面层,中间也不会有丢失。确切地说,model layer的稳定、一致、可靠性是受制于API的,因为这个架构的model是跟API返回的json数据模型一致的。

    2、为什么要抽出一个核心层,主要目的就是为了解耦activity,这跟MVP的思想是类似的。

    3、data flow也是清晰的,从界面层,到核心层,最后到接口层,一条线下来,哪里出的问题是很容易定位的。

    欢迎继续讨论~~

  • vudiy reply

    感谢楼主的分享,以及各位评论者提供的意见,都是学习的资料,谢大家

  • loutao reply

    學習到了,必須點贊!

  • river reply

    要是有demo就好了

  • river reply

    要是有demo就好了,楼主什么时候给个demo,方便理解哈

  • Keegan小钢 reply

    @river Demo在github上,地址在实现篇最后

  • 凯子哥 reply

    恩恩,看了有收获

  • grass reply

    写的很好,讨论非常精彩,@peak问得问题很有针对性

  • 刚子 reply

    写的真好,楼主,可以加你为好友吗?我的qq是328584523

  • 刚子 reply

    楼主,我问下那个对网络请求的那个PostEngine如果是用于请求,然后页面刷新的怎么办,还有就是子线程中的处理

  • Keegan小钢 reply

    @刚子 PostEngine只是对请求的封装处理,页面刷新和子线程处理这些是表示层的事,跟它没有直接关系的啊~有问题也可以微信公众号联系我

  • chn reply

    经常用枚举的话,性能开销大,楼主怎么看?

  • Keegan小钢 reply

    @chn 用枚举并不会带来什么性能问题啊,你的项目里枚举难道会多过于其他类吗?用了那么多类,几百上千个类,性能开销大吗?

  • doney reply

    同感,这个obj和ObjList应该可以合并成 T data来用才比较合适。

  • Keegan小钢 reply

    @doney 我也想的,但是我们的接口本身已经是分开的,我也没权利去把它合并啊~~

  • 现在一般都用android的注解来取代枚举。现在都不推荐使用枚举了

  • yizi reply

    我敢说,作者肯定是从java后台转过来的,这些我个人觉得在安卓里面做不是很合适

  • Keegan小钢 reply

    @yizi 我从09年开始做java web,从11年开始做android。不过,为什么觉得不是很合适呢?你至少也要说下理由啊?

  • yizi reply

    首先读的开头,找activity的那段觉得你找的太累了。找一个页面,有一个很简单的方法,就是在activity的基类中的onCreate方法里面,打印log--getClass().getName(),这样你每点开一个页面就可以直接看到当前activity的包名加类名。然后是是分类的那段,还是习惯以模块划分。

  • yizi reply

    另外不好意思,我那样随意论不太好,可以麻烦你删掉我这些评论吗。感谢作者的分享!

  • Keegan小钢 reply

    @yizi 不太明白你的评论?好像跟前面的问题无关?另外,评论是无法删除的

  • guanxp reply

    这种根据不同类型划分包的策略违反了共同重用原则,一个很明显的问题是各个包之间会存在很多原本不需要的import。

  • Keegan小钢 reply

    @guanxp 那你觉得该如何优化?

  • unknown reply

    我想说的是...移动本身是快速发展的,各种快速迭代.如果楼主这样的架构实现动态部署 代价会不会太大了? 与其这样分层,为何不如把模块的概念换成容器的概念? 而不是像楼主这样的水平开发模式.

    简单的描述一下我的看法:

    可以把水平转化成为垂直(常规的是界面,业务,通信,数据模型.把每个模块转化成容器,而每个容器又具有界面层业务层,模型层,通信层[通信层直接引用了一个pulic libry,解决代码重复的问题])

    而每个容器之间因为处于同级,是不允许直接访问的.可能需要一些设计模式来支撑一些数据的共享和访问,来达到容器的绝对独立,这是动态部署最核心的一部分.测试层面来说 也不会因为你改了容器a而影响其他容器。

  • 平时写代码还是太随意,怎么方便怎么来,逻辑处理直接写在工具类里,哈哈

  • Keegan小钢 reply

    @unknown 我觉得我现在的这个架构才是垂直模式吧,垂直方向上的分层,而你说的容器模式才是水平上扩展的模式。其实,用哪种架构更合适,都要看具体项目的需求是怎样的。而我采用这种架构,是因为我们项目的需求在通信和业务逻辑层方面基本固定,但界面需要适配多个app,分层是最合适的。如果想QQ、微信、支付宝这样的,那用你说的容器模式则更适合,只是它们的架构也并不只是容器这么简单,也有用了插件化开发的模式。

  • 有态度网友06MY5V reply

    很好,楼主总结的全面,有几个个人建议<br>1、接口层的返回objList我觉得是多余了,多多少少包含了业务逻辑,有obj我觉得足够了<br>2、为什么是在接口层转化相应的实体类?应该由核心层吧,这样接口层不会有什么耦合<br><br>如果楼主把基础架构开源讨论就更好了

  • 有态度网友06MY5V reply

    @bdll,谢谢你的建议。<br>1、首先obj和objList并不是我定义的,是我们的后台人员早定义好的;当然,如果由我来定义,我会更喜欢命名为data,那样显得更明了。<br>2、首先,接口层是要根据Api协议文档去封装接口的,包括哪个接口返回什么对象,如果转化移到了核心层,那等于核心层也要去看Api协议文档,这样才知道哪个接口要转化为哪个对象,这样就达不到分层的作用了。核心层不应该还要去看协议文档,这是接口层做的事情。<br>最后,开源的建议很好,这样的话我还需要再花些时间将其调整为通用的架构才行。

  • 有态度网友06MY5V reply

    谢谢楼主分享,现在我们的项目主要分为接口层,界面层,模型层,我们将核心层的代码写在了界面层,界面层做的就是拿到数据,检查数据,请求接口,显示数据更新ui,现在想代码重构,不太明白核心层这块怎么搞,菜鸟一枚,谢谢!

  • 有态度网友06MY5V reply

    @wjj 你可以把拿数据,检查数据,请求接口都放到核心层,显示数据更新UI才在界面层做。

  • 有态度网友06MY5V reply

    @keegan704 核心层这块写个DAO,DAOImpl,接口中写个监听回调(失败,成功,空),核心层这块主要就是数据检查,请求接口,回调界面层。(但有个困惑,我们以前将这块放在界面层的原因是Android这块逻辑不怎么多,暂时不涉及缓存什么的,目前这种情况觉得再分个层累赘,核心层这块如果这么做的话基本就是个检查数据,回调界面层更新ui)

  • 有态度网友06MY5V reply

    @wjj 你觉得Android这块逻辑不多,那可能是你们有很多东西还没做,或者是现在代码还不多。等东西多了,可能就会觉得有些乱了。分层就是为了能有更好的可读性、维护性、扩展性,减低耦合性。界面层就应该只关心界面如何展示,对于数据怎么检查,是从缓存还是网络取数据,这些交给核心层去做就好了。另外,如果你们团队以后扩展了,分层好的话那就可以有人专门做界面,有人专门做数据逻辑。

  • 有态度网友06MY5V reply

    谢谢,希望楼主有时间把基础架构开源学习学习

  • 有态度网友06MY5V reply

    @keegan704 楼主的架构网络请求能用线程吗?怎么用?

  • 有态度网友06MY5V reply

    @Robin 在核心层用自定义的异步任务请求网络,异步任务继承自AsyncTask完成的

  • 有态度网友06MY5V reply

    @keegan704 哦,谢谢,刚才刷新界面,自动重发了一遍问题,可以删掉

  • 有态度网友06MY5V reply

    新手来阅读,谢谢!

  • 有态度网友06MY5V reply

    非常期待楼主能做成一个通用的架构,学习一下

  • 有态度网友06MY5V reply

    @Gao 授人以鱼不如授人以渔,我写这个系列的文章是为了教一些新手怎么去构建,而不是直接拿来用。现在也只在写实现篇,写完也会将源代码开源。

  • 有态度网友06MY5V reply

    @keegan704 倒不是直接拿来用,主要是有代码更能深入理解,期待楼主

  • 有态度网友06MY5V reply

    为什么不考虑使用现有的开源框架呢?

  • 有态度网友06MY5V reply

    @aspen 你说什么框架呢?

  • 有态度网友06MY5V reply

    请问你们的service,receiver,application放在哪些包里呢

  • 有态度网友06MY5V reply

    先对博主赞一个,我大致搜索了好多都是介绍单个实例的,只有这个博上面介绍项目框架的,给了我很大帮助。不过我最近看到一个类似也不错的框架,分享给有需要的人 共同学习 实例地址:https://github.com/saulmm/Material-Movies

  • 有态度网友06MY5V reply

    @cuixbo service,receiver,application这些也是android组件元素,当然和activity一样是放在界面层。

  • 有态度网友06MY5V reply

    @enjoyzhao Material-Movies我看了一下,其框架的确也挺不错,可以学习学习

  • 有态度网友06MY5V reply

    先对博主无私的分享点个赞,我感觉这个架构设计还是有少许瑕疵,把这个架构放在一个项目上看不出问题,但有多个项目去开发使用接口类,我感觉移植性可能会差点。如果吧接口层与模型层解偶后可能会更好点!一点建议,仅供参考!

  • 有态度网友06MY5V reply

    @core 谢谢你的建议。我们现有的架构已经是支持多个项目的,因为每个层次都是分离的,并不存在移植性的问题。不过这系列文章没有提到怎么适配多个项目的情况。这系列文章只是讲架构的一些基础东西,所以没有考虑那么多,根据实际情况也是需要做些调整的。这系列文章更重要的其实是想传达一些如何架构的思想。

  • 有态度网友06MY5V reply

    真不错,Response 这个看不太懂,返回的Type类型是不是多余的,建议楼主把登录啊,版本检查,错误检查,分享功能,拿数据等等这些抽象出来弄个通用框架我们深入了解一下

  • 有态度网友06MY5V reply

    不知道博主有没有接触过Eventbus.如果针对架构方面来讲.处理网络层次可以通过他来解耦.不捆绑Act/Fra/Service.大概方式为在baseAct/baseFra/baseService中进行Event的注册.并且在onMainThread的方法中传baseEvent事件.执行期performance(Context context,Fragement fragment)方法.有一個常驻的EventManger来单例出来负责post/注册/注销事件.有一個baseEvent抽象类.如创建一個HelloEvent.同时会创建与其逻辑相关的接口(用以实际的Act/Fra/Service调用).HelloInterface.当post HelloEvent事件的时候.在其实现BaseEvent的performance方法.通过形参传输过来的Act/Fra.判断该传过来的Act/Fra是否实现了和我们的HelloInterface.同时把Act/Fra强转为HelloInterface然后调用其定义的方法.这样完全一套逻辑代码就完成了很好的sdk开发.话说的有点多.有点乱.不知道博主能否理解我的表述.

  • 有态度网友06MY5V reply

    @chenzj 的确是有点乱,但我看不出“处理网络层次可以通过他来解耦”是怎么解耦的?EventBus本身是一个组件之间的通信库,怎么处理网络层次呢?

  • 有态度网友06MY5V reply

    @keegan704 其实刚好是在我公司项目实际运用了.因为我可能多个Act/Fra都需要访问同一个接口.每次如果用类似博主的方式回调回来再处理.相对来讲感觉在不同的Act/Fra中要写不少代码.如果类似我上述讲的方式.如果我们是在做sdk.我们使用的时候只需要调用一下网络接口的方法.然后同时实现对应逻辑的接口即可.甚至Eventbus本来就在主线程中跑.我们不需要类似平常回调那样又在Handler中进行处理.相关数据的处理全部都在我们sdk中实现了.使用者只需要收到List/Bean后对UI进行改动即可.个人感觉这样用的会挺好的样子..

  • 有态度网友06MY5V reply

    @chenzj 我还是不清楚你们具体是怎样的实现,我的理解就是,你们这套东西更多的是界面层的优化。如果有兴趣细聊,可以发信息到我的微信订阅号。

  • 有态度网友06MY5V reply

    模型层横跨所有层级<br>-博主没有理解层的概念

  • 有态度网友06MY5V reply

    @peak 那你解释下层的概念?

  • 有态度网友06MY5V reply

    可以参考tcp/ip协议分层的架构:<br>1.每一层有自己的职责。<br>2.上层不知道下层的实现细节,只知道下层提供的功能接口。<br>3.下层不知道上层的存在。<br><br>所以不存在有一层可以横跨所有层级。<br>你对model层的理解更像是一个模块,所有的其他模块都可以访问依赖,这种方式很常见但不可靠。model layer是一个app架构最重要的一环,如果所有的类都对model layer有读写权限,model layer相当于不存在,只是把model的类放到了一个工程目录里。

  • 有态度网友06MY5V reply

    再啰嗦几句。<br>我在网上翻过很多关于架构的文章,android也好,iOS也好,谈的更多的都是对工程结构的划分,涉及架构的部分非常少。<br>很多移动项目都有自己的架构方式,很难分出好坏高低。但只要谈到架构,都不是简单分个层,划个模块就了事。架构是一种规范和强约束,是结合具体项目之后用工程的思维去搭建代码的方式。要符合所有组员包括架构师自己的理解,大家能认同在这一套方式之下一起开发搭建业务。这种前提之下,代码是谁写的并不重要,所有的代码理解起来都像自己写的一样自然。<br><br>个人觉得一个好的架构要能清晰的回答以下几个问题:<br>1. 如何让model layer稳定,一致,可靠?<br>a. 稳定是指限制model的写权限,如果一个model向全局变量一样谁都可以改,调试维护起来必然麻烦。<br>b. 一致性,应用层不同模块由相同的model驱动。不能出现activity A界面更新了,activity B展示的还是老数据。<br>c. 可靠,model与db的交互方式,所有的增删改都不能丢失。<br><br>2. 如何让应用层代码合理的解耦内聚?<br>无论是iOS的controller还是android的activity,都容易变成fat MVC。怎么样找到一种方式去拆分这部分代码很重要。如果一个工程师能清楚的知道他每一个函数该放到哪一个类,这样应用层才好维护。 关于这一块有很多成熟的方案了,mvc,mvvm,mvp等等,但这些是方案,细节还需要架构师自己敲定。<br><br>3. 要有清晰的data flow。<br>一个app说到底是关于data的变化和展现。从用户输入采集数据,上报服务器,加工再展示。这个流程能不能在你的架构里看出清晰的data flow很重要。工程师在遇到bug的时候第一反应是查数据是不是出了问题,头脑里有data flow就能快速的定位问题。<br><br>希望博主后续文章能阐述下上面几个问题。

  • 有态度网友06MY5V reply

    @peak Thx for ur questions! 问题很有深度。<br>首先,关于model层,更准确地来说,的确是一个模块,之所以叫层,主要是因为它和其他三个层属于平级的概念,所以就简单点也称为了层。<br>接着,我想说说目前的一些现状和看法。就如你说的,网上关于移动项目的架构方面的文章非常少,更多的只是说说工程结构而已。为什么会这样呢?主要是因为目前大部分的移动项目还是比较小,开发团队的人员也不多,所以并不需要考虑太多解耦、扩展之类的问题,同样也不需要谈什么架构了。另外,在移动端这一块,懂得架构的人也不多。而且,移动端的架构,并不是将后端架构直接移植过来就适用的。因此,目前对移动端架构的需求其实还是比较小的。但是,随着移动技术的发展,像淘宝、微信之类的超级app会越来越多,对移动端架构的需求也会越来越多,分层解耦、自动化测试、持续交付等等需求会越来越多。在这样的大背景下,广大的移动端程序猿们就有必要学学移动端的架构。而我这三篇系列文章,只是移动端架构的入门篇,力求简单,而没有考虑太多优化。<br>好了,扯得有点多,最后再来说说你的三个问题:<br>1、目前这个入门架构,model layer的稳定、一致、可靠性还是有保障的,model的数据是在接口层写入的,再从API传到数据层再传到界面层,中间也不会有丢失。确切地说,model layer的稳定、一致、可靠性是受制于API的,因为这个架构的model是跟API返回的json数据模型一致的。<br>2、为什么要抽出一个核心层,主要目的就是为了解耦activity,这跟MVP的思想是类似的。<br>3、data flow也是清晰的,从界面层,到核心层,最后到接口层,一条线下来,哪里出的问题是很容易定位的。<br>欢迎继续讨论~~

  • 有态度网友06MY5V reply

    感谢楼主的分享,以及各位评论者提供的意见,都是学习的资料,谢大家

  • 有态度网友06MY5V reply

    學習到了,必須點贊!

  • 有态度网友06MY5V reply

    要是有demo就好了

  • 有态度网友06MY5V reply

    要是有demo就好了,楼主什么时候给个demo,方便理解哈

  • 有态度网友06MY5V reply

    @river Demo在github上,地址在实现篇最后

  • 有态度网友06MY5V reply

    恩恩,看了有收获

  • 有态度网友06MY5V reply

    写的很好,讨论非常精彩,@peak问得问题很有针对性

  • 有态度网友06MY5V reply

    写的真好,楼主,可以加你为好友吗?我的qq是328584523

  • 有态度网友06MY5V reply

    楼主,我问下那个对网络请求的那个PostEngine如果是用于请求,然后页面刷新的怎么办,还有就是子线程中的处理

  • 有态度网友06MY5V reply

    经常用枚举的话,性能开销大,楼主怎么看?

  • 有态度网友06MY5V reply

    @chn 用枚举并不会带来什么性能问题啊,你的项目里枚举难道会多过于其他类吗?用了那么多类,几百上千个类,性能开销大吗?

  • 有态度网友06MY5V reply

    同感,这个obj和ObjList应该可以合并成 T data来用才比较合适。

  • 有态度网友06MY5V reply

    @doney 我也想的,但是我们的接口本身已经是分开的,我也没权利去把它合并啊~~

  • 有态度网友06MY5V reply

    现在一般都用android的注解来取代枚举。现在都不推荐使用枚举了

  • 有态度网友06MY5V reply

    我敢说,作者肯定是从java后台转过来的,这些我个人觉得在安卓里面做不是很合适

  • 有态度网友06MY5V reply

    @yizi 我从09年开始做java web,从11年开始做android。不过,为什么觉得不是很合适呢?你至少也要说下理由啊?

  • 有态度网友06MY5V reply

    首先读的开头,找activity的那段觉得你找的太累了。找一个页面,有一个很简单的方法,就是在activity的基类中的onCreate方法里面,打印log--getClass().getName(),这样你每点开一个页面就可以直接看到当前activity的包名加类名。然后是是分类的那段,还是习惯以模块划分。

  • 有态度网友06MY5V reply

    另外不好意思,我那样随意论不太好,可以麻烦你删掉我这些评论吗。感谢作者的分享!

  • 有态度网友06MY5V reply

    @yizi 不太明白你的评论?好像跟前面的问题无关?另外,评论是无法删除的

  • 有态度网友06MY5V reply

    这种根据不同类型划分包的策略违反了共同重用原则,一个很明显的问题是各个包之间会存在很多原本不需要的import。

  • 有态度网友06MY5V reply

    @guanxp 那你觉得该如何优化?

  • 有态度网友06MY5V reply

    我想说的是...移动本身是快速发展的,各种快速迭代.如果楼主这样的架构实现动态部署 代价会不会太大了? 与其这样分层,为何不如把模块的概念换成容器的概念? 而不是像楼主这样的水平开发模式.<br>简单的描述一下我的看法:<br>可以把水平转化成为垂直(常规的是界面,业务,通信,数据模型.把每个模块转化成容器,而每个容器又具有界面层业务层,模型层,通信层[通信层直接引用了一个pulic libry,解决代码重复的问题])<br>而每个容器之间因为处于同级,是不允许直接访问的.可能需要一些设计模式来支撑一些数据的共享和访问,来达到容器的绝对独立,这是动态部署最核心的一部分.测试层面来说 也不会因为你改了容器a而影响其他容器。

  • 有态度网友06MY5V reply

    平时写代码还是太随意,怎么方便怎么来,逻辑处理直接写在工具类里,哈哈

  • 有态度网友06MY5V reply

    @unknown 我觉得我现在的这个架构才是垂直模式吧,垂直方向上的分层,而你说的容器模式才是水平上扩展的模式。其实,用哪种架构更合适,都要看具体项目的需求是怎样的。而我采用这种架构,是因为我们项目的需求在通信和业务逻辑层方面基本固定,但界面需要适配多个app,分层是最合适的。如果想QQ、微信、支付宝这样的,那用你说的容器模式则更适合,只是它们的架构也并不只是容器这么简单,也有用了插件化开发的模式。

  • 有态度网友06MY5- reply

    写的不错,感谢分享

  • 有态度网友06MY62 reply

    能给一份 架构的源码吗?279598125@qq.com<br>

  • 有态度网友06MY5Z reply

    github上有,请前往实现篇结尾处,地址在那里

  • 有态度网友06MY6i reply

    博主,看完你四篇代码重构,我有几个问题请教下。首先是分层、软甲设计框架、模块划分的区别,我们在开发中遇到很多框架MVC、MVVM、MVP,分层和这几个框架感觉没啥区别,我现在开发主要是分模块,比如说数据库模块、网络模块、用户管理模块等,模块里面应该包含了你所说的模型层、核心层、接口层,界面负责和模块进行交互,你的想法是将模块整合将公共模块和业务模块分开,比如说网络操作用户模块有请求验证码、注册什么的这些需要用到网络,商品展示模块有请求商品价格信息等,按照分层的意思这些应该是同一类的东西应该放在一个网络核心文件处理。这样做的好处是啥?第二个就是GSON的使用,因为之前也使用过GSON,的确大大方便了数据的对象转换,但是GSON也有很多弊病,如果服务端增加了一个字段之前发出去的版本就无法解析。

  • 有态度网友06MY5Z reply

    首先,MVC、MVVM、MVP这些是设计模式,框架只是对这些模式的一种实现。分层的好处,举个简单的例子,TCP/IP协议,为什么要分为7层?你要先理解这个。至于GSON,只有你定义的字段才会解析,没有定义的并不会解析的啊,我不太了解你无法解析具体的情况是怎样的,我在实际应用中并没有问题。

  • 有态度网友06MY6i reply

    谢谢你的回复,就像你说的 TCP/IP 协议分层应该主要是高内聚低耦合,每一层都完成自己特定的工作对上层来说只是接口提供,我可不可以理解为设计模式是框架的大纲,分层是具体的实现细节。最后的 Gson 是之前遇到的一个问题,之前定义好的服务端返回信息修改返回信息导致模型转换的时候数据无法转换,GSON主要是使用代码的反射来将 JSON 转换为对象的 JAVA对象导致失败,所以后来就没怎么用了。这个不提!

  • 萧子然 reply

    总体来说算架构还是按老套路来。

  • 有态度网友06MY6n reply

    博主,转载了你的文章。有个问题,你这个架构不是MVP的模式,应该算MVC吧,model层和app层没隔离,会不会耦合比较重?

  • 有态度网友06MY5Z reply

    目前这个架构,从设计模式来划分的话,应该算是MVC的,而且每个层面都对model有依赖,如果换成MVP的话,的确可以解耦model和app层,但是否真的有必要分离,以及具体怎么实现,我还没有仔细考虑过

  • m18673403481 reply

    发。

  • m18673403481 reply

    你那模型层 接口层 和 核心层都属于mvc的m吧? 模型层是些java bean? 接口层是api调用封装 如网络访问 数据持久化等 业务层距离的业务逻辑?

  • 有态度网友06MY5Z reply

    模型层就是些简单的java bean,接口层就是Api的封装,更确切说是对底层数据的获取和封装

  • 杰_boat reply

    一大串文字,差评

  • 有态度网友06MY5Z reply

    [挖鼻屎]

  • 有态度网友06MY5V reply

    response中 objList 其实也可以用obj封装啊 数组也是对象 , 两者区分开来有什么好处,谢楼主作答<br>

  • 有态度网友06MY5Z reply

    合在一起是更好的,之所以会分开是因为我参与该项目之前,负责接口的人就已经将其分开了,接口层还不是我负责

  • 有态度网友06MY6J reply

    看完文章看评论,又是一番收获,反思自己写的代码,真心没法看

  • 有态度网友06MY6N reply

    写得很好,收益颇多!<br>有一点不是很明白,关于模型层枚举使用gson的@SerializedName标签,通过gson的方式,直接访问TRUE或FALSE就会自动序列化为1或0。这里如何使用这个枚举?<br>譬如 : if(BooleanType.TRUE.equals(1)) <br>这样使用不行,是不是不对?请指点一下,谢谢!<br>

  • 有态度网友06MY5Z reply

    当然不行啦,equals方法是不会将前面的值自动序列化成1的

  • 有态度网友06MY6N reply

    请问那具体怎么用呢?

  • 有态度网友06MY6N reply

    没明白这句话:通过gson的方式,直接访问TRUE或FALSE就会自动序列化为1或0

  • 有态度网友06MY5Z reply

    当你使用GSON在实体对象和Json转化时才会序列化的

  • 有态度网友06MY5V reply

    楼主,我们公司年后马上开始一个新项目,是在原有项目上推倒重来,我打算借机把项目重构一下,一方面方面提高自己,一方面方便以后维护 求楼主给个demo

  • 有态度网友06MY5Z reply

    demo我不是已经放在github了吗

  • 有态度网友06MY5V reply

    接口层直接用spring android不就完美解决了么 干嘛要重新造轮子

  • 有态度网友06MY5Z reply

    spring还有android的扩展?还没了解过,有空去了解下

  • 有态度网友06MY72 reply

    楼主的这种架构思想是值得推荐的,我倒是觉得划分三个层级就足够了,界面层,核心层,数据层。界面层负责采集数据以及展示需要的数据到UI上,核心层负责把从界面层采集来的数据加以处理生成其需要的数据,然后把这些数据交给界面层(展示最新数据)和数据层(缓存最新数据到本地,没有网络时,就把本地数据交给界面层),数据层负责缓存数据。只要核心层写的够漂亮,那么整个项目的耦合性自然也就降低了,可读性也会很高的。

  • 有态度网友06MY5V reply

    你实体类的设计貌似有问题 就是 private T obj; private T objList;可能是我理解有误

  • 有态度网友06MY5Z reply

    你觉得有什么问题呢?既然提出来了,就应该把它说完,不要说一半留一半啦

  • 有态度网友06MY7q reply

    首先,对于楼主对框架分层的理解表示敬佩。是不是少了个Dao层用来访问本地的数据库(比如:sqlLite),还是说楼主把这功能直接在接口实现层实现?

  • 有态度网友06MY7q reply

    还有,就是在移动端的话,个人感觉是不需要业务层(也就是楼主说的核心层),毕竟业务处理是不应该放在移动端来处理的,不然移动端相对会变得比较大,对于移动端本来就应该小的特点,界面层写点逻辑是没问题的,个人感觉业务逻辑尽可能放在后台服务器端来处理,服务端的APO架构不正是单独出一个服务层来就是为了方便移动端的调用,以减少移动端和服务端的交互次数以提高响应速度么?

  • 有态度网友06MY5Z reply

    在接口层实现

  • 有态度网友06MY5Z reply

    移动端的业务逻辑没有服务端的复杂,移动端更多的业务逻辑是对合法数据的检查

  • 有态度网友06MY7G reply

    感觉挺赞的,不过有几个问题请教一下,<br>1:接口使用的实体,和界面操作(或者说数据库)使用的实体你经常会用一个还是分开,毕竟这两个大部分字段都是一样的。<br>2:控制界面的变更,是在核心层里面放一个界面的对象,然后在核心层调用这个对象来更新界面,还是在界面层注册核心层的监听器,然后再界面层自己变更

  • 有态度网友06MY5Z reply

    1、关于实体,简单点就用一个,目前这个架构是这样的,但是,如果要再解耦,则应该分开。<br>2、界面的对象,那应该属于界面层的东西,不应该放到核心层。

  • 有态度网友06MY7Y reply

    core model api 是库文件的形式引用的吧

  • 有态度网友06MY5Z reply

    module分离

  • 有态度网友06MY7Y reply

    谢谢!现在刚进一家公司,它有很多项目,都是基于一套模板二次开发的,但是现在的代码很乱,一个类有几千行代码,领导让我重构合并代码。应该怎么弄?是不是可以把项目中的公用模块(登录,播放音乐等)分出来,做成SDK,或者jar包让别的项目也可以用,求不吝指教!

  • 有态度网友06MY5Z reply

    一点点拆分咯,重构要分步进行的

  • 有态度网友06MY7Y reply

    感觉无从下手。。。

  • 有态度网友06MY5Z reply

    那可以如你说的,可以把公用模块先分出来。另外,推荐看看《重构:改善既有代码的设计》这本书。

  • 有态度网友06MY7Y reply

    好的,谢谢钢哥!

  • 有态度网友06MY5V reply

    是不是还应该有个“通用层”,类似Common,所有工具类都放这个层里面,只要需要这个层里面的工具都可以依赖这一层,并且以后没开发一个项目,该层都可以不变,直接拿过来用就行?

  • 有态度网友06MY5Z reply

    关于通用层,我不是很建议,我们要做的是尽量减少耦合,而不是增加耦合。而且通用层用久了将会发现很难控制,会无止境的臃肿扩大。

  • 有态度网友06MY8k reply

    这个建议不错哦 下次试试看

  • 有态度网友06MY8l reply

    请问楼主所说的接口层的Response类,是对模型层实体类的封装吗

  • 有态度网友06MY5Z reply

    Response类是对接口返回的数据结构的封装

  • 有态度网友06MY8l reply

    就是原始的json串吗,那可不可以就从这里拿出一个工具生成model层

  • 有态度网友06MY8m reply

    还在用接口回调方式,说明已经out了

  • 有态度网友06MY5Z reply

    不用回调那你有其他更好的方式?

  • 有态度网友06MY8m reply

    建议看看 RX,otto等等。不过你的文章也有所收获,谢谢!

  • 青楼满座是因为人心寂寞 reply

    真的很nice,谢谢分享

  • wanggp reply

    请问数据库操作应该放在哪个模块?

  • wanggp reply

    数据库放在api还是模型?

  • 有态度网友06MY5Z reply

    API,model只是简单的javabean

  • 有态度网友06MY5V reply

    翻看楼主的文章,从宏观角度讲的确实不错.接着翻看了所有的评论,从其看出个别理解不太恰当,应该是对层次和模块的理解不够

  • 天青色等煙雨_而我在等妳 reply

    这几个问题问得非常好。

  • 有态度网友06MY9x reply

    大神你看我跪的姿势标准不

  • 有态度网友06MYaa reply

    学习了,收获了很多,现在正在学习软件工程,真是觉得有些时候很模糊确实需要作者这种具体解读

  • 有态度网友06MY5V reply

    博主写得条理不错,先赞一下。然后谈一下个人看法,由于我不是从事移动端纯应用开发的,看法也是基于本人情况而言,可能有理解偏差。<br>关于文章内容我觉得更象是针对一个具体的开发活动(移动端应用开发)的框架而言,框架的目的是能协助具体开发过程、方便项目内容复用和快速复制、便于多人理解掌握和维护等等,它是与具体开发紧密相关的。而架构是更高一层面的东西,涉及如人员的组织和管理、开发框架的选型和组合、开发过程约定规则的制定和执行等等。<br>说了这么多废话,其实总结一下就是“ 架构是抽象的行动纲领,而框架则是落实架构的具体工具,同样的架构可以使用不同的框架,不同的架构可以使用相同的框架,差别在于开发效率、扩展能力、易维护性等等的高低”。

  • 有态度网友06MY5V reply

    我想作者的意图不在于如何去查找一个Activity的位置,页在于表述之前模块的划分实在混乱.<br>你提供的方法不错,我再补一个:<br>Android系统在启动Activity时,Framework模块就已经有Log输入了,<br>TAG为: ActivityManager

  • 有态度网友06MY5Z reply

    是的~主要问题在于模块划分的混乱

  • 有态度网友06MY5V reply

    总体感觉楼主这篇的观点适合小项目

  • 美一分 reply

    这种分层方式在小项目上实现挺好,但是项目越来越大之后,API和ApiImpl层很不好维护。

  • xh reply

    文章很不错