Android的开发文档规范

我们项目的代码时间时间很长,经过太多人手,代码的规范性堪忧,目前存在较多的比较自由的「代码规范」,这非常不利于项目的维护,代码可读性也不够高。
分析现有项目的代码的情况,输出的『定制化规范』文档,用于提高代码的可读性和可维护性。

目的

  • 对于个人:帮助团队写「正确」的代码,提升编程能力。
  • 团队内部:统一项目的编码风格,降低维护『非自己模块』的成本
  • 对外部门:交付更加稳定的产品,并降低后期的维护难度

准备及通用

开发工具配置规范

工欲善其事,必先利其器。

  • 推荐使用最新的稳定版本的 Android Studio 进行开发

  • 编码格式必须统一为UTF-8

  • 编辑完 .java、.kt、.xml 等文件后必须格式化(需要在设置好以下几点的前提下,Reformat Code 的必要性,一定需要保证 IDE 配置一致为前提,尽可能贴切于 Android Studio 默认。强烈建议对于比较长的老代码局部格式化,不全局格式化)

  • 每行字符数不得超过100字符(IDE默认)
    设置 Editor -> Code Style

  • Java代码格式规则(默认设置)

全部设置为单类导入

  • XML代码格式规则(默认设置)

  • 格式化快捷键(默认设置)

以上几处设置完毕,其他采用 Android Studio 默认方式,再进行 Reformat Code 快捷键即可。

  • 可以安装Alibaba Java开发规范插件,进行代码规范的检查

地址:https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines

代码格式

  • 【强制】提交经过格式化的代码
  • 【强制】单行代码不要超过IDE右边界,单行字符数限制不超过100个(默认设置)
    如果超出行长,我们通常有两种方法来缩减行长。
    1.提取一个局部变量或方法(最好)
    2.使用换行符将一行换成多行(参考『换行策略』)

例外情况:
1.如果备注行包含长度超过 100 个字符的示例命令或文字网址,那么为了便于剪切和粘贴,该行可以超过 100 个字符。
2.导入语句行可以超出此限制,因为用户很少会看到它们(这也简化了工具编写流程)。

  • 【强制】方法、参数、变量命名使用小骆驼拼写法(lowerCamelCase)
  • 【强制】方法之间需要空1行
  • 【强制】杜绝完全不规范的缩写,避免望文不知义。比如:condition“缩写”命名成 condi,英文拼音混合
  • 【强制】如果使用到了设计模式,建议在类名中体现出具体模式。
  • 【强制】方法调用的点符号与下文一起换行,在多个参数超长,在逗号后换行

换行策略(操作符"之前"换行,而逗号"之后"换行。)

这没有一个准确的解决方案来决定如何换行,通常不同的解决方案都是有效的,但是有一些规则可以应用于常见的情况。

操作符的换行

赋值操作符的换行我们放在其后,例如:

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 链式的换行

RxJava 的每个操作符都需要换新行,并且把换行符插入在 . 之前。

例如:

public Observable<Location> syncLocations() {return mDatabaseHelper.getAllLocations().concatMap(new Func1<Location, Observable<? extends Location>>() {@Overridepublic Observable<? extends Location> call(Location location) {return mRetrofitService.getLocation(location.id);}}).retry(new Func2<Integer, Throwable, Boolean>() {@Overridepublic Boolean call(Integer numRetries, Throwable throwable) {return throwable instanceof RetrofitError;}});
}
  • 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用『单数形式』,但是类名如果有复数含义,类名可以使用『复数形式』。
    正例: 应用工具类包名为com.alibaba.open.util、类名为MessageUtils(此规则参考 spring 的框架结构)
  • 【参考】枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。

OOP 规约

  • 【推荐】类成员的顺序,没有唯一的正确解决方案。但如果都使用一致的顺序将会提高代码的可读性,推荐使用如下排序:常量>属性>构造函数>set/get方法>公有函数>私有函数>内部类或接口
