《第一行代码第二版》读书笔记 - 第一章 开始启程-你的第一行Android代码

433 阅读10分钟

《第一行代码》是学习 Android 的入门经典,该篇以一名 iOS 开发者的视角记录系统学习 Android 的点滴。

第一章 开始启程-你的第一行Android代码

Android 发展史

  • 2003年10月,Andy Rubin 等人创办了Android 公司。
  • 2005年8月,谷歌收购 Android 公司,并让 Android Rubin 继续负责 Android 项目。
  • 2008年,谷歌终于推出了 Android 系统的第一个版本。
  • 2010年,Linux 团队把 Android 从 Linux 内核主线中除名。

Android 的发展一直受到重重阻挠,乔布斯认为这是一个抄袭 iPhone 的产品,剽窃了诸多iPhone的创意,并声称一定要毁掉 Android。十几年过去了,iOS 和 Android 两个平台彼此各取所长(或者说抄袭),这对我们开发者和使用者是有益的。平台在进化,我们的技能和使用便利性都在提升。另外,甲骨文针对 Android 侵犯 Java 知识产权问题也向谷歌提起了诉讼。

Android 依然快速前进逐渐占据了全球智能手机操作系统 70% 以上的份额,因为谷歌的开放政策,任何厂商和个人都可以免费获取到 Android 系统源码,并随意使用和定制。

1.1 了解全貌-Android 王国介绍

接下来以一个开发者角度,了解一下这个操作系统。

1.1.1 Android 系统架构

Android 大致分为四层架构:

  1. Linux 内核层

    Android 系统基于 Linux 内核,内核层为设备硬件提供底层驱动,如:显示驱动、音频驱动、相机驱动、蓝牙驱动、Wifi 驱动、电源管理驱动等。

  2. 系统运行库层

    该层包含两种库:

    1. C/C++ 库为系统提供主要特性支持,如:SQLite 库提供数据支持、OpenGL|ES 库提供3D绘图支持、WebKit 库提供浏览器内核支持等。
    2. Android 运行时库,如:核心库允许开发者使用 Java 编写 Android 应用、Dalvik 虚拟机(5.0后改为ART运行环境,为移动定制针对手机内存、CPU 性能有限等情况作了优化)使得每一个 Android 应用都能运行在独立的进程中。
  3. 应用框架层

    这一层提供了构建App可能用到的API,如:XMPP服务、活动管理、窗口管理、视图管理、通知管理、包管理等

  4. 应用层 所有安装在手机上的App都属于这一层,如:短信、联系人、微信、支付宝等

图1.1 Android系统架构

1.1.2 Android已发布的版本

  • 2008年9月 Android 1.0 最早的系统版本
  • 2011年2月 Android 3.0 转为平板电脑设计的比较失败而版本
  • 2011年10月Android 4.0 不再区分平板和手机,可在两种设备上应用
  • 2014年I/O大会 Android 5.0 史上版本改动最大,ART运行环境替代了Dalvik虚拟机,提升了运行速度,并提出了Material Design概念来优化界面设计。并推出了Android Wear系统向可穿戴设备进发。
  • 2015年I/O大会 Android 6.0系统,加入运行时权限功能
  • 2016年I/O大会 Android 7.0系统,加入多窗口模式

最新数据可访问:(developer.android.google.cn/about/dashb…)

1.1.3 Android应用开发特色

首先看一下Android系统提供了哪些东西,可供我们开发出优秀的App。

  1. 四大组件

    活动(Activity):所有应用的门面、应用中能看到的东西都放在活动中。

    服务(Service) :不可见、但会在后台一直默默运行,即使退出应用服务依然可继续运行。

    广播接收器(Broadcast Receiver):允许你的应用接收各种广播消息,如电话短信等,你的应用也可以发出广播消息。

    内容提供器(Content Provider):为应用程序间共享数据提供支持,如读取电话簿中联系人

  2. 丰富的系统控件

搭建界面的基础单元,也可自定义

  1. SQLite数据库

轻量级、运算速度极快的嵌入式关系型数据库

  1. 强大的多媒体

Android系统提供了API以访问多媒体服务,如:音乐、视频、录音、拍照、闹钟等

  1. 地理位置定位

