20172327 2017-2018-2 《第一行代码Android》第一章学习总结

学号 2017-2018-2 《第一行代码Android》第一章学习总结

教材学习内容总结

- Android系统架构:


1.Linux内核层

Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动,如显示驱动,音频驱动,照相机驱动,蓝牙驱动,Wi-Fi驱动,电源管理等。

2.系统运行底层

- 通过一些C/C++库来为Android系统提供了主要的特性支持

库名 功能
SQLite库 提供数据库的支持
OpenGL/ES库 提供3D绘图支持
Webkit库 提供了浏览器内核的支持


- Android运行时库(主要提供一些核心库,允许开发者使用Java语言来编写Android应用。)
Dalvik虚拟机(5.0系统后改为ART运行环境) 使每个Android应用都能运行在独立进程当中,并拥有一个自己的Dalvik虚拟机实例。

3.应用框架层

主要提供了构建应用程序时可能用到的各种API,Android自带的核心应用就是使用这些API完成的,开发者也可以用这些API来构建自己的应用程序。

4.应用层

应用程序都是属于这一层,联系人,短信,游戏等都是。
20172327 2017-2018-2 《第一行代码Android》第一章学习总结


总结:

  • 1 Android的系统架构采用分层架构的思想,架构清晰,层次分明,协同工作。
  • 2 Android的系统架构不仅从宏观上认识了Android系统,同时,也给我们的学习与实践指明了方向。若是从事Android应用开发,那应该研究Android的应用框架层和应用程序层;若是从事Android系统开发,那应该研究Android的系统库和Android运行时;若是从事Android驱动开发,那应该研究Android的Linux内核。总之,找准切入点,实践出真知。
- Android应用开发特色:


1.四大组件

  • 活动(Activity)
    Android应用程序的门面,凡是你在应用中看到得东西,都是放在活动中。
  • 服务(service)
    无法看到,在后台默默运行,退出应用后,服务仍然是可以继续运行的。
  • 广播接收器(Broadcast Receiver)
    允许你的应用接收来自各处的广播消息,如电话,短信等。
  • 内容提供器(Content Provider)
    程序之间共享数据。


2.丰富的系统控件

  • Android为开发者提供了丰富的系统控件,可以使我们轻松的编写出漂亮的界面。你也可以定制自己的控件。


3.SQLite数据库

  • 轻量级,运行速度快,嵌入式,关系型数据库。支持SQL语法,还可通过Android封装好的API进行操作,让储存和读取数据更方便。


4.强大的多媒体

  • 音乐,视频,录音,拍照,闹钟等,均可通过代码控制。


5.地理位置定位

  • 地理位置定位应该是一个亮点,Android手机内置GPS,所以走到哪都可以定位到自己的位置,发挥出创意十足的应用,结合地图功能,LBS (通过电信移动运营商的无线电通讯网络(如GSM网、CDMA网)或外部定位方式(如GPS)获取移动终端用户的位置信息(地理坐标,或大地坐标),在地理信息系统(外语缩写:GIS、外语全称:Geographic Information System)平台的支持下,为用户提供相应服务的一种增值业务。)这一领域潜力无限。
- 开发环境构建工具:


1.JDK

  • JDK是Java语言的软件开发工具包,它包含了Java的运行环境,工具合集,基础类库等内容。


2.Android SDK

  • Android SDk 是谷歌提供的Android开发工具包,在开发Android程序时,我们需要通过引入该工具包,来使用Android相关的API。


3.Android Studio

  • 2013年谷歌推出的一款官方的IDE工具,不在以插件形式存在,Android Studio在开发Android程序方面远比以前用的Eclipse强大和方便的多。
- 分析Android程序:


创建完毕以后,将项目结构模式切换成Project

1.整体目录结构分析
20172327 2017-2018-2 《第一行代码Android》第一章学习总结


说明:除了APP目录外,其他目录都是自动生成的。APP目录的下的内容才是我们的工作重点。

