3-2-11 Designtime设计时属性

tools属性可以替换所有Android的属性,只在设计阶段有效,不会被带入最终的apk中,所以运行时无效。譬如我们最常见的在写一个TextView时不想在xml中给他初始文本内容,又想预览,这时候就可以用tools属性替代。如下:

tools:text=“Name:”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

tools:visibility=“invisible” />

可以看见,tools命名空间属性可以加速我们开发的灵活度和可预测度,同时在编译框架中又会忽略这些属性,不把他们带入最终产物apk中,我们可以在开发中酌情选择是否使用这些属性。

3-3 Android Annotations注解说明

在Android Support Library的19.1版本中加入了一个新的注解包,这个包用来注解代码,方便捕获程序中存在的问题和bug,这个包内部的代码就已经使用了该注解,在22.2版本中又增加了13个新的注解,这些注解可以方便我们代码开发与调运规范和bug检查,具体用法下面会一一讲解。

3-3-1 注解Library依赖引用

annotations注解包默认不会自动被包含,不过如果使用appcompat包则会自动包含,因为appcompat包里使用了注解。

在Android工程的Gradle文件中引入注解包如下:

dependencies {

compile ‘com.android.support:support-annotations:22.2.0’

}

如果不是Android工程中想使用该注解包则可以如下写法(url为本地android sdk的注解包路径):

repositories {

jcenter()

maven { url ‘/extras/android/m2repository’ }

}

3-3-2 执行注解

当我们在用Android Studio和IntelliJ时如果给使用了注解的方法传递错误类型参数,则IDE会实时标记提醒错误。如果使用的是Gradle 1.3.0版本以上且安装了Android M Preview Tools以上工具则可以通过命令行调用gradle的lint任务进行检查(nullness注解会被忽略检查)。

3-3-3 Null空类型判断注解

@Nullable 注解用来标注给定的参数或返回值可以为null。

@NonNull 注解用来标注给定的参数或返回值不能为null。

假设一个本地变量值为null,且把它作为参数传递给一个方法,且该方法的参数被@NonNull标注,则AS会提醒存在一个潜在的崩溃。如下:

import android.support.annotation.NonNull;

import android.support.annotation.Nullable;

/**

Add support for inflating the tag.

*/

@Nullable

@Override

public View onCreateView(String name, @NonNull Context context, @NonNull AttributeSet attrs) {

3-3-4 资源类型注解

Android的资源值通常都是通过R文件映射的整型id来关联的,也就是说获取一个layout类型的资源参数很容易被误传递一个其他类型的资源参数,因为他们都是整型的资源id,编译器很难区分。为了解决这种问题可以使用资源类型注解,因为注解提供类型检查。譬如下面是一个被@LayoutRes注解的整型参数却传递了一个string类型的资源参数,此时IDE会给出错误提示:

调运setContentView方法时传递错误参数:

setContentView的资源注解实现方法:

实际上有很多不同的资源类型注解,譬如@AnimatorRes、@AnimRes、@AnyRes、@ArrayRes、@AttrRes、@BoolRes、@ColorRes、@DimenRes、@DrawableRes、@FractionRes、@IdRes、@IntegerRes、@InterpolatorRes、@LayoutRes、@MenuRes、@PluralsRes、@RawRes、@StringRes、@StyleableRes、@StyleRes、@XmlRes等,一般一个foo类型资源的相应资源类型注解就是@FooRes。除此之外,还有一个名为@AnyRes的特殊资源类型注解,它被用来标注一个未知特殊类型的资源,且必须是一个资源类型。譬如在Resources.getResourceName(@AnyRes int resId)上使用的时候,我们可以通过getResources().getResourceName(R.drawable.icon)和getResources().getResourceName(R.string.app_name)等方式来使用,但却不能通过getResources().getResourceName(42)来使用。

3-3-5 IntDef/StringDef类型注解

这种类型的注解是基于Intellij的魔数检查机制的,因为Android开发中很多时候出于性能考虑,我们会使用整型常量代替枚举类型。譬如AppCompat库里的一个例子:

import android.support.annotation.IntDef;

public abstract class ActionBar {

@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})

@Retention(RetentionPolicy.SOURCE)

public @interface NavigationMode {}

public static final int NAVIGATION_MODE_STANDARD = 0;

public static final int NAVIGATION_MODE_LIST = 1;

public static final int NAVIGATION_MODE_TABS = 2;

@NavigationMode

public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

上面非注解的部分是原本的代码和API,我们通过@interface创建了一个新注解NavigationMode,并且用@IntDef标注它可能的取值,还添加了@Retention(RetentionPolicy.SOURCE)告诉编译器这个新定义的注解不需要被记录在生成的.class文件中;使用这个注解后,如果我们返回或传递的参数不在指定的常量值中则IDE会给出明显的错误提示。

我们也可以指定整型常量为一个标记性质的类型,因为这样就可以通过|、&等操作符同时传递多个整型常量。如下例子:

