工具类
- note.js 安装版本切换工具
- 缓动函数速查表
资源类
- 它不仅提供免费的高清视频素材,还有插画,音乐,PR 模版等,相当全面
- 8000个已分类好的扁平化图标(PNG/SVG/WEBFONT)
公司对每个ip限速300k,平时下载文件甚至打开网页都很慢,之前斐讯0元购撸了个k2路由器,刷了openwrt,配了多拨,但是后来重新刷路由器固件后多拨配置丢了,年久未搞,配了很久都单线多拨失败。今日经过百度多篇文章,最终根据文章的图文操作,弄清楚多拨会用到哪些配置文件,特此记录下来,往后搞单线多拨只需按照笔记无脑敲命令就行了,甚至连luci都不需要。
首先更新openwrt的软件源
opkg update
然后按照必要的文件
opkg install luci kmod-macvlan luci-app-mwan3
在/etc/rc.local中exit上一行加入一下配置
sleep 6
ip link add link eth0.2 name vth1 type macvlan
ifconfig vth1 up
ip link add link eth0.2 name vth2 type macvlan
ifconfig vth2 up
ip link add link eth0.2 name vth3 type macvlan
ifconfig vth3 up
ip link add link eth0.2 name vth4 type macvlan
ifconfig vth4 up
ip link add link eth0.2 name vth5 type macvlan
ifconfig vth5 up
ip link add link eth0.2 name vth6 type macvlan
ifconfig vth6 up
在/etc/config/network中,把原有的config interface各项去掉, 修改成一下版本:
//这个wan修改一下
config interface ‘wan’
option proto ‘dhcp’
option ifname ‘eth0.2’
option metric ‘20’
config interface ‘vwan1’
option proto ‘dhcp’
option ifname ‘vth1’
option metric ‘21’
config interface ‘vwan2’
option proto ‘dhcp’
option ifname ‘vth2’
option metric ‘22’
config interface ‘vwan3’
option proto ‘dhcp’
option ifname ‘vth3’
option metric ‘23’
config interface ‘vwan4’
option proto ‘dhcp’
option ifname ‘vth4’
option metric ‘24’
config interface ‘vwan5’
option proto ‘dhcp’
option ifname ‘vth5’
option metric ‘25’
config interface ‘vwan6’
option proto ‘dhcp’
option ifname ‘vth6’
option metric ‘26’
在 /etc/config/firewall 中
config zone
option name ‘wan’
option input ‘REJECT’
option output ‘ACCEPT’
option forward ‘REJECT’
option masq ‘1’
option mtu_fix ‘1’
option network ‘wan wan6 vwan1 vwan2 vwan3 vwan4 vwan5 vwan6’
在 /etc/config/mwan3 中
config interface ‘vwan1’
option enabled ‘1’
option initial_state ‘online’
option family ‘ipv4’
option track_method ‘ping’
option reliability ‘1’
option count ‘1’
option size ‘56’
option max_ttl ‘60’
option check_quality ‘0’
option timeout ‘2’
option interval ‘5’
option failure_interval ‘5’
option recovery_interval ‘5’
option down ‘3’
option up ‘3’
list track_ip ‘8.8.8.8’
config interface ‘vwan2’
option enabled ‘1’
option initial_state ‘online’
option family ‘ipv4’
option track_method ‘ping’
option reliability ‘1’
option count ‘1’
option size ‘56’
option max_ttl ‘60’
option check_quality ‘0’
option timeout ‘2’
option interval ‘5’
option failure_interval ‘5’
option recovery_interval ‘5’
option down ‘3’
option up ‘3’
list track_ip ‘8.8.8.8’
config interface ‘vwan3’
option enabled ‘1’
option initial_state ‘online’
option family ‘ipv4’
option track_method ‘ping’
option reliability ‘1’
option count ‘1’
option size ‘56’
option max_ttl ‘60’
option check_quality ‘0’
option timeout ‘2’
option interval ‘5’
option failure_interval ‘5’
option recovery_interval ‘5’
option down ‘3’
option up ‘3’
list track_ip ‘8.8.8.8’
config interface ‘vwan4’
option enabled ‘1’
option initial_state ‘online’
option family ‘ipv4’
option track_method ‘ping’
option reliability ‘1’
option count ‘1’
option size ‘56’
option max_ttl ‘60’
option check_quality ‘0’
option timeout ‘2’
option interval ‘5’
option failure_interval ‘5’
option recovery_interval ‘5’
option down ‘3’
option up ‘3’
list track_ip ‘8.8.8.8’
config interface ‘vwan5’
option enabled ‘1’
option initial_state ‘online’
option family ‘ipv4’
option track_method ‘ping’
option reliability ‘1’
option count ‘1’
option size ‘56’
option max_ttl ‘60’
option check_quality ‘0’
option timeout ‘2’
option interval ‘5’
option failure_interval ‘5’
option recovery_interval ‘5’
option down ‘3’
option up ‘3’
list track_ip ‘8.8.8.8’
config interface ‘vwan6’
option enabled ‘1’
option initial_state ‘online’
option family ‘ipv4’
option track_method ‘ping’
option reliability ‘1’
option count ‘1’
option size ‘56’
option max_ttl ‘60’
option check_quality ‘0’
option timeout ‘2’
option interval ‘5’
option failure_interval ‘5’
option recovery_interval ‘5’
option down ‘3’
option up ‘3’
list track_ip ‘8.8.8.8’
config member ‘mwan’
option interface ‘wan’
config member ‘mvwan1’
option interface ‘vwan1’
config member ‘mvwan2’
option interface ‘vwan2’
config member ‘mvwan3’
option interface ‘vwan3’
config member ‘mvwan4’
option interface ‘vwan4’
config member ‘mvwan5’
option interface ‘vwan5’
config member ‘mvwan6’
option interface ‘vwan6’
config policy ‘balanced’
option last_resort ‘default’
list use_member ‘mwan’
list use_member ‘mvwan1’
list use_member ‘mvwan2’
list use_member ‘mvwan3’
list use_member ‘mvwan4’
list use_member ‘mvwan5’
list use_member ‘mvwan6’
最后重启一下路由器
reboot
使用大文件测速专用下载测试一下
100g http://repos.mia.lax-noc.com/speedtests/100gb.bin
10t http://repos.mia.lax-noc.com/speedtests/10tb.bin
Git的优点很多,但是这里只列出我认为非常突出的几点。
感兴趣的,可以去看一下Git本身的设计,内在的架构体现了很多的优势,不愧是出资天才程序员Linus (Linux之父) 之手
虽然有这么优秀的版本管理工具,但是我们面对版本管理的时候,依然有非常大得挑战,我们都知道大家工作在同一个仓库上,那么彼此的代码协作必然带来很多问题和挑战,如下:
大部分开发人员现在使用Git就只是用三个甚至两个分支,一个是Master, 一个是Develop, 还有一个是基于Develop打得各种分支。这个在小项目规模的时候还勉强可以支撑,因为很多人做项目就只有一个Release, 但是人员一多,而且项目周期一长就会出现各种问题。
就像代码需要代码规范一样,代码管理同样需要一个清晰的流程和规范
Vincent Driessen 同学为了解决这个问题提出了 A Successful Git Branching Model
下面是Git Flow的流程图
上面的图你理解不了? 没关系,这不是你的错,我觉得这张图本身有点问题,这张图应该左转90度,大家应该就很用以理解了。
也就是我们经常使用的Master分支,这个分支最近发布到生产环境的代码,最近发布的Release, 这个分支只能从其他分支合并,不能在这个分支直接修改
这个分支是我们是我们的主开发分支,包含所有要发布到下一个Release的代码,这个主要合并与其他分支,比如Feature分支
这个分支主要是用来开发一个新的功能,一旦开发完成,我们合并回Develop分支进入下一个Release
当你需要一个发布一个新Release的时候,我们基于Develop分支创建一个Release分支,完成Release后,我们合并到Master和Develop分支
当我们在Production发现新的Bug时候,我们需要创建一个Hotfix, 完成Hotfix后,我们合并回Master和Develop分支,所以Hotfix的改动会进入下一个Release
所有在Master分支上的Commit应该Tag
分支名 feature/*
Feature分支做完后,必须合并回Develop分支, 合并完分支后一般会删点这个Feature分支,但是我们也可以保留
分支名 release/*
Release分支基于Develop分支创建,打完Release分之后,我们可以在这个Release分支上测试,修改Bug等。同时,其它开发人员可以基于开发新的Feature (记住:一旦打了Release分支之后不要从Develop分支上合并新的改动到Release分支)
发布Release分支时,合并Release到Master和Develop, 同时在Master分支上打个Tag记住Release版本号,然后可以删除Release分支了。
分支名 hotfix/*
hotfix分支基于Master分支创建,开发完后需要合并回Master和Develop分支,同时在Master上打一个tag
a. 创建develop分支
1 | git branch develop |
b. 开始新Feature开发
1 | git checkout -b some-feature develop |
c. 完成Feature
1 | git pull origin develop |
d. 开始Relase
1 | git checkout -b release-0.1.0 develop |
e. 完成Release
1 | git checkout master |
f. 开始Hotfix
1 | git checkout -b hotfix-0.1.1 master |
g. 完成Hotfix
1 | git checkout master |
实际上,当你理解了上面的流程后,你完全不用使用工具,但是实际上我们大部分人很多命令就是记不住呀,流程就是记不住呀,肿么办呢?
总有聪明的人创造好的工具给大家用, 那就是Git flow script.
brew install git-flow
apt-get install git-flow
wget -q -O - –no-check-certificate https://github.com/nvie/gitflow/raw/develop/contrib/gitflow-installer.sh | bash
上面讲了这么多,我知道还有人记不住,那么又有人做出了GUI 工具,你只需要点击下一步就行,工具帮你干这些事!!!
当你用Git-flow初始化后,基本上你只需要点击git flow菜单选择start feature, release或者hotfix, 做完后再次选择git flow菜单,点击Done Action. 我勒个去,我实在想不到还有比这更简单的了。
目前SourceTree支持Mac, Windows, Linux.
这么好的工具请问多少钱呢? 免费!!!!
转载自csdn博客,查看原文
不知不觉已经2019了。成为社会人也已经有三年有余。成长了很多,但是觉得还不够。在时间管理,目标计划方面,还有很大的改进空间。经常在心里立下FLAG,但是没多久FLAG就倒了。因此本篇用于记录我的目标和计划。那些已经实现的、已经失败的、正在计划的……
OBJECT | CREATE TIME | START TIME | END TIME | CURRENT STATUS | LINK |
---|---|---|---|---|---|
OBJECT | CREATE TIME | START TIME | END TIME | CURRENT STATUS | LINK |
---|---|---|---|---|---|
OBJECT | CREATE TIME | START TIME | END TIME | CURRENT STATUS | LINK |
---|---|---|---|---|---|
熟练使用Adobe XD | 2019.03.10 | 2019.3.13 | 开始阅读vue-js 2.0完全入门记录 | ℹ | |
熟练使用 vue | 2019.03.12 | ℹ | |||
熟练使用docker | 2019.03.10 | 2019.03.14 | 学习搭建docker-youphptube | ℹ | |
熟练使用flutter | 2019.03.12 | ℹ |
上午京东买了958的KPW3,结果WIFI一直连不上。于是百度解决办法,也不行。问在线客服,并没有本质上解决问题,而且技术支持一点也不懂技术。下面是对话记录。
我: 怎么看是paperwhite是第几代,连接不上wifi
您现在已连接到亚马逊的 高云涛。
高云涛: 您好,欢迎使用亚马逊在线服务,我是亚马逊kindle客服:高云涛,很高兴为您服务,请问有什么可以帮到您的?
麻烦您提供一下设备的序列号我帮您查询下
在这里查询序列号
在做项目初期,如果知道有哪些框架/工具可用,对项目的开发会有很大的帮助。这篇帖子收集项目开发用过的,或者有类似需求不知道有对应工具,后来发现这些工具有相见恨晚感觉的。作为一个类似于备忘录的帖子,根据个人判断在需要的时候进行增删改查。介绍时候尽量用一两个关键词。收集的文章可能会因各种原因失效,请以标题自行在搜索引擎搜索。帖子目的不是做到大而全且更新频繁。如果读者有这样的需求,良心推荐干货集中营,每日分享 妹子图 和 ** 技术干货**,还有供大家中午休息的休闲视频
最近更新于 2017-03-24 原文才持续更新哦
DiffUtil是一个查找集合变化的工具类,是搭配RecyclerView一起使用的。DiffUtil的作用,就是找出集合中每一个Item发生的变化,然后对每个变化给予对应的刷新。
Android开发学习之路-DiffUtil使用教程
简单,美观,功能强大的安卓打印工具。
GitHub
ButterKnife Zelezny:ButterKnife 生成器
SelectorChapek:selector 自动生成XML
GsonFormat:json字符串生成相应的实体类
介绍文章
JakeWharton大神出品。View,资源,事件注解方式初始化。
官网
2013年Google I/O大会上推出的一个新的网络通信框架,简化Http通信,提供异步回调。
个人更推荐使用retrofit`
Retrofit与okhttp共同出自于Square公司,retrofit就是对okhttp做了一层封装。把网络请求都交给给了Okhttp.配置简单灵活,接口返回对象,支持rxJava无缝对接
GitHub
这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官方app.Glide和Picasso有90%的相似度
推荐用Glide代替。查看对比文章 Picasso VS Glide
greenDao是一个将对象映射到SQLite数据库中的轻量且快速的ORM解决方案,跟EvenBus师出同门。
介绍文章1
介绍文章2
官网
square出品。一个轻量级SQLiteOpenHelper包装类,引入reactive 流式语法,完美解决数据库和UI的同步更新!
GitHub
JakeWharton大神出品。只要一行
@DebugLog
注解打印方法的传参和返回值,甚至方法的执行时间,只在debug版本打印,对release版本无任何影响。
GitHub
JakeWharton大神出品。查看界面层级,3D的效果。方便优化界面布局。
GitHub
square出品。内存泄漏检测工具
GitHub
RxJava Essentials 中文翻译版
给 Android 开发者的 RxJava 详解
深入浅出RxJava(一:基础篇)
RxJava 和 RxAndroid 五(线程调度
近日在搜MVP模式作为安卓项目架构时候,发现GitHub上一篇介绍MVP架构的文章。一看star已经超过2K了。通读全文发现作者用实际项目将MVP架构要怎么分职责讲得十分通俗易懂。为了方便大家查阅,把原文翻译了一下。作者还有一篇文章讲安卓项目和代码风格指南的。欢迎查看相关翻译。
我们的安卓APP架构基于 MVP (Model View Presenter) 模式。
View (UI 层):这是 Activities, Fragments 和其他标准安卓控件所在层。它的职责是呈现从Presenter收到的数据给用户。它也处理用户的交互和输入(点击监听等)以及在需要时触发Presenter中对应的动作。
Presenter: Presenter 订阅由 DataManager
提供的 RxJava Observables。他们负责处理订阅的生命周期,分析/修改DataManager
返回的数据,调用View中的合适方法以便展示数据。
Model (Data 层): 它们的职责是取回,保存,缓存,以及通知数据。它可以与本地数据库以及其他的数据仓库通信,使用restful API或者其他第三方SDK等方式。它分为两部分:一组帮助工具类以及一个 DataManager
。工具类的数量因项目而异,每一个工具类有特定的功能,比如与API通信或在 SharedPreferences
中保存数据. DataManager
把不同工具类的输出使用rx操作符进行组合变换,所以它可以: 1) 提供有意义的数据给 Presenter,2) 把经常一起出现的动作组合在一起。这一层也包含实际的实体类,定义数据结构是怎样的。
从右到左看示意图:
Helpers (Model): 一组类的集合,每个类有特定的职责,他们的功能可以从与API或数据库通信,到实现一些特定的业务逻辑等。每个项目会有不同的工具类,但最常见的几个是:
SharedPreferences
的数据,他可以返回 Observables 或者直接返回简单java对象。Data Manager (Model): 这是MVP架构的关键部分。它持有每一个工具类的引用,使用这些工具类满足来自Presenter的请求。 它的方法广泛的使用 Rx 操作符来组合,转换或过滤来自工具类的输出,以便生成Presenter想要的输出。它返回发射数据模型(data models)的 observables。
Presenters: 订阅由 DataManager
提供的observables,处理这些数据以便调用View中合适的方法。
Activities, Fragments, ViewGroups (View): 实现了一组Presenter可以调用的方法的标准安卓组件。它们也处理用户的交互如点击等,然后调用Presenter中合适的方法来采取相应的行动。这些控件也实现框架相关的任务,如管理安卓生命周期,渲染视图(Views)等。
Event Bus: 它使得View控件得到发生在Model的特定事件通知。通常 DataManager
发出事件,然后这些事件可以被Activities 和 Fragments 订阅。 event bus 仅仅 用于非常特别的动作——这些事件不是仅与一个界面相关的,要通知多方,如:用户已经退出登录。
原文链接
译文链接
近日在搜MVP模式作为安卓项目架构时候,发现GitHub上一篇介绍MVP架构的文章。一看star已经超过2K了。作者同项目的这篇文章讲安卓项目和代码风格指南,也非常有参考价值。为了方便大家查阅,把原文翻译了一下。点击查看作者介绍安卓MVP架构指南的翻译文章。
新项目应该遵循安卓Gradle项目结构,定义在这里 :安卓Gradle插件用户指南。项目ribot Boilerplate 是一个很好的参考。
类名书写方式是 大写的驼峰命名.
继承于安卓组件的类,名称应该以继承的组件命名,比如:SignInActivity
, SignInFragment
, ImageUploaderService
, ChangePasswordDialog
.
资源文件书写方式:小写_下划线。如:ic_launcher.png
drawable类型资源命名:
资源类别 | 前缀 | 例子 |
---|---|---|
Action bar | ab_ |
ab_stacked.9.png |
Button | btn_ |
btn_send_pressed.9.png |
Dialog | dialog_ |
dialog_top.9.png |
Divider | divider_ |
divider_horizontal.9.png |
Icon | ic_ |
ic_star.png |
Menu | menu_ |
menu_submenu_bg.9.png |
Notification | notification_ |
notification_bg.9.png |
Tabs | tab_ |
tab_pressed.9.png |
图标(icons)命名方式 (取自 安卓图标官方指南):
资源类别 | 前缀 | 例子 |
---|---|---|
Icons | ic_ |
ic_star.png |
Launcher icons | ic_launcher |
ic_launcher_calendar.png |
Menu icons and Action Bar icons | ic_menu |
ic_menu_archive.png |
Status bar icons | ic_stat_notify |
ic_stat_notify_msg.png |
Tab icons | ic_tab |
ic_tab_recent.png |
Dialog icons | ic_dialog |
ic_dialog_info.png |
selector 状态命名方式:
状态 | 后缀 | 例子 |
---|---|---|
Normal (正常) | _normal |
btn_order_normal.9.png |
Pressed(按下) | _pressed |
btn_order_pressed.9.png |
Focused (获得焦点) | _focused |
btn_order_focused.9.png |
Disabled (不可用) | _disabled |
btn_order_disabled.9.png |
Selected (选中) | _selected |
btn_order_selected.9.png |
布局文件应该跟对应的安卓组件名称匹配,但是把最顶级的组件名称放在前面。比如,当我们创建一个用于 SignInActivity
的布局,那布局文件名称应该是activity_sign_in.xml
.
组件 | 类名 | 布局文件名 |
---|---|---|
Activity | UserProfileActivity |
activity_user_profile.xml |
Fragment | SignUpFragment |
fragment_sign_up.xml |
Dialog | ChangePasswordDialog |
dialog_change_password.xml |
AdapterView item | — | item_person.xml |
Partial layout | — | partial_stats_bar.xml |
一个稍微不同的地方是当我们创建用于Adapter
渲染的布局,如填充一个 ListView
, 在这种情况下,布局文件命名应该是用 item_
开始。
注意有些地方这些规则没法应用,如,当我们创建一个布局文件,用于渲染另一个布局的一部分,这样的情况下,我们应该使用partial_
前缀。
跟布局文件相似,按钮文件应该跟对应的组件匹配。比如:当我们定义一个菜单,用于 UserActivity
,那么文件名应该是 activity_user.xml
文件名不含有menu
是个良好的习惯做法,因为这些文件已经位于 menu
目录了。
在values文件夹的资源文件应该是复数形式(plural),比如,strings.xml
, styles.xml
, colors.xml
, dimens.xml
, attrs.xml
你万不该这样做:
1 | void setServerPort(String value) { |
虽然你可能觉得你的代码永远不会抛出这个异常或者这异常不重要,不需要处理它,像上面那样忽略异常会在你的代码中留下雷区,将来其他人会踩到。你必须在你的代码中以某种原则的方式处理每个异常。具体的处理视情况而定。._ - (安卓官方代码指南)
指南中关于不要忽略异常的说明在 这里.
你不应该这样做:
1 | try { |
查看不这样做的原因以及要怎么做: 猛戳安卓官方指南之不要捕获一般的异常
我们不使用finalizer。它什么时候被调用是没有保证的,甚至它不被调用。大部分情况下,你可以使用良好的异常处理来满足需要在finalizer中做的工作。如果你确实需要它,定义一个 close()
方法(或类似的)然后在文档中明确的指出什么时候这个方法需要被调用。可以查看 InputStream
做为例子.这种情况下,在finalizer中打印一个简短的log信息是恰当的但不是必须的,因为我们不希望log泛滥 ._ - (猛戳安卓官方指南之不要用finalizer)
反例: import foo.*;
正解: import foo.Bar;
点击 这里 查看更多说明
全局变量应该定义在文件的头部,遵循下面的命名规则。
m
开头s
开头译者注:这个规则取自Android Open Source Project代码贡献规范。在程序员的圈子里对于要不要前缀这个问题已经吵翻天了。我在使用greendao的时候使用前缀的话,自动生成的getter/setter会是getMxxx/setMxxx这样难看的方法。很多人也觉得这个命名规则没有意义。stackOverFlow 还有 这里 ,以及一本教你怎么写出整洁代码的书中如是说:
“我觉得如今这些前缀没有意义,尤其是在你的APP中!你的类和方法应该尽量的小,而且你应该使用代码高亮的编辑环境,使得成员变量易于分辨。再者,人们快速适应忽略了前缀或后缀来看名字的有意义部分。我们阅读代码越多,看到前后缀越少。渐渐地,前缀就变成了旧代码看不到的线索和标记。——代码整洁之道(Clean.Code).Robert.C.Martin”
例子:
1 | public class MyClass { |
好的例子 | 不好的例子 |
---|---|
XmlHttpRequest |
XMLHTTPRequest |
getCustomerId |
getCustomerID |
String url |
String URL |
long id |
long ID |
使用四个空格做代码块缩进:
1 | if (x == 1) { |
换行时使用8个空格缩进:
1 | Instrument i = |
大括号的开始跟代码同一行
1 | class MyClass { |
条件语句使用大括号包住,除非条件体只有一行。
如果条件及只有一行条件体,而且没被换行,大括号是不必的。
1 | if (condition) body(); |
这是不好的:
1 | if (condition) |
根据安卓代码风格指南,一些Java内置的注解标准的实践规范有:
@Override
: 无论一个方法是重载父类还是实现某个接口的都必须使用@Override 注解。比如,当你使用 @inheritdocs Javadoc 标签,然后 从一个类(不是一个接口)中导出,你也必须声明那个方法 @Overrides 父类的方法。
@SuppressWarnings
: @SuppressWarnings 注解应该仅当不可能消除一个警告的时候才使用。如果一个警告 通过这个 “不可能消除” 的测试, @SuppressWarnings 注解必不可少, 以便保证所有的警告在代码中反映实际的问题。
关于注解的更多指南可以查看这里.
类,方法及构造器
当注解被应用到一个类,方法或者构造函数时候,注解在代码注释之后,一行一个注解
1 | /* 这是这个类的注解 */ |
全局变量
全局变量的注解应该在同一行列出。除非这一行超过了最大字数了。
1 | @Nullable @Mock DataManager mDataManager; |
变量的使用范围应该限制到最小(Effective Java 条目 29)。这样做,你可以为你的代码增加可读性和可维护性,减少可能的错误。每个变量应该在最内层的使用到的它代码块中定义
局部变量应该在第一次用到他们的时候定义。几乎每个局部变量都应该初始化。如果你没有足够的信息去初始化一个变量,你应该延迟声明这个变量,直到你有足够的初始化信息。._ - (安卓代码风格指南)
如果你使用IDE,如Android Studio,你不必担心这些规则,这些IDE已经遵循这些规则。如果你不用IDE,往下看这些规则:
为了保持跟IDE的设置一致,这些imports应该是这样的:
更多信息查看这里
使用 Log
类提供的日志方法来打印错误信息或对开发者分辨问题有用的其他信息:
Log.v(String tag, String msg)
(verbose)Log.d(String tag, String msg)
(debug)Log.i(String tag, String msg)
(information)Log.w(String tag, String msg)
(warning)Log.e(String tag, String msg)
(error)通常来说,我们使用一个类的名称作为一个TAG,在文件的开头定义成一个 static final
变量,如:
1 | public class MyClass { |
VERBOSE 和 DEBUG 日志 必须在release版本中禁用。同时也建议禁用INFORMATION, WARNING 和 ERROR 日志,但是你可能觉得它们在release版本中定位问题很有用而保持启用。如果你决定让他们保持启用,你要保证这些日志信息不会泄漏email地址,用户id之类的隐私信息。
仅限debug版本显示Log的配置:
1 | if (BuildConfig.DEBUG) Log.d(TAG, "The value of x is " + x); |
这虽然没有简单正确的方案,但是使用一个 逻辑的 及 ** 一致的 ** 顺序可以提高代码的可读性和可学习性。下面是推荐的顺序:
例子:
1 | public class MainActivity extends Activity { |
如果你的类继承一个安卓组件如Activity或Fragment,对重载的方法进行排序以便跟组件的生命周期匹配是一个最佳实践。比如,当你的Activity实现onCreate()
, onDestroy()
, onPause()
和 onResume()
,正确的顺序是:
1 | public class MainActivity extends Activity { |
在安卓编码时候,定义一个方法拥有一个Context
参数是非常常见的,如果你写一个这样的方法,Context应该是第一个参数。
相反的例子是回调接口,它应该是最后一个参数
例子:
1 | // Context 总是在第一个位 |
很多安卓SDK的元素如SharedPreferences
, Bundle
, 或 Intent
使用键值对实现,所以即使是一个小应用,使用一堆字符串常量也是很常见的。
当使用这些组件,你必须定义这些键是 static final
变量,并且它们应该像下面这样使用前缀
元素 | 变量名前缀 |
---|---|
SharedPreferences | PREF_ |
Bundle | BUNDLE_ |
Fragment Arguments | ARGUMENT_ |
Intent Extra | EXTRA_ |
Intent Action | ACTION_ |
注意Fragment的参数——Fragment.getArguments()
也是一个Bundle。然而,因为这是Bundle非常常见的用法,我们为它定义一个不同的前缀。
例子:
1 | //注意这些变量的值应该和名称一致来避免问题 |
当数据通过Intent
或Bundle
传递到一个Activity
或 Fragment
,这些不同值的键必须 遵循上面描述的规则。
当一个 Activity
或 Fragment
想要参数,它应该提供一个public static
方法来简化对应的Intent
或 Fragment
创建
在Activity中这个方法通常叫 getStartIntent()
:
1 | public static Intent getStartIntent(Context context, User user) { |
对于Fragment它的名称是newInstance()
,处理使用合适的参数创建Fragment。
1 | public static UserFragment newInstance(User user) { |
注意1: 这些方法应该在类的 onCreate()
前面
注意2: 如果我们提供上面说的方法,这些extras对应的键和参数应该是private
的,因为他们不需要暴露到类以外。
代码行不应该超过100 个字符。如果代码行超过这个限制长度,通常有两种方式来降低长度:
有两种例外可以让一行超过100字符:
package
和 import
语句.没有精确的公式解释怎么换行,很多不同的方案是有效的。然而,这里有几个规则可以应用到常见情况。
在操作符前断开
当一行被操作符断开,断开处应该在操作符之前,例子如下:
1 | int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne |
赋值符号(=)例外
在操作符前断开有一个例外,那就是赋值符号 =
,应该在赋值符号后面断开。
1 | int longName = |
方法链的情况
当多个方法被链接在同一行的时候——如使用Builder时,每一个方法的调用应该在独立一行,在 .
之前断开。
1 | Picasso.with(context).load("http://ribot.co.uk/images/sexyjoe.jpg").into(imageView); |
1 | Picasso.with(context) |
长参数的情况
当一个方法有很多参数或它的参数非常长,我们应该在每个逗号 ,
后面断开
1 | loadPicture(context, "http://ribot.co.uk/images/sexyjoe.jpg", mImageViewProfilePicture, clickListener, "Title of the picture"); |
1 | loadPicture(context, |
Rx链式操作符要求换行。每一个操作符必须在新的一行,断行应该在.
之前
1 | public Observable<Location> syncLocations() { |
当一个XML元素没有任何内容时,你必须使用自关闭标签。
这是好例子:
1 | <TextView |
这是不好的例子 :
1 | <!-- 不要这样做! --> |
资源 ID 和名称使用小写加下划线方式 lowercase_underscore.
ID应该使用小写加下划线命名,加上元素名称为前缀,如:
元素 | 前缀 |
---|---|
TextView |
text_ |
ImageView |
image_ |
Button |
button_ |
Menu |
menu_ |
Image view 例子:
1 | <ImageView |
Menu 例子:
1 | <menu> |
字符串名称以它们所属的部分为前缀命名,比如registration_email_hint
或 registration_name_hint
。如果一个字符串不属于任何部分,那么你应该遵循下面的规则:
前缀 | 描述 |
---|---|
error_ |
An error message |
msg_ |
A regular information message |
title_ |
A title, i.e. a dialog title |
action_ |
An action such as “Save” or “Create” |
不像其他的资源,style命名方式是大写的驼峰是命名UpperCamelCase
作为通用的规则,你应该把相似的属性放在一起分组,一个对常见属性良好的排序方式是
测试类应该跟需要测试的类名字对应,以Test
做后缀。比如我们创建一个测试类包含对DatabaseHelper
的测试,我们应该把它命名为 DatabaseHelperTest
。
测试方法用@Test
注解,通常以要测试的方法名为命名开始,以测试的前置条件及/或期望结果做后缀。
@Test void methodNamePreconditionExpectedBehaviour()
@Test void signInWithEmptyEmailFails()
如果没有它们测试也能够清楚的表达,前置条件和/或期望结果不总是必须的。
有时候一个类可能包含一大堆方法,同时每个方法要求多个测试,在这种情况,推荐把测试类分割成几个。比如,如果 DataManager
包含一大堆方法,我们可能想把它分到 DataManagerSignInTest
, DataManagerLoadUsersTest
等等。通常你能够知道哪些测试应该在一起,因为它们有共同的test fixtures.
每一个 Espresso 测试类目标通常是一个Activity,所以它的名称应该跟目标Activity的名称匹配,以Test
结束,如 SignInActivityTest
当使用 Espresso API ,把链式方法调用放新行是一个最佳实践。
1 | onView(withId(R.id.view)) |