Android手机都内置有GPS,结合地图功能,LBS领域潜力无限

1.2 手把手带你搭建开发环境

现在都是用Android Studio开发,使用Mac搭建环境会遇到以下两个问题:

  1. 官网下载最新安装包:developer.android.com/studio
  2. 会遇到以下问题:
  • Unable to access Android SDK add-on list

    解决方法:在 Android Studio 安装目录 bin/idea.properties 文件最后追加一句:disable.android.first.run=true

  • Your Android SDK is missing, out of date or corrupted

    解决方法:blog.csdn.net/qq_24118527…

  • studio Connection refused (Connection refused)

    解决方法:www.jianshu.com/p/dc12c965a… 我的配置当时删除了: systemProp.http.proxyHost=127.0.0.1 systemProp.https.proxyPort=8118 systemProp.https.proxyHost=127.0.0.1 systemProp.http.proxyPort=8118

1.3 创建第一个 Android 项目

比较简单,一步步操作即可。主要关注创建后的项目是怎么运行起来的。

  1. 先看 AndroidManifest.xml 文件,可看到如下代码
<activity android:name=".HelloWorldActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

这段配置,表示对 HelloWorldActivity 这个活动进行注册,没有在该配置文件里注册的活动是不能使用的。

intent-filter 中的两个配置分别 xxx.MAIN 和 xxx.LAUNCHER 表示该活动是这个项目的主活动,点击 APP 图标,首先启动的就是这个活动。

  1. 既然 HelloWorldActivity 是主活动,我们看一下它的代码
public class HelloWorldActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.hello_world_layout);
    }

} 

介绍四大组件的时候讲过,活动是App的门面,凡是所见的皆是在活动中。我们启动该项目后在手机中看到的界面,其实就是在 HelloWorldActivity 活动中的。

代码中可看到 HelloWorldActivity 继承自 AppCompatActivity,Compat 有兼容之意 AppCompatActivity 是一种向下兼容的 Activity ,最低支持 2.1 系统。

然后,可以看到有一个 onCreate 方法,这个方法是一个活动被创建时要执行的。Android 程序设计讲究视图和逻辑分离,因此不推荐在 Activity 中直接写界面。通用的方式如代码所示通过 setContentView(),传入一个 layout 即可。 layout 有布局、设计之意,它既包含视图元素也包含布局信息。

  1. 接下来看一下 hello_world_layout.xml 这个 Layout 文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/hello_world_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.helloworld.HelloWorldActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" 
    />
        
</RelativeLayout>

这个文件在 res/layout 目录中,在这里可以看到界面展示的 HelloWorld!字样是在 TextView 控件中配置的。

1.3.5 项目中的核心资源解读

  1. res 中的目录资源

res/values/strings 用以配置项目中使用的字符串资源信息

<resources>
    <string name="app_name">HelloWorld</string>
</resources>

使用场景有两种:

  • 代码中:R.string.app_name 可获得该字符串引用
  • XML中 :@string/app_name

string 部分是可替换的,如果要使用图片资源换成 drawable,图标就用 mipmap,布局文件是layout。

看一下 AndroidManifest.xml 文件,主要关注对资源的访问方式

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    ...
</application> 

1.3.6 详解 build.gradle 文件

Android Studio 是采用 Gradle 来创建项目的。Gradle是一个非常先进的项目构建工具,使用了一种基于 Groovy 的领域特定语言(DSL)来声明项目设置,摒弃了传统的基于 XML (如 Ant 和 Maven)的各种琐碎配置。

HelloWorld 项目中有两个 build.gradle 文件,一个是在最外层目录下,一个是在 app 目录下。两个文件都很重要,需要认真掌握

  1. 最外层目录下的 build.gradle 文件 代码如下:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

首先,看一下 jcenter,它是一个代码托管仓库,很多开源项目会托管在 jcenter 上,声明了 jcenter() 后就可以在项目中轻松引用任何 jcenter 上的开源项目了。

然后,classpath 声明了一个 Gradle 插件。之所以声明该插件,是因为 Gradle 并非只为构建 Android 项目而开发,java、c++ 等很多项目都可使用 Gradle 来构建。

  1. app 目录下的 build.gradle 文件

代码如下:


apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.example.helloworld"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1”
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
}”

首先,看第一行 apply plugin 配置,该插件配置有两种值可选:

  1. com.android.application

    表示是一个应用程序模块,可运行

  2. com.android.library

    表示是一个库模块,不可运行只能作为代码库依附于某个应用程序模块来运行

接下来,是 Android 的闭包,该闭包中可配置项目构建的各种属性。

  1. compileSdkVersion 用以指定项目的编译版本,24 表示使用 Android 7.0 系统的 SDK 编译。

  2. buildToolsVersion 用于支付那个项目构建工具的版本

  3. defaultConfig 闭包,可对项目更多细节进行配置:

    applicationId 用于指定项目的包名

    minSdkVersion 用于指定项目兼容的最低 Android 系统版本

    targetSdkVersion 用于指定充分测试过的系统版本,高于该系统版本引入的新功能不会启用。

    versionCode 用于指定版本号

    versionName 用于指定版本名

  4. buildTypes 闭包, 用于指定生成安装文件的相关配置,通常只会有两个子闭包:

    1. debug 闭包,指定生成测试版安装文件的配置

      该闭包,可忽略不写

    2. release 闭包,指定生成正式版安装文件的配置

      minifyEnabled 用于指定是否对项目代码进行混淆 proguardFiles 用于指定混淆使用的规则文件。proguard-android.txt 是在 Android SDK 目录下,是所有项目的通用混淆规则。proguard-rules.pro 是在当前项目的根目录下,可编写当前项目的混淆规则。

最后,还剩下一个 dependencies 闭包,它用于指定当前项目的所有依赖关系,通常 Android Studio 项目有以下3种依赖方式:

  1. 本地依赖

    可对本地的 jar 包或目录添加依赖关系,第一行的 compile fileTree 就是一个本地依赖声明,表示将 libs 目录下所有的 .jar 后缀的文件都添加到项目的构建路径中。

  2. 库依赖

    可对项目中的库模块添加依赖关系

  3. 远程依赖

    可对 jcenter 库上的开源项目添加依赖关系,第二行的 compile 是远程依赖声明,com.android.support:appcompat-v7:24.2.1 是一个标准的远程依赖库格式,其中com.android.support 是域名部分,用于和其它公司的库作区分;appcompat-v7 是组名称,用于和同一个公司中不同的库做区分;24.2.1 是版本号,用于和同一个库的不同版本作区分。

testCompile 用于声明测试用例库,暂时忽略。

1.4 前行必备-掌握日志工具的使用

Log 工具类的五个重载方法:

  1. Log.v() 对应 verbose 级别,级别最低,用于打印最为琐碎、意义最小的日志信息
  2. Log.d() 对应 debug 级别,比 verbose 高一级,用于打印调试信息
  3. Log.i() 对应 info 级别,比 debug 高一级,用于打印一些比较重要的数据,这些数据是你非常想看到的、可以帮你分析用户行为的数据
  4. Log.w() 对应 warn 级别,比 info 高一级,用于打印一些警告信息,这些警告提示程序在某个地方会有潜在风险,最好去修复一些这些出现警告的地方
  5. Log.e() 对应 error 级别,比 warn 高一级,用于打印程序中的错误信息,比如程序进度到了 catch 语句中。当有 error 信息打印的时候,一般代表程序出现了严重问题,必须尽快修复

用法举例如下

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.hello_world_layout);
    Log.d("HelloWorldActivity", "onCreate execute");
}

相关快捷键

  1. 方法中输入 logd ,按下 Tab 健,会补全一条完整打印语句,以此类推logi、loge、logw等均可
  2. Log的所有打印要求传入一个 tag 参数,可在方法外输入 logt,按下 Tab 健,这是会自动生成一个 Tag 常量,如下所示
public class HelloWorldActivity extends AppCompatActivity {

    private static final String TAG = "HelloWorldActivity";

    ...
}

小结

在iOS开发中,首先要解决项目目录结构问题,日志的分级上报也需要自己开发,这些在 Android 开发中不需要考虑的,平台已经提供了合理的目录分组和便捷的日志系统。另外,视图分离问题 Android 也提供了优秀的 layout 设计,这种设计清晰且便于开发者使用。