@IntDef(flag=true, value={

DISPLAY_USE_LOGO,

DISPLAY_SHOW_HOME,

DISPLAY_HOME_AS_UP,

DISPLAY_SHOW_TITLE,

DISPLAY_SHOW_CUSTOM

})

@Retention(RetentionPolicy.SOURCE)

public @interface DisplayOptions {}

@StringDef和@IntDef的作用基本上一样,不同的是它针对的是字符串。关于类型注解更多信息点我获取。

3-3-6 线程注解@UiThread、@WorkerThread等

线程注解是在Support Library 22.2及更高版本中才被支持的,如果我们的方法只能在指定的线程类型中被调用,则就可以使用以下4个注解来标注它们:

@UiThread @MainThread @WorkerThread @BinderThread

如果一个类中的所有方法都有相同的线程需求则可以注解类本身。

关于线程注解使用的一个例子是AsyncTask,如下:

@WorkerThread

protected abstract Result doInBackground(Params… params);

@MainThread

protected void onProgressUpdate(Progress… values) {

}

如果在使用该方法时没有按照注解线程执行则会报错,如下:

3-3-7 约束值注解@Size、@IntRange、@FloatRange

如果我们的参数是float或double类型且限制在一个范围内,则可以使用@FloatRange注解,如下:

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {

如果我们的参数是int或long类型则可以使用@IntRange注解来约束值的范围,如下:

public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }

对于数据集合或字符串,我们可以用@Size注解来限定集合大小或字符串长度。譬如:

//集合不能为空

@Size(min=1)

//字符串最多只能有23个字符

@Size(max=23)

//数组只能有2个元素

@Size(2)

//数组大小必须是2的倍数

@Size(multiple=2)

3-3-8 权限注解@RequiresPermission

如果我们的方法调用时需要特定权限,则可以用@RequiresPermission进行注解。如下:

@RequiresPermission(Manifest.permission.SET_WALLPAPER)

public abstract void setWallpaper(Bitmap bitmap) throws IOException;

如果方法至少需要权限集合中的一个则可以使用anyOf属性。如下:

@RequiresPermission(anyOf = {

Manifest.permission.ACCESS_COARSE_LOCATION,

Manifest.permission.ACCESS_FINE_LOCATION})

public abstract Location getLastKnownLocation(String provider);

如果方法同时需要多个权限则可以使用allOf属性。如下:

@RequiresPermission(allOf = {

Manifest.permission.READ_HISTORY_BOOKMARKS,

Manifest.permission.WRITE_HISTORY_BOOKMARKS})

public static final void updateVisitedHistory(ContentResolver cr, String url, boolean real) {

对于Intent的权限可以直接在定义的Intent常量字符串字段上标注权限需求(通常都已经被@SdkConstant注解标注过了)。如下:

@RequiresPermission(android.Manifest.permission.BLUETOOTH)

public static final String ACTION_REQUEST_DISCOVERABLE =

“android.bluetooth.adapter.action.REQUEST_DISCOVERABLE”;

有时对于ContentProvider的权限可能需要单独的标注读和写权限,所以可以用@Read或者@Write注解。如下:

@RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))

@RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))

