本文同步发表于个人微信公众号,微信搜索 nanchen 便可关注java
虽然咱们项目的代码时间并不长,也没通过太多人手,但代码的规范性依然堪忧,目前存在较多的比较自由的「代码规范」,这很是不利于项目的维护,代码可读性也不够高,android
此外,客户端和后端的研发模式也彻底不一样,后端研发基本都是基于 SOA 思想的,一般一个子系统 3 我的一块儿维护就已是很充分的人力了,更多时候就是 1 个主力 + 1 个 backup 的人力配置。git
而客户端却彻底不一样,你们的代码都是相互交叉的,一个模块的代码可能要经历数十人的蹂躏,因此造成一个一致的开发规范迫在眉睫。github
核心仍是减小沟通成本,提高咱们的 Code Review 效率,让咱们的代码更加易于维护。此外,一个一致的代码规范能够形成更少的 bug,也就意味着更节省时间和金钱。数据库
固然,规范是约定的,本系列文字全是笔者多年来博采众长,积累而成,因此有任何不一样意见,欢迎评论拍砖。后端
工欲善其事,必先利其器。微信
因为 Android 基本都基于 Android Studio 进行开发,因此工具规范所有以 Android Studio 为前提。markdown
4. 编辑完 .java、.kt、.xml 等文件后必须格式化(须要在设置好如下几点的前提下)app
Reformat Code 的必要性,必定须要保证 IDE 配置一致为前提,尽量贴切于 Android Studio 默认。框架
强烈建议对于比较长的老代码局部格式化,不全局格式化
kotlinx.android.synthetic.main
除外。 以上几处设置完毕,其余采用 Android Studio 默认方式,再进行 Reformat Code 快捷键便可。
前面强调了工具的统一配置,再利用 Android Studio 自己的功能即可把代码风格变得一致。接下来就带来第二部分:Android 的分包规范。
对于分包,咱们须要达成一致,咱们采用 PBF 方式,不推荐使用 PBL 方式。
PBF(按功能分包 Package By Feature) PBL(按层分包 Package By Layer)
PBF 可能不是很好区分在哪一个功能中,不过也比 PBL 要好找不少,且 PBF 与 PBL 相比较有以下优点:
哪块要添新功能,只改某一个 package 下的东西,而PBL 须要改多个 package,很是麻烦。
原则上一个 package 下的不容许其余类访问都是不该该加上 public 的。
统计发现新功能没人用,这个版本那块功能得去掉。若是是 PBL,得从功能入口到整个业务流程把受到牵连的全部能删的代码和 class 都揪出来删掉,一不当心就完蛋。若是是 PBF,好说,先删掉对应包,再删掉功能入口(删掉包后入口确定报错了),完事。
解决问题的通常方法是从抽象到具体,PBF 包名是对功能模块的抽象,包内的 class 是实现细节,符合从抽象到具体,而 PBL 弄反了。PBF 从肯定 AppName 开始,根据功能模块划分 package,再考虑每块的具体实现细节,而 PBL 从一开始就要考虑要不要 dao 层,要不要 com 层等等。
PBL 既分离 class 又分离 package,而 PBF 只经过 class 来分离逻辑代码。
PBL 中包的大小无限增加是合理的,由于功能越添越多,而 PBF 中包太大(包里 class 太多)表示这块须要重构(划分子包)。
代码中的命名严禁使用拼音与英文混合的方式,更不容许直接使用中文的方式。正确的英文拼写和语法可让阅读者易于理解,避免歧义。
注意:即便纯拼音命名方式也要避免采用。但国际通用的名称,可视同英文,好比
toutiao
、douyin
等。
Android 里面有 package 的概念,因此须要约定一下包名命名规范。
包名所有小写,不容许出现中文、大写字母或者下划线,前面为子模块命名,再根据 PBF 方式进行命名。
类名都以 UpperCamelCase
风格编写。
类名一般是名词或名词短语,接口名称有时多是形容词或形容词短语。如今尚未特定的规则或行之有效的约定来命名注解类型。
名词,采用大驼峰命名法,尽可能避免缩写,除非该缩写是众所周知的, 好比 HTML、URL,若是类名称中包含单词缩写,则单词缩写的每一个字母均应大写。
类 | 描述 | 例如 |
---|---|---|
Activity 类 |
模块名 + Activity |
闪屏页类 SplashActivity |
Fragment 类 |
模块名 + Fragment |
主页类 HomeFragment |
Service 类 |
模块名 + Service |
时间服务 TimeService |
BroadcastReceiver 类 |
功能名 + Receiver |
推送接收 JPushReceiver |
ContentProvider 类 |
功能名 + Provider |
ShareProvider |
自定义 View | 功能名 + View/ViewGroup(组件名称) | ShapeButton |
Dialog对话框 | 功能名+Dialog | ImagePickerDialog |
Adapter 类 |
模块名 + Adapter |
课程详情适配器 LessonDetailAdapter |
解析类 | 功能名 + Parser |
首页解析类 HomePosterParser |
工具方法类 | 功能名 + Utils 或 Manager |
线程池管理类:ThreadPoolManager 日志工具类: LogUtils (Logger 也可)打印工具类: PrinterUtils |
数据库类 | 功能名 + DBHelper |
新闻数据库:NewsDBHelper |
自定义的共享基础类 | Base + 基础 |
BaseActivity , BaseFragment |
抽象类 | Base / Abstract 开头 |
AbstractLogin |
异常类 | Exception 结尾 |
LoginException |
接口 | able / ible 结尾 / I 开头 |
Runnable , Accessible ,ILoginView |
测试类的命名以它要测试的类的名称开始,以 Test 结束。例如:HashTest
或 HashIntegrationTest
。
接口(interface):命名规则与类同样采用大驼峰命名法,多以 able 或 ible 结尾,如 interface Runnable
、interface Accessible
。
注意:若是项目采用 MVP,全部 Model、View、Presenter 的接口都以 I 为前缀,不加后缀,其余的接口采用上述命名规则。
方法名都以 lowerCamelCase
风格编写。
方法名一般是动词或动词短语。
方法 | 说明 |
---|---|
initXX() |
初始化相关方法,使用 init 为前缀标识,如初始化布局 initView() |
isXX() , checkXX() |
方法返回值为 boolean 型的请使用 is/check 为前缀标识 |
getXX() |
返回某个值的方法,使用 get 为前缀标识 |
setXX() |
设置某个属性值 |
handleXX() , processXX() |
对数据进行处理的方法 |
displayXX() , showXX() |
弹出提示框和提示信息,使用 display/show 为前缀标识 |
updateXX() |
更新数据 |
saveXX() , insertXX() |
保存或插入数据 |
resetXX() |
重置数据 |
clearXX() |
清除数据 |
removeXX() , deleteXX() |
移除数据或者视图等,如 removeView() |
drawXX() |
绘制数据或效果相关的,使用 draw 前缀标识 |
这里的变量为广义的变量,包括了常量、局部变量、全局变量等,它们的基础规则是:
lowerCamelCase
风格;在具体的变量命名时,会根据该变量的类型不一样而附加额外的命名规则:
类型 | 说明 | 例如 |
---|---|---|
常量 | 大写 & 下划线隔开,Kotlin 必定要 const val | const val TYPE_NORMAL = 1 static final TYPE_NORMAL = 1 |
临时变量名 | 整型:i 、j 、k 、m 、n ,字符型通常用 c 、d 、e |
for(int i = 0;i < len; i++) |
其余变量 | lowerCamelCase 风格便可,私有变量也不要使用 m 开头 |
private int tmp; |
Kotlin | 只读变量使用 val ,可变变量使用 var ,尽量使用 val |
var tmp = 0 val defaultIndex = 0 |
Android 的资源包括:
资源文件命名为所有小写,采用下划线命名法。
安卓主要包含属性动画和视图动画,其视图动画包括补间动画和逐帧动画。属性动画文件须要放在 res/animator/
目录下,视图动画文件需放在 res/anim/
目录下。命名规则:{模块名_}逻辑名称
。
说明:
{}
中的内容为可选,逻辑名称
可由多个单词加下划线组成。例如:refresh_progress.xml
、market_cart_add.xml
、market_cart_remove.xml
。
若是是普通的补间动画或者属性动画,可采用:动画类型_方向
的命名方式。
例如:
名称 | 说明 |
---|---|
fade_in |
淡入 |
fade_out |
淡出 |
push_down_in |
从下方推入 |
push_down_out |
从下方推出 |
push_left |
推向左方 |
slide_in_from_top |
从头部滑动进入 |
zoom_enter |
变形进入 |
slide_in |
滑动进入 |
shrink_to_middle |
中间缩小 |
color/ 是专门用于存放颜色相关资源的文件夹。命名规则:类型{_模块名}_逻辑名称
。
说明:
{}
中的内容为可选。例如:sel_btn_font.xml
。
颜色资源也能够放于 res/drawable/
目录,引用时则用 @drawable
来引用,但不推荐这么作,最好仍是把二者分开。
res/drawable/
目录下放的是位图文件(.png、.9.png、.jpg、.gif)或编译为可绘制对象资源子类型的 XML 文件,而 res/mipmap/
目录下放的是不一样密度的启动图标,因此 res/mipmap/
只用于存放启动图标,其他图片资源文件都应该放到 res/drawable/
目录下。
命名规则:类型{_模块名}_逻辑名称
、类型{_模块名}_颜色
。
说明:
{}
中的内容为可选;类型
能够是可绘制对象资源类型,也能够是控件类型最后可加后缀_small
表示小图,_big
表示大图。
例如:
名称 | 说明 |
---|---|
btn_main_about.png |
主页关于按键 类型_模块名_逻辑名称 |
btn_back.png |
返回按键 类型_逻辑名称 |
divider_maket_white.png |
商城白色分割线 类型_模块名_颜色 |
ic_edit.png |
编辑图标 类型_逻辑名称 |
bg_main.png |
主页背景 类型_逻辑名称 |
btn_red.png |
红色按键 类型_颜色 |
btn_red_big.png |
红色大按键 类型_颜色 |
ic_avatar_small.png |
小头像图标 类型_逻辑名称 |
bg_input.png |
输入框背景 类型_逻辑名称 |
divider_white.png |
白色分割线 类型_颜色 |
bg_main_head.png |
主页头部背景 类型_模块名_逻辑名称 |
def_search_cell.png |
搜索页面默认单元图片 类型_模块名_逻辑名称 |
ic_more_help.png |
更多帮助图标 类型_逻辑名称 |
divider_list_line.png |
列表分割线 类型_逻辑名称 |
sel_search_ok.xml |
搜索界面确认选择器 类型_模块名_逻辑名称 |
shape_music_ring.xml |
音乐界面环形形状 类型_模块名_逻辑名称 |
若是有多种形态,如按钮选择器:sel_btn_xx.xml
,采用以下命名:
名称 | 说明 |
---|---|
sel_btn_xx |
做用在 btn_xx 上的 selector |
btn_xx_normal |
默认状态效果 |
btn_xx_pressed |
state_pressed 点击效果 |
btn_xx_focused |
state_focused 聚焦效果 |
btn_xx_disabled |
state_enabled 不可用效果 |
btn_xx_checked |
state_checked 选中效果 |
btn_xx_selected |
state_selected 选中效果 |
btn_xx_hovered |
state_hovered 悬停效果 |
btn_xx_checkable |
state_checkable 可选效果 |
btn_xx_activated |
state_activated 激活效果 |
btn_xx_window_focused |
state_window_focused 窗口聚焦效果 |
注意:使用 Android Studio 的插件 SelectorChapek 能够快速生成 selector,前提是命名要规范。
命名规则:类型_模块名
、{模块名_}类型_逻辑名称
。(也采用 PBF,方便查看,尤为在大项目中)
说明:
{}
中的内容为可选。
例如:
类型 | 名称 | 说明 |
---|---|---|
Activity |
main_activity.xml |
主窗体 模块名_类型 |
Fragment |
music_fragment.xml |
音乐片断 模块名_类型 |
Dialog |
loading_dialog.xml |
加载对话框 逻辑名称_类型 |
PopupWindow |
info_ppw.xml |
信息弹窗(PopupWindow) 逻辑名称_类型 |
adapter 的列表项 |
main_song_item.xml |
主页歌曲列表项 模块名_类型_逻辑名称 |
命名规则:{模块名_}_逻辑名_view 缩写(功能)
,例如: main_search_btn
、back_btn
。此外,采用 Kotlinx 直接获取布局文件的时候,id 命名采用驼峰样式。
说明:
{}
中的内容为可选。参考 GoogleSamples Demo:github.com/android/arc…
例如:
类型 | 规范 | 命名示例 |
---|---|---|
TextView |
xxx_text |
user_login_text |
EditText |
xxx_edit |
user_login_edit |
ImageView |
xxx_iv |
user_login_iv |
Button |
xxx_btn |
user_login_btn |
CheckBox |
xxx_cb |
user_login_cb |
GridView |
xxx_gv |
user_login_gv |
ListView |
xxx_lv |
user_login_lv |
RecyclerView |
xxx_rv |
user_login_rv |
RadioButton |
xxx_rb |
user_login_rb |
LinearLayout |
xxx_ll |
user_login_ll |
RelativeLayout |
xxx_rl |
user_login_rl |
FrameLayout |
xxx_fl |
user_login_fl |
GridLayout |
xxx_gl |
user_login_gl |
ConstraintLayout |
xxx_cl |
user_login_cl |
菜单相关的资源文件应放在该目录下。命名规则:{模块名_}逻辑名称
说明:
{}
中的内容为可选。例如:main_drawer.xml
、navigation.xml
。
<color>
的 name
命名使用下划线命名法,在你的 colors.xml
文件中应该只是映射颜色的名称一个 ARGB 值,而没有其它的。不要使用它为不一样的按钮来定义 ARGB 值。
例如,不要像下面这样作:
<resources>
<color name="button_foreground">#FFFFFF</color>
<color name="button_background">#2A91BD</color>
<color name="comment_background_inactive">#5F5F5F</color>
<color name="comment_background_active">#939393</color>
<color name="comment_foreground">#FFFFFF</color>
<color name="comment_foreground_important">#FF9D2F</color>
...
<color name="comment_shadow">#323232</color>
复制代码
使用这种格式,会很是容易重复定义 ARGB 值,并且若是应用要改变基色的话会很是困难。同时,这些定义是跟一些环境关联起来的,如 button
或者 comment
,应该放到一个按钮风格中,而不是在 colors.xml
文件中。
相反,应该这样作:
<resources>
<!-- grayscale -->
<color name="white" >#FFFFFF</color>
<color name="gray_light">#DBDBDB</color>
<color name="gray" >#939393</color>
<color name="gray_dark" >#5F5F5F</color>
<color name="black" >#323232</color>
<!-- basic colors -->
<color name="green">#27D34D</color>
<color name="blue">#2A91BD</color>
<color name="orange">#FF9D2F</color>
<color name="red">#FF432F</color>
</resources>
复制代码
向应用设计者那里要这个调色板,名称不须要跟 "green"
、"blue"
等等相同。"brand_primary"
、"brand_secondary"
、"brand_negative"
这样的名字也是彻底能够接受的。像这样规范的颜色很容易修改或重构,会使应用一共使用了多少种不一样的颜色变得很是清晰。一般一个具备审美价值的 UI 来讲,减小使用颜色的种类是很是重要的。
注意:若是某些颜色和主题有关,那就单独写一个
colors_theme.xml
。
<string>
的 name
命名使用下划线命名法,采用如下规则:{模块名_}逻辑名称
,这样方便同一个界面的全部 string
都放到一块儿,方便查找。
名称 | 说明 |
---|---|
main_menu_about |
主菜单按键文字 |
friend_title |
好友模块标题栏 |
friend_dialog_del |
好友删除提示 |
login_check_email |
登陆验证 |
dialog_title |
弹出框标题 |
button_ok |
确认键 |
loading |
加载文字 |
<style>
的 name
命名使用大驼峰命名法,几乎每一个项目都须要适当的使用 styles.xml
文件,由于对于一个视图来讲,有一个重复的外观是很常见的,将全部的外观细节属性(colors
、padding
、font
)放在 styles.xml
文件中。 在应用中对于大多数文本内容,最起码你应该有一个通用的 styles.xml
文件,例如:
<style name="ContentText">
<item name="android:textSize">@dimen/font_normal</item>
<item name="android:textColor">@color/basic_black</item>
</style>
复制代码
应用到 TextView
中:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/price"
style="@style/ContentText"/>
复制代码
或许你须要为按钮控件作一样的事情,不要中止在那里,将一组相关的和重复 android:xxxx
的属性放到一个通用的 <style>
中。
每一个类完成后应该有做者姓名和联系方式的注释,对本身的代码负责。
/** * <pre> * author : nanchen * e-mail : xxx@xx * time : 2021/01/18 * desc : xxxx 描述 * version: 1.0 * </pre> */
public class WelcomeActivity {
...
}
复制代码
具体能够在 AS 中本身配制,进入 Settings -> Editor -> File and Code Templates -> Includes -> File Header,输入
/** * <pre> * author : ${USER} * e-mail : xxx@xx * time : ${YEAR}/${MONTH}/${DAY} * desc : * version: 1.0 * </pre> */
复制代码
这样即可在每次新建类的时候自动加上该头注释。
每个成员方法(包括自定义成员方法、覆盖方法、属性方法)的方法头都必须作方法头注释,在方法前一行输入 /** + 回车
或者设置 Fix doc comment
(Settings -> Keymap -> Fix doc comment)快捷键,AS 便会帮你生成模板,咱们只须要补全参数便可,以下所示。@param
, @return
, @throws
, @deprecated
这 4 种标记出现的时候,描述都不能为空。当描述没法在一行中容纳,连续行至少须要再缩进 4 个空格。
/** * Report an accessibility action to this view's parents for delegated processing. * * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally * call this method to delegate an accessibility action to a supporting parent. If the parent * returns true from its * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)} * method this method will return true to signify that the action was consumed.</p> * * <p>This method is useful for implementing nested scrolling child views. If * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action * a custom view implementation may invoke this method to allow a parent to consume the * scroll first. If this method returns true the custom view should skip its own scrolling * behavior.</p> * * @param action Accessibility action to delegate * @param arguments Optional action arguments * @return true if the action was consumed by a parent */
public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
for (ViewParent p = getParent(); p != null; p = p.getParent()) {
if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
return true;
}
}
return false;
}
复制代码
块注释与其周围的代码在同一缩进级别。它们能够是 /* ... */
风格,也能够是 // ...
风格(//
后最好带一个空格)。对于多行的 /* ... */
注释,后续行必须从 *
开始, 而且与前一行的 *
对齐。如下示例注释都是 OK 的。
/* * This is okay. */
// And so
// is this.
/* Or you can * even do this. */
复制代码
注释不要封闭在由星号或其它字符绘制的框架里。
Tip:在写多行注释时,若是你但愿在必要时能从新换行(即注释像段落风格同样),那么使用
/* ... */
。
好比:
全局变量的注释样式以下(注意注释之间有空格):
/** * The next available accessibility id. */
private static int nextAccessibilityViewId;
/** * The animation currently associated with this view. */
protected Animation currentAnimation = null;
复制代码
AS 已帮你集成了一些注释模板,咱们只须要直接使用便可,在代码中输入 TODO
、FIXME
等这些注释模板,回车后便会出现以下注释。
// TODO: 17/3/14 须要实现,但目前还未实现的功能的说明
// FIXME: 17/3/14 须要修正,甚至代码是错误的,不能工做,须要修复的说明
复制代码
好比 Item getItem(int index)
是一段自说明的代码,咱们能够直接从方法的命名就能知道它是干吗的,因此不须要增长注释。
左大括号不单独占一行,与其前面的代码位于同一行:
class MyClass {
int func() {
if (something) {
// ...
} else if (somethingElse) {
// ...
} else {
// ...
}
}
}
复制代码
咱们须要在条件语句周围添加大括号。例外状况:若是整个条件语句(条件和主体)适合放在同一行,那么您能够(但不是必须)将其所有放在一行上。例如,咱们接受如下样式:
if (condition) {
body();
}
复制代码
一样也接受如下样式:
if (condition) body();
复制代码
但不接受如下样式:
if (condition)
body(); // bad!
复制代码
在可行的状况下,尽可能编写短小精炼的方法。咱们了解,有些状况下较长的方法是恰当的,所以对方法的代码长度没有作出硬性限制。若是某个方法的代码超出 40 行,请考虑是否能够在不破坏程序结构的前提下对其拆解。
这并无惟一的正确解决方案,但若是都使用一致的顺序将会提升代码的可读性,推荐使用以下排序:
例如:
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private String mTitle;
private TextView mTextViewTitle;
@Override
public void onCreate() {
...
}
public void setTitle(String title) {
mTitle = title;
}
private void setUpView() {
...
}
static class AnInnerClass {
}
}
复制代码
若是类继承于 Android 组件(例如 Activity
或 Fragment
),那么把重写函数按照他们的生命周期进行排序是一个很是好的习惯,例如,Activity
实现了 onCreate()
、onDestroy()
、onPause()
、onResume()
,它的正确排序以下所示:
public class MainActivity extends Activity {
//Order matches Activity lifecycle
@Override
public void onCreate() {}
@Override
public void onResume() {}
@Override
public void onPause() {}
@Override
public void onDestroy() {}
}
复制代码
在 Android 开发过程当中,Context
在函数参数中是再常见不过的了,咱们最好把 Context
做为其第一个参数。
正相反,咱们把回调接口应该做为其最后一个参数。
例如:
// Context always goes first
public User loadUser(Context context, int userId);
// Callbacks always go last
public void loadUserAsync(Context context, int userId, UserCallback callback);
复制代码
Android SDK 中的不少类都用到了键值对函数,好比 SharedPreferences
、Bundle
、Intent
,因此,即使是一个小应用,咱们最终也不得不编写大量的字符串常量。
当时用到这些类的时候,咱们 必须 将它们的键定义为 static final
字段,并遵循如下指示做为前缀。
类 | 字段名前缀 |
---|---|
SharedPreferences | PREF_ |
Bundle | BUNDLE_ |
Fragment Arguments | ARGUMENT_ |
Intent Extra | EXTRA_ |
Intent Action | ACTION_ |
说明:虽然 Fragment.getArguments()
获得的也是 Bundle
,但由于这是 Bundle
的经常使用用法,因此特地为此定义一个不一样的前缀。
例如:
// 注意:字段的值与名称相同以免重复问题
static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";
// 与意图相关的项使用完整的包名做为值的前缀
static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";
复制代码
代码中每一行文本的长度都应该不超过 160 个字符。虽然关于此规则存在不少争论,但最终决定还是以 160 个字符为上限,若是行长超过了 160(AS 窗口右侧的竖线就是设置的行宽末尾 ),咱们一般有两种方法来缩减行长。
不过存在如下例外状况:
这没有一个准确的解决方案来决定如何换行,一般不一样的解决方案都是有效的,可是有一些规则能够应用于常见的状况。
除赋值操做符以外,咱们把换行符放在操做符以前,例如:
int longName = anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne
+ theFinalOne;
复制代码
赋值操做符的换行咱们放在其后,例如:
int longName =
anotherVeryLongVariable + anEvenLongerOne - thisRidiculousLongOne + theFinalOne;
复制代码
当同一行中调用多个函数时(好比使用构建器时),对每一个函数的调用应该在新的一行中,咱们把换行符插入在 .
以前。
例如:
Picasso.with(context).load("https://blankj.com/images/avatar.jpg").into(ivAvatar);
复制代码
咱们应该使用以下规则:
Picasso.with(context)
.load("https://blankj.com/images/avatar.jpg")
.into(ivAvatar);
复制代码
当一个方法有不少参数或者参数很长的时候,咱们应该在每一个 ,
后面进行换行。
好比:
loadPicture(context, "https://blankj.com/images/avatar.jpg", ivAvatar, "Avatar of the user", clickListener);
复制代码
咱们应该使用以下规则:
loadPicture(context,
"https://blankj.com/images/avatar.jpg",
ivAvatar,
"Avatar of the user",
clickListener);
复制代码
RxJava 的每一个操做符都须要换新行,而且把换行符插入在 .
以前。
例如:
public Observable<Location> syncLocations() {
return mDatabaseHelper.getAllLocations()
.concatMap(new Func1<Location, Observable<? extends Location>>() {
@Override
public Observable<? extends Location> call(Location location) {
return mRetrofitService.getLocation(location.id);
}
})
.retry(new Func2<Integer, Throwable, Boolean>() {
@Override
public Boolean call(Integer numRetries, Throwable throwable) {
return throwable instanceof RetrofitError;
}
});
}
复制代码
参考文档:
source.android.com/source/code…
developer.android.com/kotlin/styl…
github.com/Blankj/Andr…
本文同步发表于个人微信公众号,微信搜索 nanchen 便可关注