2.APP目录结构分析
20172327 2017-2018-2 《第一行代码Android》第一章学习总结


说明:程序的默认运行效果就是不写一行代码,直接部署到模拟器上的运行效果。

3.定义主活动

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                //这两句代码表示MainActivity是主活动,点击图标后首先运行此活动
            </intent-filter>
        </activity>


说明: 这段代码表示对MainActivity活动进行注册,没有在AndroidManifest.XML中注册的活动是不能使用的。

4.主活动分析

package com.example.zy.myapplication;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {
        //活动被创建必须要调用下述的方法
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}


说明:
1.我们之前说了应用程序中所有的可以看到的东西都是放到活动中的,所以首先必须要继承自活动。
  2.主活动的继承关系:
20172327 2017-2018-2 《第一行代码Android》第一章学习总结

  3.super.onCreate(savedInstanceState)就是调用父类的onCreate构造函数,时用来创建活动的,savedInstanceState是保存当前Activity的状态信息。

5.HelloWorld来自哪?
其实在Android程序的设计讲究逻辑和视图分类,因此是不推荐在活动中直接编写界面的,更加通用的方法是在布局文件中编写界面,然后在活动中引入进来

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    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.zy.myapplication.MainActivity">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</RelativeLayout>


说明: 我们看到其中有一个TextView,这是Android的一个控件,用于在布局中显示文字的。

6.详解res目录
20172327 2017-2018-2 《第一行代码Android》第一章学习总结


说明:之所以有这么多的mipmap开头的文件夹,其实主要是为了让程序能够更好地兼容各种设备。
打开values目录下的strings.xml文件:

<resources>
    <string name="app_name">My Application</string>
</resources>

这里定义了一个应用程序名的字符串,我们可以使用以下两种方式引用它:

  • 在代码中通过: ◇ R.string.app_name
  • 在XML文件通过: ◇ @string/app_name


7.详解build.gradle
在AS中,我们是通过Gradle来构建项目的。Gradle是一个非常先进的项目构建工具,它使用了一种基于Groovy的领域特定语言(DSL)来声明项目设置,摒弃了传统基于 XML的繁琐配置。

I.最外端的build.gradle

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

allprojects {
    repositories {
        jcenter()
    }
}


说明:

  • 两处repositories中都使用了jcenter(),jcenter是一个代码托管仓库,很多Android开源项目都会选择将代码托管到jcenter上,声明了这些配置,我们就可以在项目中轻松引用任何jcenter上的开源项目了。
  • dependencies 使用了classpath 声明了一个Cradle插件。


II.APP目录下的build.gradle

apply plugin: ‘com.android.application‘

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"

    defaultConfig {
        applicationId "com.example.zy.myapplication"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }
    buildTypes { //用于指定生成安装文件的相关配置,一般有release和deubug两项。
        release {
            minifyEnabled false  //是否对代码进行混淆
            proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘ //代码的混淆规则
        }
    }
}

dependencies { //用于指定当前项目的所有依赖关系
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])
    //上着为本地依赖关系,将libs目录下*jar包添加到构建路径当中    
    testCompile ‘junit:junit:4.12‘
    //声明测试用例库的
    compile ‘com.android.support:appcompat-v7:25.2.0‘
    //这是一个标准的远程依赖库格式,Gradle在构建项目时会检查是否有此库的缓存,如果没有则联网下载.添加依赖库声明:compile project(‘:helper‘),将helper依赖关系加入.
}


说明:

  • 第一行引用了一个插件,com.android.application‘是一个应用程序模块,可以直接运行,com.android.library是一种库模块,只能作为代码库依附于别的应用程序模块来运行。
  • 接下来是一个大的Android闭包,这个闭包可以配合项目构建的各种属性。
        compileSdkVersion 25 :指定使用Android6.0系统的SDK编译。
        buildToolsVersion :指定项目构建工具的版本。
  • 接下来是一个defaultConfig闭包,可以对项目的更多细节进行配置。
        applicationId :执行项目的包名
         minSdkVersion 15 项目最低兼容的Android系统版本
         targetSdkVersion 25 你在该秒版本上做过了充分的测试,系统会为你的应用程序启动一些最新的功能和特性。
         versionCode 1 项目版本号
         versionName "1.0" 项目的版本名