public static final Uri BOOKMARKS_URI = Uri.parse(“content://browser/bookmarks”);

3-3-9 重写方法注解@CallSuper

如果想在重写方法中要求必须调运父类的super方法则可以用@CallSuper标注。如下:

@CallSuper

protected void onCreate(@Nullable Bundle savedInstanceState) {

3-3-10 @CheckResult、@VisibleForTesting、@Keep

如果我们的方法返回一个值且期望调用者用这个值做些事情则可以使用@CheckResult注解标注这个方法。

如果我们想在测试时使用一个类、方法或者字段则可以用@VisibleForTesting注解进行标明。

特别要说的就是我们还在注解库里添加了@Keep注解,但是Gradle插件目前版本支持的还不是很好,这个注解标注的东西不会被混淆。

3-3-11 其他注解相关

如果我们在自己的lib库中使用了上面这些注解,且通过Gradle构建生成了aar包,则在构建时Android Gradle插件会提取注解信息放在aar文件中供使用库的地方使用。在aar文件中你可以看到一个名为annotations.zip的文件,这个文件记录的就是使用IntelliJ扩展注解XML格式的注解信息。

PS一句,IntelliJ其实还有他自己的注解,这里不再详细说明。

可以看见,有了这种注解我们的IDE看起来就更加的智能便捷强大了,同时也帮助我们的编译框架及早的发现问题,给出警告或者错误提示。

【工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请尊重作者劳动成果。私信联系我】

4 Gradle Android构建

======================

其实Android的Gradle构建没啥太多说的,掌握Groovy语法和Gradle框架后看看Gradle Android Plugs相关DSL特性就行了,用的时候去查API和Android DSL规则即可,重点明白结构和常用的DSL规则即可,这里给出一个常用模板,补充常用实战基础示例参见《Android Studio入门到精通》一文的第7小节。

4-1 Gradle Android编译构建配置基础

Android Studio的project在project树根和每个module根都包含一个叫build.gradle的文件,我们所谓的编译构建配置其实就是通过Gradle的Android插件进行编写脚本,大多数情况下我们一般只用修改相关module下的build.gradle文件就能满足需求。如下一个例子:

//添加Gradle的Android构建插件,默认包含一些task和android {…}等特定元素

apply plugin: ‘com.android.application’

//android元素用来配置Android编译特有选项

android {

//!!!特别注意:我们一定要保证buildToolsVersion版本号总是高于等于compileSdkVersion版本号

//指定编译目标

compileSdkVersion 19

//指定编译工具版本,可以通过SDK Manager查看

buildToolsVersion “19.0.0”

//defaultConfig元素用来配置核心设置和AndroidManifest.xml文件的动态配置,这里的值会覆盖AndroidManifest.xml文件中相对应的值。

//!!!特别注意:defaultConfig元素值默认应用于所有build variant,除非我们在build variant中重写这些值

defaultConfig {

//!!!App的唯一id只能在这里声明,不能在AndroidManifest.xml中

applicationId “com.example.my.app”

minSdkVersion 8

targetSdkVersion 19

versionCode 1

versionName “1.0”

}

//buildTypes元素用来控制如何打包编译app

//默认情况下编译系统定义了两中编译类型:debug和release

//debug类型默认会包含调试符和debug key,但是release默认不包含签名

buildTypes {

release {

//通过Run ProGuard进行资源混淆!!!

minifyEnabled true

//getDefaultProguardFile默认获取SDK路径下的文件,我们还可以指定一个混淆规则文件,譬如proguard-rules.pro

proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’

}

}

}

//dependencies在android元素之外且之下,该元素用来指明当前module的依赖关系,构建系统会把这些依赖加入编译classpath中

dependencies {

//Module依赖,编译时会被包含进去

compile project(“:lib”)

//远程二进制依赖

compile ‘com.android.support:appcompat-v7:19.0.1’

//本地二进制依赖

compile fileTree(dir: ‘libs’, include: [‘*.jar’])

}

有时候你会在gradle脚本中发现repositories被声明两次,这时候你一定有过疑惑的,下面给出这个疑惑的答案:

**buildscript块中的repositories声明:**该声明的作用是声明gradle脚本自身要用的资源(譬如依赖项、第三方插件、maven地址等)。

**build.gradle文件中的repositories声明:**该声明作用是项目自身需要的资源声明。

如果想在Gradle脚本中使用第三方插件,且这些插件、类库又不用于项目,而是支持其它Gradle脚本运行的,此时我们就该把这种依赖声明放在buildscript代码块中,Gradle在执行脚本时会优先执行buildscript代码块中的内容,然后执行剩余的脚本。相反,如果我们在项目中需要使用一些插件、类库的话,就需要定义在buildscript块之外的dependencies中。

4-2 Gradle Android构建配置build variants

接下来我们来看看如何通过Gradle构建系统对一套项目工程编译多个版本(譬如适配多设备类型、不同应用Market发布等),这个构建功能非常简单、强大和实用。

使用Product flavors进行多版本apk生成的步骤如下:

在build文件中定义product flavors; 为每一个flavor创建额外的资源目录; 把这些资源加入工程进行指定类型编译;

先看第一步,如下定义两中类型的编译配置:

android {

defaultConfig { … }

signingConfigs { … }

buildTypes { … }

productFlavors {

demo {

applicationId “com.buildsystemexample.app.demo”

versionName “1.0-demo”

}

full {

applicationId “com.buildsystemexample.app.full”

versionName “1.0-full”

}

}

}

上面例子创建了id与version不同的两个apk;特别注意,我们一般把不同product flavors相同的属性元素都统一定义在defaultConfig元素中,因为defaultConfig元素的属性值默认应用于所有build variant,除非我们在build variant中重写这些值才可以。

接着我们看下第二步和第三步,为每个flavor添加不同的资源。我们可以看见上一步中定义了不同的applicationId,主要区分是demo和full,也就是说我们可以在src目录下为这两种情况分别创建相关的资源目录(譬如这里创建demo和full目录,我们放置一些特定属于demo和full的区分资源),完事以后在AS的面板中选择Build Variants的不同类型编译即可。

4-3 Gradle Android Plugin DSL

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)

总结

【Android 详细知识点思维脑图(技能树)】

我个人是做Android开发,已经有十来年了,目前在某创业公司任职CTO兼系统架构师。虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

最后,赠与大家一句话,共勉!

化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android) [外链图片转存中…(img-MonvfIJu-1711737096158)]

总结

【Android 详细知识点思维脑图(技能树)】

[外链图片转存中…(img-N7gnMv4v-1711737096158)]

我个人是做Android开发,已经有十来年了,目前在某创业公司任职CTO兼系统架构师。虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

[外链图片转存中…(img-khNiOPMK-1711737096159)]

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

最后,赠与大家一句话,共勉!

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

推荐链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。