》 1. 讲体验,讲标准,讲规范。
说适配,说美观,說构图。
谈工时,谈加班,谈星座。。。
最终功能该合并的合并,该去二级菜单的去二级菜单。保持了原菜单不变。
ヽ(✿゚▽゚)ノ
2.架构设计
这里还是个需求密切相关的。不同需求对应不同架构设计。
假如是要做一个某系统的手机端,那么就不需要太多的业务逻辑。只需要做好调用不同的webservice进行增删改查数据罢了。官方控件完全可以满足需求。最多重写一下控件,自定义view,网上教程很多,不是十分困难。
甚至以前读到过有工具能把网页应用直接封装成app轻应用的方法。具体方法忘记了。只记得前阵子很火的2048就是这样的轻应用。
至于有复杂业务逻辑的应用,比如公交地铁换乘,有本地数据库,用到算法的应用,就如@M.A.G.I所说,需要用到设计模式和模式选择。
细节上来说就是分包,目的上是解偶。
fragement,adapter,activity,listener,tool/util,common等等都分开放。
3.命名规则
命名规则有很多高大上的名词,比如大驼峰,小驼峰,匈牙利命名法。
其实最简单的就是按照谷歌命名学习。比如MainActivity,LoginActivity
比如activity_main.xml
比如ic_launcher
等等。个人觉得谷歌做的很贴心了已经。
代码中的变量名啦,方法名啦,按照java命名规范来就很好了。
4.第三方库
个人不建议用。一来是安全稳定性没有保障,另一方面不利于个人学习,容易产生懒惰思想。个人比较喜欢找开源程序代码,看大神的思路,自己实现。这样能有效的提高自己,并去除其他不需要的功能,还能按照自己的风格组织代码。
当然像二维码扫描核心库这种非个人短期能达成的,还是必须拿来就用的zxing(≧∇≦)
说适配,说美观,說构图。
谈工时,谈加班,谈星座。。。
最终功能该合并的合并,该去二级菜单的去二级菜单。保持了原菜单不变。
ヽ(✿゚▽゚)ノ
2.架构设计
这里还是个需求密切相关的。不同需求对应不同架构设计。
假如是要做一个某系统的手机端,那么就不需要太多的业务逻辑。只需要做好调用不同的webservice进行增删改查数据罢了。官方控件完全可以满足需求。最多重写一下控件,自定义view,网上教程很多,不是十分困难。
甚至以前读到过有工具能把网页应用直接封装成app轻应用的方法。具体方法忘记了。只记得前阵子很火的2048就是这样的轻应用。
至于有复杂业务逻辑的应用,比如公交地铁换乘,有本地数据库,用到算法的应用,就如@M.A.G.I所说,需要用到设计模式和模式选择。
细节上来说就是分包,目的上是解偶。
fragement,adapter,activity,listener,tool/util,common等等都分开放。
3.命名规则
命名规则有很多高大上的名词,比如大驼峰,小驼峰,匈牙利命名法。
其实最简单的就是按照谷歌命名学习。比如MainActivity,LoginActivity
比如activity_main.xml
比如ic_launcher
等等。个人觉得谷歌做的很贴心了已经。
代码中的变量名啦,方法名啦,按照java命名规范来就很好了。
4.第三方库
个人不建议用。一来是安全稳定性没有保障,另一方面不利于个人学习,容易产生懒惰思想。个人比较喜欢找开源程序代码,看大神的思路,自己实现。这样能有效的提高自己,并去除其他不需要的功能,还能按照自己的风格组织代码。
当然像二维码扫描核心库这种非个人短期能达成的,还是必须拿来就用的zxing(≧∇≦)
》1.整体架构
代码和文档规范,根据需求进行模块划分,确定交互方式,形成接口文档,这些较为通用的内容不再细说。做Android App时,我一般将App进行纵向和横向的划分。纵向的App由UI层,逻辑层和模型层构成,整体结构基于MVP思想(图片来自网络)。
<img src="https://i-blog.csdnimg.cn/blog_migrate/b19830e87c0ec07a9049d83c545b6e1a.jpeg" data-rawwidth="640" data-rawheight="433" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/9fe1e5679a642f9f82373d2a32d461b7_r.jpg">UI层内部多用模板方法,以Activity为例一般有BaseActivity,提供包括一些基础样式,Dialog,ActionBar在内的内容,展现的Activity都会继承BaseActivity并实现预留的接口,Activity之间的继承不超过3次;为避免Activity内代码过多,将App的整体控制权后移,也借鉴了IOC做法,大量的逻辑操作放在逻辑层中,逻辑层和UI层通过接口或者Broadcast等实现通信,只传递结果。一般Activity里的代码量都很大,通过这两种方式一般我写的单个Activity内代码量不超过400行。 UI层内部多用模板方法,以Activity为例一般有BaseActivity,提供包括一些基础样式,Dialog,ActionBar在内的内容,展现的Activity都会继承BaseActivity并实现预留的接口,Activity之间的继承不超过3次;为避免Activity内代码过多,将App的整体控制权后移,也借鉴了IOC做法,大量的逻辑操作放在逻辑层中,逻辑层和UI层通过接口或者Broadcast等实现通信,只传递结果。一般Activity里的代码量都很大,通过这两种方式一般我写的单个Activity内代码量不超过400行。
逻辑层实现的是绝大部分的逻辑操作,由UI层启动,在内部通过接口调用模型层的方法,在逻辑层内大量使用了代理。打个比方,UI层告诉逻辑层我需要做的事,逻辑层去找相应的人(模型层)去做,最后只告诉UI这件事做的结果。
模型层没什么好说的,这部分一般由大量的Package组成,代码量是三层中最大的,需要在内部进行分层。
横向的分割依据AOP面向切面的思想,主要是提取出共用方法作为一个单独的Util,这些Util会在App整体中穿插使用。现在我的App都会引入我自己封装的Jar包,封装了包括文件、JSON、SharedPreference等在内的常用操作,自己写的用起来顺手,也大幅度降低了重复作业。
这样纵,横两次对于App代码的分割已经能使得程序不会过多堆积在一个Java文件里,但靠一次开发过程就写出高质量的代码是很困难的,趁着项目的间歇期,对代码进行重构很有必要。
如:对application/baseactivity,图片加载,数据库等进行分析
代码和文档规范,根据需求进行模块划分,确定交互方式,形成接口文档,这些较为通用的内容不再细说。做Android App时,我一般将App进行纵向和横向的划分。纵向的App由UI层,逻辑层和模型层构成,整体结构基于MVP思想(图片来自网络)。
<img src="https://i-blog.csdnimg.cn/blog_migrate/b19830e87c0ec07a9049d83c545b6e1a.jpeg" data-rawwidth="640" data-rawheight="433" class="origin_image zh-lightbox-thumb" width="640" data-original="https://pic4.zhimg.com/9fe1e5679a642f9f82373d2a32d461b7_r.jpg">UI层内部多用模板方法,以Activity为例一般有BaseActivity,提供包括一些基础样式,Dialog,ActionBar在内的内容,展现的Activity都会继承BaseActivity并实现预留的接口,Activity之间的继承不超过3次;为避免Activity内代码过多,将App的整体控制权后移,也借鉴了IOC做法,大量的逻辑操作放在逻辑层中,逻辑层和UI层通过接口或者Broadcast等实现通信,只传递结果。一般Activity里的代码量都很大,通过这两种方式一般我写的单个Activity内代码量不超过400行。 UI层内部多用模板方法,以Activity为例一般有BaseActivity,提供包括一些基础样式,Dialog,ActionBar在内的内容,展现的Activity都会继承BaseActivity并实现预留的接口,Activity之间的继承不超过3次;为避免Activity内代码过多,将App的整体控制权后移,也借鉴了IOC做法,大量的逻辑操作放在逻辑层中,逻辑层和UI层通过接口或者Broadcast等实现通信,只传递结果。一般Activity里的代码量都很大,通过这两种方式一般我写的单个Activity内代码量不超过400行。
逻辑层实现的是绝大部分的逻辑操作,由UI层启动,在内部通过接口调用模型层的方法,在逻辑层内大量使用了代理。打个比方,UI层告诉逻辑层我需要做的事,逻辑层去找相应的人(模型层)去做,最后只告诉UI这件事做的结果。
模型层没什么好说的,这部分一般由大量的Package组成,代码量是三层中最大的,需要在内部进行分层。
横向的分割依据AOP面向切面的思想,主要是提取出共用方法作为一个单独的Util,这些Util会在App整体中穿插使用。现在我的App都会引入我自己封装的Jar包,封装了包括文件、JSON、SharedPreference等在内的常用操作,自己写的用起来顺手,也大幅度降低了重复作业。
这样纵,横两次对于App代码的分割已经能使得程序不会过多堆积在一个Java文件里,但靠一次开发过程就写出高质量的代码是很困难的,趁着项目的间歇期,对代码进行重构很有必要。
如:对application/baseactivity,图片加载,数据库等进行分析
每个人对应用框架的理解不相同,但是最终达到的效果应该是一样:
那么有没有一些通用的东西可以抽取呢?从自己的一些实践经验来回答题主的一些问题,权当抛砖引玉。
<img src="https://i-blog.csdnimg.cn/blog_migrate/e0f8457b4362a7f3e2b12f169e8a6faf.png" data-rawwidth="399" data-rawheight="415" class="content_image" width="399">这些包名的作用一目了然,在别人接手这个项目的时候就会相对简单。 这些包名的作用一目了然,在别人接手这个项目的时候就会相对简单。
<img src="https://i-blog.csdnimg.cn/blog_migrate/6fff856348612bc7c3ed9d52a7a1b4a3.png" data-rawwidth="281" data-rawheight="47" class="content_image" width="281">
2.AppContext 的处理
Application本身在一个应用中只会存在一个实例,所以它一般用来存储一些全局的变量和一些只需要处理一次的数据。
3.Base的处理
对BaseActivity的处理好坏一定程度上会影响项目的代码可读性,在Base里面做一些规范化处理将会大大减少代码的书写量和提高可读性。
通过这种规范可以大大减少后期代码的混乱,onCreat方法中存在大量杂乱无章的代码;
个人建议在处理数据库的时候采用ContentProvider的方式,有2个优点:
对图片处理的文章很多,其实你只要把基本的一些开源框架原理搞清楚,对普通应用其实足够了。
--------------------------------------------------------------------------------------------------------
- 降低项目的复杂性
- 易扩展、易修改、可重用性强、可维护性强
- 职责单一,功能清晰
那么有没有一些通用的东西可以抽取呢?从自己的一些实践经验来回答题主的一些问题,权当抛砖引玉。
- 项目工程搭建
<img src="https://i-blog.csdnimg.cn/blog_migrate/e0f8457b4362a7f3e2b12f169e8a6faf.png" data-rawwidth="399" data-rawheight="415" class="content_image" width="399">这些包名的作用一目了然,在别人接手这个项目的时候就会相对简单。 这些包名的作用一目了然,在别人接手这个项目的时候就会相对简单。
- adapter 适配器,如果业务复杂,根据不同的业务可以添加子包来进行分类;
- base 用来存放View的基类,例如BaseAcitivity、BaseFragment,甚至可以添加某些不同actionbar主题的Base类;
- common 当然是存放一些共用的配置类信息,常量等等;
- controller 控制器,将一部分的业务类需求放到里面,充当db和View交互的中间层,减少Activity中业务的复杂性;
- db数据库类
- event 观察者模式,事件通知;
- task一些AsyncTask任务类
- view一些自定义组件
- vo 值对象,其实就是给各个组件使用的对象,比如ListView的Item对象等等
- widget UI界面
- AppContext 自定义Application类
<img src="https://i-blog.csdnimg.cn/blog_migrate/6fff856348612bc7c3ed9d52a7a1b4a3.png" data-rawwidth="281" data-rawheight="47" class="content_image" width="281">
2.AppContext 的处理
Application本身在一个应用中只会存在一个实例,所以它一般用来存储一些全局的变量和一些只需要处理一次的数据。
- context的管理。这个和BaseActivity组合使用,将每一个Activity放到一个列表中,需要的时候直接使用即可;
- 初始化和记录一些app信息,例如app的版本信息、设备信息等等;
- 初始化特定的业务需求,例如有盟统计类、分享SDK、推送等等
- 记录应用启动次数、是否第一次安装等等,如果在第一个版本不加,到后面版本使用次记录会很麻烦(血泪教训……)
- 记录是否开启处于调试模式。
public final static boolean DEBUG=BuildConfig.DEBUG;
对BaseActivity的处理好坏一定程度上会影响项目的代码可读性,在Base里面做一些规范化处理将会大大减少代码的书写量和提高可读性。
- 将其Base类定义成抽象类,增加一些抽象方法,例如findView的处理、onClick的处理、初始化数据的处理。例如可以重载setContentView方法来规范子类的行为:
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
findView();
initView();
setOnClick();
}
/**
* 获取布局控件
*/
protected abstract void findView();
/**
* 初始化View的一些数据
*/
protected abstract void initView();
/**
* 设置点击监听
*/
protected abstract void setOnClick();
- 添加观察者模式的支持。具体的可以看我的博客观察者模式在android 上的最佳实践
- 定义一些ActionBar上面的保护类方法,比如返回按钮、下拉事件等等;
个人建议在处理数据库的时候采用ContentProvider的方式,有2个优点:
- 采用URI的方式访问,更加符合我们的使用习惯;
- 随时可以提供给其它应用访问数据库;
对图片处理的文章很多,其实你只要把基本的一些开源框架原理搞清楚,对普通应用其实足够了。
继承Application类(存放全局数据,
注意同步
,一些SDK也要求在这初始化)
+创建BaseActivity(做好页面的缓存策略, 别对Bundle savedInstanceState视而不见 )
+Volley(网络通信)
+Fresco(图片加载)
+ORMLite(ORM,不多说)
+EventBus(为了解耦)
1、在 搭自己的框架之前 ,你需要 熟练应用别人的框架 。用多了别人的框架,自己再写的时候,就可以想怎么做可能像别人的那样易用。
2、设计模式的熟练应用,为了 自己好写(易拓展),别人好用(易定制) 。
一个典型的单例模式,我们看一下Volley的源码,它的里面确实不像一般的单利模式写法:
注意到一个queue.start();//请求队列的start
跟进去:
一个stop(),是不是算一个单例啊?
不用猜了,下面的那些调用start()方法的实例全是线程实例。
比如,我要做一个音视频处理工具,原来只有音频处理能力:
我现在也做了视频处理部分,那就只需要加一个新的工厂方法就可以了,其他API不需要变动。
但我们对于一些高阶的用户需要一些有逼格的功能,他们在做产品中需要更多的个性化,这时候 就应该拿出建造者模式了,接着上面的例子:
是不是人民群众喜闻乐见的库的调用方式!
再次拿Volley开刀!
对于Volley这样的网络请求框架来说,必要的重连机制是必不可少的,你看:
当然,再次照顾小白(主要水作业的学生党),Volley也提供了
默认的重连策略。
容错的具体处理委托给这些策略类。
目前就想到这么多,其他的再补。
+创建BaseActivity(做好页面的缓存策略, 别对Bundle savedInstanceState视而不见 )
+Volley(网络通信)
+Fresco(图片加载)
+ORMLite(ORM,不多说)
+EventBus(为了解耦)
1、在 搭自己的框架之前 ,你需要 熟练应用别人的框架 。用多了别人的框架,自己再写的时候,就可以想怎么做可能像别人的那样易用。
2、设计模式的熟练应用,为了 自己好写(易拓展),别人好用(易定制) 。
- 单例模式进行初始化,防止资源泄露。
mRequestQueue = Volley.newRequestQueue(this);
注意到一个queue.start();//请求队列的start
跟进去:
一个stop(),是不是算一个单例啊?
不用猜了,下面的那些调用start()方法的实例全是线程实例。
- 抽象工厂模式进行最外层的包装,主要照顾老用户。
比如,我要做一个音视频处理工具,原来只有音频处理能力:
AudioVideoProcessor audioProcessor = AudioVideoProcessorFactory.CreateAudioProcessor();//抽象工厂创建
audioProcessor.openFile(...);//打开文件
audioProcessor.encode(EncodeEnginer encoderEnginer);//调用编码器
audioProcessor.sendRtpStream(...);//发送Rtp流
- 建造者模式满足小白与高阶用户。
但我们对于一些高阶的用户需要一些有逼格的功能,他们在做产品中需要更多的个性化,这时候 就应该拿出建造者模式了,接着上面的例子:
AudioVideoProcessorBuilder audioVideoProcessorBuilder = new AudioVideoProcessorBuilder()//建造者模型精细的把握各项参数
.setResize(ResizeStyleOptions.W_H_16_9)//长宽比
.setMaxBitrate(BitRateOptions.64_K)//码流率
.setP2PMode(P2PModeOptions.NAT);//p2p穿透方式
AudioVideoProcessor videoProcessor = audioVideoProcessorBuilder.getVideoProcessor();
- 策略模式进行容错处理。
再次拿Volley开刀!
对于Volley这样的网络请求框架来说,必要的重连机制是必不可少的,你看:
当然,再次照顾小白(主要水作业的学生党),Volley也提供了
默认的重连策略。
容错的具体处理委托给这些策略类。
目前就想到这么多,其他的再补。
1. 首先是项目框架,特指代码的组织方式,一个清晰优雅的框架简直让人神清气爽,这方面知乎上已经有很多文章,不再赘述。
在Android开发过程中搭建一个自己的应用框架有几个步骤?需要注意什么? - Android 开发
2. 其次是开源框架,这里指的是Android开发中经常用到的第三方开源框架的组合,有很多选择,我个人推荐:
3. 最后是各种免费好用的第三方开发者服务,我主要做海外市场,只推荐我用过的觉得好的:
2. 其次是开源框架,这里指的是Android开发中经常用到的第三方开源框架的组合,有很多选择,我个人推荐:
- UI: 各种开源控件,可以在这里找 Trinea/android-open-project · GitHub
- 依赖注入:Dagger + ButterKnife
- 图片加载:Picasso
- 网络请求: Retrofit + OkHttp+Gson
- 数据库访问: Content Provider + Schematic, 或某款orm
- 消息事件队列:otto
3. 最后是各种免费好用的第三方开发者服务,我主要做海外市场,只推荐我用过的觉得好的:
- Flurry: 国外统计分析系统的标杆, 类似国内的友盟。
- Google各种开发者服务:首推Google Analytics,官方版的友盟, 也是业界标配了。
- Facebook各种开发者服务:Parse Push, Applink, 各种良心工具与服务。
- Twitter各种开发者服务:大名顶顶的Crashlytic也被它集成了, Fabric下的各种服务等你去发现。
- Appsflyer:做海外推广的话,这个是为数不多的选择之一。
- Disqus: 国外评论服务垄断者,对比之下国内的畅言,友言什么的我就不说了。
- 广告平台: Google与Facebook的广告服务,目前native广告最火,效果也是最佳。
- 支付:一般的应用内支付就够了,类似电商之类可能需要第三方海外支付,推荐payssion.
- 推送: 上面提到的Parse Push, 有使用限制,超过要付费,不过一般中小应用也差不多够了。
- 客服: helpshift,国外最专业的客服平台了。
- 短信验证: Fabric digits, twitter出品的,不要钱。
- 灰度测试: optimizely, 支持Android, iOS,用过就知道,直接在线改UI,不是一般的强大。
- 云测: testin,用了很久,挺赞的。
- 最后的彩蛋: appsee, 这个很强大, PM最爱,再也不担心转化率上不去了,可惜要收费。
1. Android best practice:
futurice/android-best-practices · GitHub
中文版: android-best-practices/README.cn.md at master · futurice/android-best-practices · GitHub
2. 对GitHub上的各大开源库的收录和分析: Trinea/android-open-project · GitHub
3. 另外再推荐一个人: JakeWharton (Jake Wharton) · GitHub (Jake Wharton:此人在Square,而Square也位列我之前所说的湾区四小龙之中)。
中文版: android-best-practices/README.cn.md at master · futurice/android-best-practices · GitHub
2. 对GitHub上的各大开源库的收录和分析: Trinea/android-open-project · GitHub
3. 另外再推荐一个人: JakeWharton (Jake Wharton) · GitHub (Jake Wharton:此人在Square,而Square也位列我之前所说的湾区四小龙之中)。
有时遥想当年,在Facebook做Android和iOS开发,由于毕竟是大公司,里面的自有工具,内部库还有技术大牛都很丰富,所以基本上除了使用少数几个经典开源库之外,其他大部分都是自己写,比如 Buck,FBNetworking,FBCache,FBImageLoader等等。这对于创业公司来说是完全不试用。一来没人手,二来很容易碰到一个技术难点就把整个公司给陷进去了。现在想想,当年在大公司真是身在福中不知福啊。。。
国内:Talking Data, 可惜友盟现在启动就带上阿里全家桶。
国外: Flurry, 国外统计分析系统的标杆,免费的。
Crash分析
国内: 腾讯Bugly, 号称全球唯一自带ANR收集,其实原理很简单,不知别家为何不做。
国外: Crashlytics, 已经收归Twitter Fabric开发者工具集,免费好用。
推送
国内: LeanCloud,这个没实际用过,身边朋友反馈很好。
国外: Parse, 正如 覃超 所说,FB也在用,30qps免费限制,一般中小应用够用。
分享
国内: ShareSDK,专业做社交分享。
国外: 各社交平台自家SDK, 注意不同国家主流社交平台不同。
评论
国内:畅言, 基本抄的Disqus, 免费,算是良心产品了。
国外:Disqus, 基本不用考虑其他家的,虽然确实有竞品。
广告变现
国内:百度 or 广点通,两个效果差不多。
国外:FB or Google,做native广告,效果最佳。
支付
国内: 支付宝, 微信
国外: payssion, 专业做海外跨境收款的,能省很多事。
短信验证
国内:没用过,Google找一家最便宜的就行。
国外:Fabric Digits, twitter出品,居然不要钱。
灰度测试
国内:AppAdhoc,移动AB测试国内最专业的一家。
国外:optimizely, 支持Android, iOS, 直接在线改UI做AB测试, 三观都要颠覆了。
云测
国内:百度云测试。
国外:test in, 其实百度的也跑,国内的Android设备都卖到国外去了。
客服
国内:微客服, 有免费额度,中小应用够用。
国外:helpshift,国外最专业的客服平台。
推广
国内:这个真不了解。
国外:Appsflyer, 海外推广为数不多的选择之一。
可视化分析
国内:growingio, 还在内测中,linkedin数据分析大牛回国创业,据说黑科技,可以直接在app上实时查看各种转化率数据。
国外:appsee, 绝对黑科技,PM最爱,转化率什么的再也不怕上不去了,用过后我们团队成员一致好评,在我的微信公众号里有专门文章介绍使用体验。
----2015.11.27更新----
网络优化
国外:TwinPrime, 颇具特色的网络优化服务,目前正在尝试中,可移步我另外一篇回答查看
Android开发如何进行网络优化? - 汤涛的回答
国内:暂时还没发现同类产品,不过TwinPrime理论上是支持全球的。
最后,给大家介绍传说中的Android军火库,我很多东西都是在这里面找的。
国内: DevStore_移动互联网企业运营解决方案整合平台
国外: http://www.android-arsenal.com
----2015.11.28更新----
安利一下我的另外一篇回答,用心写的都木有人看,好桑心呀。
面试时,问哪些问题能试出一个 Android 应用开发者真正的水平? - 汤涛的回答
最近刚开始运营一个微信公众号AndroidTrending,里面主要是Android开发最佳实践,最好用的工具与服务的总结,如果大家感兴趣,可以关注一下。做技术有捷径,少走弯路即是。
-------
转载地址:http://www.zhihu.com/question/35009721
https://www.zhihu.com/question/37433825/answer/73556099
http://www.zhihu.com/question/27140400