- 可见性:


1.父类的私有成员也被子类继承,虽不能以成员名直接地访问这些私有成员,但可以间接地访问。

- 类间继承关系地设计:

1.软件设计中必须特别精心地研究和设计类间继承关系地参差结构。

2.final方法常用于保证该方法能在所有的子类中得到使用。final修饰符也可以作用于整个类。final类不能再用于派生新类。

教材学习中的问题和解决过程

  • 问题1:权限修饰符有哪些,分别有什么作用?
  • 问题1解决方案:


1: 什么是权限修饰符,他有什么作用,为什么需要他;

一个Java应用有很多类,但是有些类,并不希望被其他类使用。每个类中都有数据成员和方法成员,但是并不是每个数据和方法,都允许在其他类中调用。如何能做到访问控制呢?就需要使用访问权限修饰符。

1.权限修饰符就是用于控制被修饰变量、方法、类的可见范围.也就是其作用范围;


2:java中权限修饰符包括4种:

1.公共类型 public ;

2.public可以修饰类,成员变量,构造方法,方法成员。

3.被public修饰的成员,可以在任何一个类中被调用,不管同包或不同包,

4.是权限最大的一个修饰符

1.私有类型 private;
2.可以修饰成员变量,构造方法,成员方法,不能修饰类(此处指外部类,不考虑内部类)。
3.被private修饰的成员,只能在定义它们的类中使用,在其他类中不能调用。
1.默认类型 default;
2.可用于修饰类,成员变量,构造方法,方法,都能够使用默认权限,即不写任何关键字。
3.默认权限即同包权限,同包权限的元素只能在定义它们的类中,以及同包的类中被调用。
1.保护类型 protect;
2.可以修饰数据成员,构造方法,方法成员,不能修饰类(此处指外部类,不考虑内部类)。
3.被protected修饰的成员,能在定义它们的类中,同包的类中被调用。
4.如果有不同包的类想调用它们,那么这个类必须是定义它们的类的子类。

图片:


3: 关于权限修饰符还要注意几个问题;

1.并不是每个修饰符都可以修饰类(指外部类),只有public和default可以。

2.所有修饰符都可以修饰数据成员,方法成员,构造方法。

3.为了代码安全起见,修饰符不要尽量使用权限大的,而是适用即可。比如,数据成员,如果没有特殊需要,尽可能用private。加强封装性;

4.修饰符修饰的是“被访问”的权限。

  • 问题2:this和super引用有啥不同:
  • 问题2解决方案:
this

this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。 this的用法在java中大体可以分为3种:
1.普通的直接引用
这种就不用讲了,this相当于是指向当前对象本身。
2.形参与成员名字重名,用this来区分.
3.引用构造函数this(参数):
调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。
super

super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。 super也有三种用法:
1.普通的直接引用
与this类似,super相当于是指向当前对象的父类,这样就可以用super.xxx来引用父类的成员。
2.子类中的成员变量或方法与父类中的成员变量或方法同名
3.引用构造函数
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
super和this的异同:

super(参数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句)
this(参数):调用本类中另一种形成的构造函数(应该为构造函数中的第一条语句)
super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。
super()和this()均需放在构造方法内第一行。
尽管可以用this调用一个构造器,但却不能调用两个。
this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
  • 问题3:Java语言的设计者为啥明确决定不支持多继承?
  • 问题3解决方案:


James Gosling在1995年2月发表了一篇名为”Java概览”的Java白皮书,文章解释了Java不支持多重继承的原因。

Java去除了一些C++中很少用、而且被经常误解而错用的功能,如操作符的重载(operator overloading)(尽管Java仍旧保留方法的重载),多重继承(multiple inheritance),以及广泛的自动强迫同型(extensive automatic coercions)。