public class MainActivity extends Activity {private static final String TAG = MainActivity.class.getSimpleName();private String mTitle;private TextView mTextViewTitle;@Overridepublic 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@Overridepublic void onCreate() {}@Overridepublic void onResume() {}@Overridepublic void onPause() {}@Overridepublic void onDestroy() {}
}
  • 【推荐】类成员与方法访问控制从严:
  1. 如果不允许外部直接通过new来创建对象,那么构造方法必须是private。
  2. 工具类不允许有public或default构造方法。
  3. 类非static成员变量并且与子类共享,必须是protected。
  4. 类非static成员变量并且仅在本类使用,必须是private。
  5. 类static成员变量如果仅在本类使用,必须是private。
  6. 若是static成员变量,必须考虑是否为final。
  7. 类成员方法只供类内部调用,必须是private。
  8. 类成员方法只对继承类公开,那么限制为protected。
  • 【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读。
  • 【推荐】setter 方法中,参数名称与类成员变量名称一致,this.成员名 = 参数名。『getter/setter 方法中,不要添加业务逻辑,业务逻辑可以放在其他工具类』
  • 【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
  • 【推荐】函数参数的排序,在 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);

注释规范

  • 【极好】类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容/格式,不得使用 //xxx 方式。
  • 【强制】所有的抽象方法(包括接口中的方法)必须要用Javadoc注释,返回值、参数、异常都需要有注释,还必须指出该方法做什么事情,实现什么功能。
  • 【强制】所有的枚举类型字段必须要有注释,说明每个数据项的用途。
  • 【强制】正确使用注释(//,/**/)
  • 【强制】注释要规范,避免尾行注释

Java代码

变量的命名和值

  • 【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
  • 【推荐】使用Android特有常量的命名规范,参考『Android特有常量』
  • 【推荐】一行代码只声明一个变量,不要有多个变量
  • 【强制】视图变量规则:类型缩写(小写)+业务名称,如:btnClose,tvTitle(参考『常见的视图控件缩写表』)
  • 【推荐】视图变量的『声明顺序』要尽量和『XML布局』里的摆放顺序一致
  • 【强制】中括号是数组类型的一部分,数组定义如下:String[] args;
  • 【强制】不建议魔法值(即未经定义的常量)直接出现在代码中,如果没有抽取,相关代码处需写清楚『注释』。
  • 【强制】long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。
  • 【推荐】常量的复用层次,类常量<包常量<模块常量,优先使用作用域小的常量。

Android特有常量

Android SDK 中的很多类都用到了键值对函数,比如SharedPreferences、Bundle、Intent,所以,即便是一个小应用,我们最终也不得不编写大量的字符串常量。当时用到这些类的时候,我们『必须』将它们的键定义为 static final 字段,并遵循以下指示作为前缀。

字段名前缀
SharedPreferences PREF_
Bundle BUNDLE_
Fragment Arguments ARGUMENT_
Intent Extra EXTRA_
Intent Action ACTION_

例如:

// 注意:字段的值与名称相同以避免重复问题
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";

常见的视图控件缩写表

UI控件 缩写
LinearLayout ll
RelativeLayout rl
FrameLayout fl
Button btn
ImageButton ibtn
TextView tv
ImageView iv
RecyclerView rv
ConstraintLayout cl
ScollView sv
CheckBox cb
RadioButton rb
EditText et

方法的内部实现

  • 【强制】尽量使用lambda代替匿名内部类
  • 【极好】方法的参数和返回值,添加@NonNull,@Nullable注解
    (包含其他androidx.anotation)
  • 【强制】无用的代码直接删除(检测:各自模块无用代码直接删除)
  • 【强制】不要任意添加try-catch,如果添加try-catch需要明确异常
  • 【强制】不要在方法内部修改参数的值(a方法调用,会影响后面的b方法)
  • 【推荐】单个方法实现不超过屏幕(80行,缩短代码行数,做好拆分)
  • 【推荐】方法内部不需要空行
  • 【推荐】不同业务View设置不同事件监听(例如OnClickListener)
  • 【推荐】if-else不要写反向逻辑
  • 【推荐】表达异常的分支时,少用 if-else 方式,这种方式可以改写成:if (condition) { return ; }
  • 【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
    正例: “test”.equals(object);
    反例: object.equals(“test”);
  • 【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式。
  • 【推荐】使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。
  • 【强制】在 if/else/for/while/do 语句中必须使用大括号。即使只有一行代码,避免使用 单行的形式:if (condition) statements;
  • 【推荐】除常用方法(如 getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

Android代码

Android基本组件

  • 【强制】Activity间通过隐式Intent的跳转,在发出Intent之前必须通过resolveActivity 检查,避免找不到合适的调用组件,造成 ActivityNotFoundException 的异常。
  • 【强制】Activity和Fragment的参数要使用@Autowired(原因:减少模板代码,支持ARouter跳转)
  • 【强制】避免在 BroadcastReceiver#onReceive()中执行耗时操作,如果有耗时工作, 应该创建 IntentService 完成,而不应该在 BroadcastReceiver 内创建子线程去做。
  • 【强制】如果广播仅限于应用内,则可以使用LocalBroadcastManager.sendBroadcast()实现,避免敏感信息外泄和Intent拦截的风险。
  • 【推荐】优先考虑EventBus等框架代替Broadcast(如果操作轻量级,不涉及Intent和Context的情况下)
  • 【推荐】当前Activity的onPause方法执行结束后才会执行下一个Activity的onCreate 方法,所以在onPause方法中不适合做耗时较长的工作,这会影响到页面之间的跳转效率。
  • 【推荐】使用 Toast 时,建议定义一个全局的Toast对象,这样可以避免连续显示Toast 时不能取消上一次Toast消息的情况(如果你有连续弹出Toast的情况,避免使用Toast.makeText)。
  • 【强制】Activity或者Fragment中动态注册BroadCastReceiver时registerReceiver()和unregisterReceiver()要成对出现。否则可能导致已经注册的receiver没有在合适的时机注销,导致内存泄漏,占用内存空间,加重SystemService负担。
  • 【强制】同一方法禁止多次调用sp的apply(一些SPUtils只封装单次的提交,连续调用这样的方法就有这个问题)
  • 【强制】在Activity中显示对话框或弹出浮层时,尽量使用 DialogFragment,而非 Dialog/AlertDialog,这样便于随Activity生命周期管理对话框/弹出浮层的生命周期。
  • 【推荐】不能在 Activity 没有完全显示时显示 PopupWindow 和 Dialog

进程、线程与消息通信

  • 【强制】新建线程时,必须通过线程池提供(AsyncTask 或者 ThreadPoolExecutor 或者其他形式自定义的线程池),不允许在应用中自行显式创建线程。(需要线程池)
  • 【强制】线程池不允许使用 Executors 去创建,而是通过ThreadPoolExecutor 的方 式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
  • 【推荐】ThreadPoolExecutor 设置线程存活时间(setKeepAliveTime),确保空闲时 线程能被释放。

文件与数据库

  • 【强制】任何时候不要硬编码文件路径,请使用 Android 文件系统 API 访问。
  • 【强制】当使用外部存储时,必须检查外部存储的可用性。
  • 【强制】应用间共享文件时,不要通过放宽文件系统权限的方式去实现,而应使用 FileProvider。
  • 【推荐】SharedPreference中只能存储简单数据类型(int、boolean、String等), 复杂数据类型建议使用文件、数据库等其他方式存储。
  • 【推荐】SharedPreference 提交数据时,尽量使用 Editor#apply(),而非 Editor#commit()。一般来讲,仅当需要确定提交结果,并据此有后续操作时,才使用Editor#commit()。
  • 【强制】数据库 Cursor 必须确保使用完后关闭,以免内存泄漏。
  • 【强制】多线程操作写入数据库时,需要使用事务,以免出现同步问题。
  • 【推荐】大数据写入数据库时,请使用事务或其他能够提高 I/O 效率的机制,保证执行速度。
  • 【强制】执行 SQL 语句时,应使用 SQLiteDatabase#insert()、update()、delete(), 不要使用 SQLiteDatabase#execSQL(),以免 SQL 注入风险。

Android资源文件

布局

  • 【推荐】推荐使用ConstraintLayout(必要时可以有内部嵌套),布局中不得使用ViewGroup多重嵌套(ConstraintLayout需要普及讲解)
  • 【强制】禁止在非ui线程进行 view 相关操作。
  • 【强制】禁止在设计布局时多次设置子 view和父view中为同样的背景造成页面过度绘制,推荐将不需要显示的布局进行及时隐藏。
  • 【推荐】灵活使用布局,推荐 Merge、ViewStub 来优化布局,尽可能多的减少 UI 布局层级。
  • 【极好】布局文件可以不用运行,仿真预览(使用tools)

Bitmap、Drawable 与动画

  • 【强制】加载大图片或者一次性加载多张图片,应该在异步线程中进行。图片的加载,涉及到I 操作,以及CPU密集操作,很可能引起卡顿。
  • 【强制】png 图片使用 tinypng 或者类似工具压缩处理,减少包体积。
  • 【强制】在 Activity.onPause()或 Activity.onStop()回调中,关闭当前 activity 正在执 行的的动画。
  • 【推荐】在动画或者其他异步任务结束时,应该考虑回调时刻的环境是否还支持业务处理。例如 Activity的onStop()函数已经执行,且在该函数中主动释放了资源,此时回调中如果不做判断就会空指针崩溃。
  • 【推荐】尽量减少Bitmap(BitmapDrawable)的使用,尽量使用纯色(ColorDrawable)、渐变色(GradientDrawable)、StateSelector(StateListDrawable)等与Shape结合的形式构建绘图。

Android 资源文件命名与使用

  • 【强制】资源文件需带模块前缀(公用放在base)
  • 【强制】动画资源文件(anim/和animator/)

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/)

color/是专门用于存放颜色相关资源的文件夹。命名规则:类型{_模块名}_逻辑名称。

  • 【强制】图片资源文件(drawable/ 和 mipmap/)

res/drawable/ 目录下放的是位图文件(.png、.9.png、.jpg、.gif)或编译为可绘制对象资源子类型的 XML 文件,而 res/mipmap/ 目录下放的是不同密度的启动图标,所以 res/mipmap/ 只用于存放启动图标,其余图片资源文件都应该放到 res/drawable/ 目录下。

命名规则:类型{_页面名称}{_逻辑名称}{_颜色}

说明:{}中的内容为可选;类型 可以是可绘制对象资源类型。
例如:

名称 说明
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_pressedstate_pressed 点击效果
btn_xx_focusedstate_focused 聚焦效果
btn_xx_disabledstate_enabled 不可用效果
btn_xx_checkedstate_checked 选中效果
btn_xx_selectedstate_selected 选中效果
btn_xx_hoveredstate_hovered 悬停效果
btn_xx_checkablestate_checkable 可选效果
btn_xx_activatedstate_activated 激活效果
btn_xx_window_focusedstate_window_focused 窗口聚焦效果

注意:使用 Android Studio 的插件 SelectorChapek 可以快速生成 selector,前提是命名要规范。

  • 【强制】 布局资源文件(layout/)

命名规则:模块名_类型_

类型 名称 说明
Activity passport_activity_main.xml 窗体页面 模块名_类型_页面名称
Fragment resume_fragment_music.xml 音乐片段 模块名_类型_逻辑名称
Dialog resume_dialog_loading.xml 加载对话框 模块名_类型_逻辑名称
PopupWindow position_popup_info.xml 信息弹窗(PopupWindow) 模块名_类型_逻辑名称
adapter 的列表项 my_item_main_song.xml 主页歌曲列表项 模块名_类型_页面名称_逻辑名称
  • 【强制】视图layout布局的命名:view_float_live
  • 【强制】嵌套layout布局的命名:layout_title_bar(一般有复用)
  • 【强制】布局资源 id 命名

命名规则:类型小写_{模块名_}_逻辑名,例如:btn_main_search、btn_back。

  • 【推荐】colors.xml

的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">#2a91db</color><color name="orange">#ff9d2f</color><color name="red">#ff432f</color></resources>

向应用设计者那里要这个调色板,名称不需要跟 “green”、“blue” 等等相同。“brand_primary”、“brand_secondary”、“brand_negative” 这样的名字也是完全可以接受的。像这样规范的颜色很容易修改或重构,会使应用一共使用了多少种不同的颜色变得非常清晰。通常一个具有审美价值的 UI 来说,减少使用颜色的种类是非常重要的。

  • 【强制】styles.xml

style的name命名使用大驼峰命名法,几乎每个项目都需要适当的使用 styles.xml 文件,因为对于一个视图来说,有一个重复的外观是很常见的,将所有的外观细节属性(colors、padding、font)放在 styles.xml 文件中。在应用中对于大多数文本内容,最起码你应该有一个通用的styles.xml 文件,例如:

<resources><style name="ContentText"><item name="android:textSize">@dimen/font_normal</item><item name="android:textColor">@color/basic_black</item></style>
</resources>

应用到 TextView 中:

<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/price"style="@style/ContentText"/>
  • 【推荐】style 资源采用小写单词+下划线方式命名,写入 module_styles.xml 文件中, 采用以下规则:父style名称.当前style名称,如ParentTheme.ThisActivityTheme。

参考

  • 阿里巴巴Java开发手册v1.2.0
  • 阿里巴巴Android开发手册
  • Android代码规范大全(https://juejin.cn/post/6921257795555852301)
  • BroadcastReceiver、EventBus的优缺点(https://blog.csdn.net/crazy_yyyyy/article/details/51318092)

Android的开发文档规范相关推荐

  1. Android官方开发文档Training系列课程中文版:目录

    原文地址 : http://android.xsoftlab.net/training/index.html 引言 在翻译了一篇安卓的官方文档之后,我觉得应该做一件事情,就是把安卓的整篇训练课程全部翻 ...

  2. Android官方开发文档Training系列课程中文版:创建自定义View之View的创建

    原文地址:http://android.xsoftlab.net/training/custom-views/index.html 引言 Android框架含有大量的View类,这些类用来显示各式各样 ...

  3. Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制

    原文地址:http://android.xsoftlab.net/training/graphics/opengl/draw.html 如果你还不清楚如何定义图形及坐标系统,请移步:Android官方 ...

  4. android 中文开发文档

    android 中文开发文档 ,请点击一下连接,学习官方开发文档 https://developer.android.google.cn/training/basics/firstapp

  5. Android官方开发文档Training系列课程中文版:使用Fragment构建动态UI之Fragment创建

    原文地址:http://android.xsoftlab.net/training/basics/fragments/index.html 导言 为了在Android中创建动态的多面板用户界面,你需要 ...

  6. Android官方开发文档Training系列课程中文版:构建第一款安卓应用之入门指南

    入门指南 欢迎来到安卓开发训练课,在这里你可以找到一系列课程来描述如何使用现有的代码示例来重新适用到你的APP上,你可以在左侧的导航栏顶部看到在若干个大项里有若干个有组织的子项课程.(导航栏请参见官方 ...

  7. Android官方开发文档Training系列课程中文版:线程执行操作之创建多线程管理器

    原文地址:http://android.xsoftlab.net/training/multiple-threads/create-threadpool.html 上节课我们学习了如何定义一个任务.如 ...

  8. Android官方开发文档Training系列课程中文版:电池续航时间优化之监测电池电量及充电状态

    原文地址:http://android.xsoftlab.net/training/monitoring-device-state/index.html 引言 作为一款优秀的APP应用,应该总是想方设 ...

  9. Android官方开发文档Training系列课程中文版:性能优化建议

    原文地址:http://android.xsoftlab.net/training/articles/perf-tips.html 本篇文章主要介绍那些可以提升整体性能的微小优化点.它与那些能突然改观 ...

最新文章

  1. oracle schedule stop,Oracle调度Schedule特性(第八部分)-Windows和Window Groups
  2. 能实现自控的那天,再考虑其他
  3. IntelliJ IDEA中跳转到上一个视图位置(向后/向前导航)的键盘快捷键
  4. ubuntu更新rtl8192cu驱动
  5. 使用java做paypal开发时购买东西支付不成功的原因
  6. [Java] grails 安装手记
  7. 【Python】编程笔记11
  8. Vista下与移动设备的同步笔记
  9. 如何在麦田拍出小清新?
  10. 目前我们所说的个人商用计算机属于,计算机组成原理试题库(大专生用,共20份,有答案)...
  11. Linux操作系统中GDB工具常见用法(一)
  12. 浅谈下对volatile的理解
  13. 2019年泰迪杯技能赛A题心得
  14. 云南省A级旅游景区名录(截止2016年12月)
  15. Lora入门(1)—— PingPong测试(CubeMX篇)
  16. 线性波传播至垂直壁面反射形成驻波的动画MATLAB程序
  17. Python基础知识-字典dictionary
  18. 微信小程序连接emqx服务器实现数据交互
  19. IE浏览器一打开就提示“已停止工作”的解决方案
  20. Linux安装卸载 Mysql完整步骤

热门文章

  1. HTML 基本开发方式,学会常用的 HTML 标签
  2. usb rndis主机接收数据错误的分析
  3. windows中搭建当当网
  4. 清华大学研读间助手-清华小图Android
  5. SQL语句两字段拼成一个字段显示
  6. sqlserver配置定时任务查询SQL导出excel并以附件发送邮件
  7. VCSA 7.0 重置root密码
  8. [Codewar练习-javac++]Twice linear(双线性)
  9. SpringBoot2.3.x整合ElasticSearch7.6.2 实现PDF,WORD全文检索
  10. 【天池学习赛】数据分析达人赛3:汽车产品聚类分析