我想在这里分享一下James Gosling对于Java的定义。
Java: 一种简单的,面向对象的,分布式的,解释型的(译者注:Java既不是纯解释型也不是纯编译型的语言),健壮的,安全的,架构中立的,可移植的,高性能的,支持多线程的,动态语言。


看看定义的美妙之处吧。现代程序语言应该有这样的特性。我们看到,定义第一个特性是什么?是简单。


为了强化简单这个特点,这就是我们去除多重继承的原因。下面来看个例子,多重继承的菱形继承问题。

tupian


有两个类B和C继承自A。假设B和C都继承了A的方法并且进行了覆盖,编写了自己的实现。假设D通过多重继承继承了B和C,那么D应该继承B和C的重载方法,那么它应该继承哪个的呢?是B的还是C的呢?


C++中经常会掉入这个陷阱,虽然它也提出了替代的方法来解决这个问题。我们在Java中就不会出现这个问题。就算两个接口拥有同样的方法,实现的类只会有一个方法,这个方法由实现的类编写。动态的加载类会让多重继承的实现变得困难。

代码调试中的问题和解决过程

  • 问题1:在做pp9.1时,遇到到了下面这个问题
    图片115054
  • 问题1解决方案:这是我对Coin类完全没改造成的,在Coin类中,我们应该将face的修饰符改为protected。
  • 问题2:在做pp9.1时,我在测试类中选择创建一个大小为5的数组,但我定义时,只定义了三个,所以最后运行时,无法将sum值算出来。
    图片
  • 问题2解决方案:前面一个问题改一下顺序就可以,后面一个问题我又设了一个变量b,把计算过程分开才可以。

上周考试错题总结

  • 第一题:In Java, arrays are
    A .primitive data types
    B .objects
    C .interfaces
    D .primitive data types if the type stored in the array is a primitive data type and objects if the type stored in the array is an object
    E .Strings

  • 分析:在书的第245页,有说在Java中,数组是必须实例化的对象。
  • 第二题:The "off-by-one" error associated with arrays arises because
    A .the first array index is 0 and programmers may start at index 1, or may use a loop that goes one index too far
    B .the last array index is at length + 1 and loops may only iterate to length, missing one
    C .the last array element ends at length - 1 and loops may go one too far
    D .programmers write a loop that goes from 0 to length - 1 whereas the array actually goes from 1 to length
    E .none of the above, the "off-by-one" error has nothing to do with arrays
  • 分析:索引值必须大于等于0并且小于数组的元素个数。如果数组中有X个元素,则索引值是0~X-1.

  • 第三题:If an int array is passed as a parameter to a method, which of the following would adequately define the parameter list for the method header?
    A .(int[ ])
    B .(int a[ ])
    C .(int[ ] a)
    D .(int a)
    E .(a[ ])
  • 分析:参数被定义为变量最初被声明为类型参数名称。这里,类型为int[],参数为a。

  • 第四题:Assume that BankAccount is a predefined class and that the declaration BankAccount[ ] firstEmpireBank; has already been performed. Then the following instruction reserves memory space for
    firstEmpireBank = new BankAccount[1000];
    A .a reference variable to the memory that stores all 1000 BankAccount entries
    B .1000 reference variables, each of which point to a single BankAccount entry
    C .a single BankAccount entry
    D .1000 BankAccount entries
    E .1000 reference variables and 1000 BankAccount entries
  • 分析:第一次银行帐户;为firstentity银行保留内存空间,它本身是指向BankAccount[]对象的引用变量。第一次银行账户=新银行账户[1000];实例化BankAccount[]对象为1000个BankAccount对象。

  • 第五题:Given the following declarations, which of the following variables are arrays?
    int[ ] a, b;
    int c, d[ ];
    A .a
    B .a and b
    C .a and d
    uD .a, b and d
    E .a, b, c and d
  • 分析:第一个声明声明a和b都是int数组。第二个声明声明c和d是ints,但对于d,一个int数组。a b和d都是int数组。

  • 第六题If a and b are both int arrays, then a = b; will
    A .create an alias
    B .copy all elements of b into a
    C .copy the 0th element of b into the 0th element of a
    D .return true if each corresponding element of b is equal to each corresponding element of a (that is, a[0] is equal to b[0], a[1] is equal to b[1] and so forth) and return false otherwise
    E .return true if a and b are aliases and return false otherwise
  • 分析:这样使得两个数组是相同的,所以a和b所引用的数组是同一个,所以一个称为另一个的别名。

  • 第七题:A Java main method uses the parameter (String[ ] variable) so that a user can run the program and supply "command-line" parameters. Since the parameter is a String array, however, the user does not have to supply any parameters.
    A .true
    B .false
  • 分析:在java命令之后,在命令行输入的任何内容都将被接受为命令行参数。如果是由空格分隔的几个单词,那么每个单词都作为一个单独的字符串数组元素存储。

  • 第八题:An array index cannot be a float, double, boolean or String.
    A .true
    B .false
  • 分析:数组索引必须是int类型,或者可以扩展为int类型的值(因此,char、byte和short也是允许的)。

  • 第九题:An array, when instantiated, is fixed in size, but an ArrayList can dynamically change in size when new elements are added to it.
    A .true
    B .false
  • 分析:数组的一个缺点是它的固定大小。一旦实例化,它的大小是固定的。ArrayList是一个使用数组的类,它会自动创建一个更大的数组,将旧数组复制到新数组中,这样ArrayList就可以根据需要更大。虽然这可以解决抛出异常的问题,但它确实会导致性能较差,因为每次增加ArrayList大小时,必须从一个数组复制到另一个数组。

  • 第十题:Just as arrays can only have a fixed number of elements, set at the time the array is declared, a parameter list also can only have a fixed number of elements, set at the time the method is declared.
    A .true
    B .false
  • 分析:Java为可变长度参数列表提供了特殊的表示法。省略号(…)用于指定可变长度参数列表。

  • 第十一题:So long as one is only accessing the elements of an ArrayList, its efficiency is about the same as that of an array. It‘s only when one begins to insert or remove elements towards the front portion of an ArrayList that its efficiency deteriorates.
    A .true
    B .false
  • 分析:对ArrayList的前部分进行插入或删除时,就会发生大量的元素复制,从而降低其效率。

代码托管

结对及互评

点评模板:

  • 博客中值得学习的或问题:
    • xxx
    • ...
  • 基于评分标准,我给本博客打分:XX分。得分情况如下:xxx
  • 代码中值得学习的或问题:
    • xxx
    • xxx
    • ...
  • 基于评分标准,我给本博客打分:XX分。得分情况如下:xxx

  • 参考示例

点评过的同学博客和代码

  • 本周结对学习情况
    • 20172317
    • 结对照片
    • 结对学习内容
      • XXXX
      • XXXX
      • ...

其他(感悟、思考等,可选)

概念很多,嘚仔细看,有很多细节,和前面的章节联系紧密。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 95/95 1/1 18/18
第二周 515/620 1/2 22/40
第三周 290/910 1/3 20/60
第四周 1741/2651 1/4 30/84
第五周 579/3230 1/5 20/104
第六周 599/3829 1/6 18/122
第七周 732/4561 1/6 24/146

参考:软件工程软件的估计为什么这么难软件工程 估计方法

  • 计划学习时间:22小时

  • 实际学习时间:24小时

  • 改进情况:稍有点

(有空多看看现代软件工程 课件
软件工程师能力自我评价表
)

参考资料

20172327 2017-2018-2 《第一行代码Android》第一章学习总结

上一篇:Android Studio 第六十四期 - Android业务组件化之URL Scheme使用


下一篇:FL studio系列教程(十四):如何在FL Studio播放列表中排列样式