Android
1 | 选择30分 填空15分 简答 30分 综合25分 |
选择填空
Activity的相关知识
- Activity直接或间接继承了Context、ContextWrapper、ContextThemeWrapper等基类。
- 在使用Activity时,需要开发者继承Activity基类。在不同的应用场景下,可以选择继承Activity的子类。
- 例如界面中只包括列表,则可以继承ListActivity;若界面需要实现标签页效果,则要继承TabActivity。
- 当一个Activity类被定义之后,这个Activity类何时被实例化,它所包含的方法何时被调用,都是由Android系统决定的。开发者只负责实现相应的方法创建出需要的Activity即可。
- 创建一个Activity需要实现一个或多个方法,其中最基本的方法是onCreate(Bundle status)方法,它将会在Activity被创建时回调,然后通过setContentView(View view)方法显示要展示的布局文件。
常见的手机操作系统
手机操作系统主要应用在智能手机上。主流的智能手机有Google Android和苹果的iOS等。智能手机与非智能手机都支持JAVA,智能机与非智能机的区别主要看能否基于系统平台的功能扩展。
目前应用在手机上的操作系统主要有Android(谷歌)、iOS(苹果)、[windows phone](https://baike.baidu.com/item/windows phone/9227600)(微软)、Symbian(诺基亚)、BlackBerry OS(黑莓)、web os、[windows mobile](https://baike.baidu.com/item/windows mobile/749381)(微软)、Harmony(鸿蒙)等。
常见组件:图片、文本框、进度条等
- 初次看到ImageView很容易让大家觉得这是一个显示图片的View,这种说法没错,但是不全面,因为它能显示Drawable中的所有对象。如图所示,ImageView派生了ImageButton、QuickContactBadge等组件。详细
- TextView直接继承了View,并且它还是EditText和Button两个UI组件的父类,TextView类图如图所示。TextView的作用就是在界面上显示文本,只是Android关闭了它的文字编辑功能(EditText有编辑功能)。详细
- 在实际开发中,ProgressBar也是经常用到的进度条组件,它派生了两个常用的子类组件:SeekBar与RatingBar。Progress及其子类在用法上很相似,只是显示界面有一定的区别。它们的继承关系如图所示:详细
图片资源的引用
图中,drawable文件夹中存放各种位图文件,包括*.png、*.png、*.jpg、*.gif
等,还包括一些XML文件;layout文件夹中存放各种用户界面的布局文件;menu文件夹中存放应用程序定义各种菜单的资源;mipmap文件夹中存放图片资源,按照同一种图片不同的分辨率存放在不同的mipmap文件夹下(这样做是为了让系统根据不同的屏幕分辨率选择相应的图片);values文件夹中存放各种简单值的XML文件,包括字符串值、整数值、颜色值、数组等。
Res下各类资源
资源的存储方式主要针对在res目录下的资源,使用不同的子目录来保存不同的应用资源。当新建一个Android项目时,Android Studio在res目录下自动生成几个子目录,如图所示。
图中,drawable文件夹中存放各种位图文件,包括*.png、*.png、*.jpg、*.gif
等,还包括一些XML文件;layout文件夹中存放各种用户界面的布局文件;menu文件夹中存放应用程序定义各种菜单的资源;mipmap文件夹中存放图片资源,按照同一种图片不同的分辨率存放在不同的mipmap文件夹下(这样做是为了让系统根据不同的屏幕分辨率选择相应的图片);values文件夹中存放各种简单值的XML文件,包括字符串值、整数值、颜色值、数组等。
但在实际开发中,这些自动生成的文件夹有时候并不能满足需求,比如要使用动画效果时,需要定义属性动画或者补间动画的XML文件,此时就需要在res目录下新建两个文件夹,分别命名为anim和animator,其中anim目录用于放置补间动画的XML文件,animator目录用于放置属性动画的XML文件。另外,如果一个RadioButton按钮在不同状态下其对应的文字颜色也不同,此时就需要定义一个XML文件用于其颜色变化的设置与选择,而在res目录中就需要新建命名为“color”的子目录,用于放置该XML文件。
常见布局
- LinearLayout(线性布局)、FrameLayout(帧布局)、RelativeLayout(相对布局)、AbsoluteLayout(绝对布局)、TableLayout(表格布局)、GridLayout(网格布局)六大基本布局以及它们常用的属性,并且结合不同布局的各自特点给出自身特有的属性(重复的属性不会列出)。这六大基本布局与View类的关系如图所示。
Intent含义及作用
这两个并不是Android应用的组件,但它对Android应用的作用非常大——它是Android应用内不同组件之间通信的载体。当一个Android应用内需要有不同组件之间的跳转,例如一个Activity跳转到另一个Activity,或者Activity跳转到Service时,甚至发送和接收广播时,都需要用到Intent。 Intent封装了大量关于目标组件的信息,可以利用它启动Activity、Service或者BroadcastReceiver。一般称Intent为“意图”,意图可以分为两类: (1)显式Intent:明确指定需要启动或者触发的组件的类名。 (2)隐式Intent:指定需要启动或者触发的组件应满足怎样的条件。
对于显式Intent,Android系统无须对该Intent做出任何解析,系统直接找到指定的目标组件,启动或者触发它即可。 而对于隐式Intent,Android需要解析出它的条件,然后再在系统中查找与之匹配的目标组件。若找到符合条件的组件,就启动或触发它们。 那么Android系统如何判断是隐式Intent还是显示Intent呢?就是通过IntentFilter来实现的。被调用的组件通过IntentFilter声明自己满足的隐式条件,使系统可以拿来判断是否启动这个组件。关于这个知识点的详细内容,在后面的内容中会详细介绍。
Activity、Service和BroadcastReceiver都是通过Intent启动,并且可以通过Intent传递数据。下表列出了使用Intent启动不同组件的方法。
- 关于Service与BroadcastReceiver的启动,在后面的章节中会详细讲解。这里只介绍Intent的相关内容。Intent包含的属性主要包括Component、Action、Category、Data、Type、Extra和Flag这7种属性。其中Extra属性在前面的很多示例中都有涉及,就不做介绍了。接下来详细介绍剩余6个属性的作用,以及使用示例。
事件的实现方法
Android事件处理
- 基于监听的事件处理
- 基于回调的事件处理
- 响应系统设置的事件
- Handler消息传递机制
数据库操纵语言的命令
使用SQL语句操作SQLite数据库
- SQLiteDatabase的execSQL方法可执行任意SQL语句,包括带占位符的SQL语句。但由于该方法没有返回值,因此一般用于执行DDL(data definition language)语句或DML(data manipulation language)语句;如果需要执行査询语句,则可调用SQLiteDatabase的rawQuery(String sql, String[] selectionArgs)方法。
使用特定方法操作SQLite数据库
考虑到可能有开发者对SQL语法不熟悉,SQLiteDatabase提供了insert、update、delete以及query语句来操作数据库。
- 1.使用insert方法插入记录
SQLiteDatabase中的insert方法包括3个参数,具体方法为insert(String table, String nullColumnHack, ContentValues values),其中table为插入数据的表名,nullColumnHack是指强行插入null值的数据列的列名,当values参数为null时该参数有效,values代表一行记录的数据。
insert()方法中的第三个参数values代表插入一行记录的数据,该参数类型为ContentValues,ContentValues类似于Map,提供了put(String key, Xxx values)方法用于存入数据,getAsXxx(String key)方法用于取出数据。
具体示例代码片段如下:
不管values参数是否包含数据,执行insert()方法总会添加一条记录,如果values为空,则会添加一条除主键之外其他字段值都为null的记录。
另外还需要注意的是insert()方法返回类型为long。
- 2.使用update方法更新记录
SQLiteDatabase中的update()方法包含4个参数,具体方法为update(String table, ContentValues values, String whereClause, String[] whereArgs),其中table为更新数据的表名,values为要更新的数据,whereClause 是指更新数据的条件,whereArgs为whereClause子句传入参数。update()方法返回int型数据,表示修改数据的条数。
修改person_inf表中所有主键大于15的人的姓名和地址,示例代码如下:
上面示例代码可更直观的看出,第四个参数whereArgs用于向第三个参数whereClause中传入参数。
- 3.使用delete方法删除记录
SQLiteDatabase中的delete()方法包含3个参数,具体方法为delete(String table, String whereClause, String[] whereArgs),其中table是要删除数据的表名,whereClause是删除数据时的要满足的条件,whereArgs用于为whereClause传入参数。
删除person_inf表中所有姓名以“小”开头的记录,示例代码如下:
- 4.使用query方法查询记录
SQLiteDatabase中的query()方法包含9个参数,具体方法为query(boolean distinct, String table, String[] columns, String whereClause, String[] selectionArgs, String groupBy, String having, String orderBy, String limit),参数说明如下。
distinct:指定是否去除重复记录。
table:执行查询数据的表名。
columns:要查询出来的列名,相当于select语句select关键字后面的部分。
whereClause:查询条件子句,相当于select语句中where关键字后面的部分,在条件子句中允许使用占位符“?”。
selectionArgs:用于为whereClause子句中的占位符传入参数值,值在数组中的位置与占位符在语句中的位置必须一致;否则会出现异常。
groupBy:用于控制分组,相当于select语句group by关键字后面的部分。
having:用于对分组进行过滤,相当于select语句having关键字后面的部分。
orderBy:用于对记录进行排序,相当于select语句order by关键字后面的部分。
limit:用于进行分页。
该方法中参数较多,大家使用时如果不清楚各个参数的意义,可根据API查询。下面通过示例代码片段展示query()方法的使用,查询person_inf表中人名以“小”开头的记录。
query()方法返回的是Cursor类型对象。
Toast常用方法
1 | Toast.makeText(context, text, duration); //返回值为Toast |
Intent启动Activity方式
- 对于显式Intent,Android系统无须对该Intent做出任何解析,系统直接找到指定的目标组件,启动或者触发它即可。 而对于隐式Intent,Android需要解析出它的条件,然后再在系统中查找与之匹配的目标组件。若找到符合条件的组件,就启动或触发它们。 那么Android系统如何判断是隐式Intent还是显示Intent呢?就是通过IntentFilter来实现的。被调用的组件通过IntentFilter声明自己满足的隐式条件,使系统可以拿来判断是否启动这个组件。关于这个知识点的详细内容,在后面的内容中会详细介绍。
- Activity、Service和BroadcastReceiver都是通过Intent启动,并且可以通过Intent传递数据。下表列出了使用Intent启动不同组件的方法。
Sp数据保存方式及位置
SharedPreferences保存的数据主要是简单类型的key-value键值对。SharedPreferences是一个接口,所以程序无法直接创建SharedPreferences对象,只能通过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例。 SharedPreferences并没有提供写入数据的能力,而是通过其内部接口首先获取到Editor对象,通过Editor提供的方法向SharedPreferences写入数据。Editor提供的方法如表所示。
SharedPreferences接口主要负责读取应用程序中的Preference数据,提供了如表所示方法访问key-value键值对。
下面介绍SharedPreferences(以下简称SP)的简单使用。
SP的存储位置和格式
获取SP对象是通过Context提供的getSharedPreferences(String name, int mode)方法来获取,该方法中第一个参数设置保存的XML文件名,该文件用于SharedPreferences数据,第二个参数支持如表所示的几个值。
SharedPreferences数据是以key-value键值对的形式保存的。 SharedPreferences数据总是保存在/data/data//shared_prefs
目录下,SharedPreferences数据总是以XML格式保存,根元素是元素,该元素中每个子元素代表一个key-value对,当value是整数类型时,使用子元素;当value是字符串类型时,使用
子元素。
ContentProvider接口作用
ContentProvider内容提供者作为Android四大组件之一,其作用是在不同的应用程序之间实现数据共享的功能。
Fragment几种状态
- 与Activity一样,Fragment也有自己的生命周期,如图所示。
- 在上图中展示了Fragment生命周期中被回调的所有方法。
- onCreate(Bundle saveStatus):创建Fragment时被回调,该方法只会被回调一次。
- onCreateView():每次创建、绘制该Fragment的View组件时回调该方法,Fragment将会显示该方法返回的View组件。
- onActivityCreated():当Fragment所在的Activity被启动完成后回调该方法。
- onStart():启动Fragment时回调该方法。
- onResume():恢复Fragment时被回调,在onStart()方法后一定会回调该方法。
- onPause():暂停Fragment时被回调。
- onDestroyView():销毁该Fragment所包含的View组件时被回调。
- onDestroy():销毁该Fragment时被回调。
- onDetach():将该Fragment从宿主Activity中删除、替换完成时回调该方法,在onDestroy()方法后一定会回调onDetach()方法,且只会被回调一次。
- 与开发Activity时一样,开发Fragment时也是根据需要选择指定的方法进行重写,Fragment中最常被重写的方法是onCreateView()。
Handler机制中的的关键对象
- 前面提到新线程将消息发送至MessageQueue,然后Handler不断从MessageQueue中获取并处理消息。Handler从MessageQueue中读取消息就要用到Looper,Looper的loop方法负责读取MessageQueue中的消息,读取消息之后把消息发送给Handler来处理。
上图很好地展示了这三者之间的关系,可以看出,如果希望
Handler
正常工作,必须在当前线程中有一个Looper对象。而Looper的创建分为两种情况:
- (1)在主线程即UI线程中,系统已默认初始化了一个Looper对象,因此程序可直接创建Handler即可。
- (2)开发者新建的子线程中,必须自己创建一个Looper对象并启动它,才可使用Handler。创建Looper对象调用它的prepare()方法即可。
下面来分别归纳一下这三者的作用,如表所示。
在新建的线程中使用
Handler
的步骤如下:
- (1)调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,Looper的构造方法会自动创建与之匹配的MessageQueue。
- (2)Looper创建完成之后,开始创建Handler实例,并重写handleMessage()方法,该方法负责处理来自于其他线程的消息。
- (3)调用Looper的loop()方法启动Looper。
Android中有许多控件的祖先类
View组件是所有UI组件和容器控件的基类,它是App中用户能看到的部分。
- Android应用的绝大多数UI组件都是放在Android.widget包及其子包、Android.view包及其子包中。
- 值得注意的是,Android中所有的组件都是继承了View类,View组件代表一个空白的矩形区域。
- View类还有一个重要的子类ViewGroup,但ViewGoup类经常作为其他组件的容器使用。
- Android的所有UI组件都建立在View、ViewGroup基础之上,它们的组织结构如图所示。
ListView作用
- 实际开发中ListView是最常用的组件之一,ListView以垂直列表的形式显示所有列表项。其实除了利用ListView生成列表视图之外,还可以让Activity直接继承ListActivity,这里暂不提这种形式。
- 当程序中使用了ListView“容器”之后,就需要为容器中加内容,添加的内容由Adapter提供。这一点也和AdapterView很相似:通过
数据库的数据插入的方法
使用insert方法插入记录
SQLiteDatabase中的insert方法包括3个参数,具体方法为insert(String table, String nullColumnHack, ContentValues values),其中table为插入数据的表名,nullColumnHack是指强行插入null值的数据列的列名,当values参数为null时该参数有效,values代表一行记录的数据。
insert()方法中的第三个参数values代表插入一行记录的数据,该参数类型为ContentValues,ContentValues类似于Map,提供了put(String key, Xxx values)方法用于存入数据,getAsXxx(String key)方法用于取出数据。
具体示例代码片段如下:
不管values参数是否包含数据,执行insert()方法总会添加一条记录,如果values为空,则会添加一条除主键之外其他字段值都为null的记录。
另外还需要注意的是insert()方法返回类型为long。
Android文件路径及数据库存储名
4.4.2系统,带有SD卡 (真机)
存储位置 | 获取路径的方法 | 容量(写入前) | 容量(写入后) | 备注 |
---|---|---|---|---|
/data/data/packname/files | getFilesDir() | 2.22GB | 2.18GB | 内部存储 |
/storage/emulated/0/Android /data/packname/files | getExternal StorageDirectory() | 2.20GB | 2.16GB | 机身外部存储 |
/storage/sdcard1 | getExternalFilesDirs | 1.47GB | 1.47GB | 外部存储(SD卡 没有向其写数据,只是读取) |
6.0.0系统,带有SD卡 (真机)
存储位置 | 获取路径的方法 | 容量(写入前) | 容量(写入后) | 备注 |
---|---|---|---|---|
/data/user/0/packname/files | getFilesDir() | 11.94GB | 11.90GB | 内部存储 |
/storage/emulated/0/Android /data/packname/files | getExternal StorageDirectory() | 11.92GB | 11.88GB | 机身外部存储 |
/storage/B3E4-1711 | getExternalFilesDirs | 1.47GB | 1.47GB | 外部存储(SD卡) 没有向其写数据,只是读取 |
用SQLiteDatabase的静态方法即可打开或创建数据库,例如如下代码:
SQLiteDatabase.openOrCreateDataBase("/mnt/db/temp.db3",null);
上面的代码就用于打开或创建一个SQLite数据库,如果/mnt/db/目录下的temp.db3文件 (该文件就是一个数据库)存在,那么程序就是打开该数据库;如果该文件不存在,则上面的代码将会在该目录下创建temp.db3文件(即对应于数据库)。
文件打开模式
Context中提供了如下两个方法来打开应用程序的数据文件夹中文件I/O流。 FileInputStream openFileInput(String name):打开应用程序中数据文件夹下name文件对应的输入流。 FileOutputStream openFileOutput(String name, int mode):打开应用程序中数据文件夹下name文件对应的输出流。 在openFileOutput(String name, int mode)方法中,mode参数是指打开文件的模式,支持的模式值如表所示。
Android中还提供了访问应用程序的数据文件夹方法,如表所示。
Android系统的底层组成
Android系统的底层建立在Linux系统之上,该平台由操作系统、中间件、用户界面和应用软件4层组成,它采用一种被称为软件叠层(Software Stack)的方式进行构建。这种软件叠层结构使得层与层之间相互分离,明确各层的分工。这种分工保证了层与层之间的低耦合,当下层的层内或层下发生改变时,上层应用层序无需任何改变。
布局文件中组件属性设置及获取该组件方法
Android推荐使用这种方式来控制视图,因为这样不仅简单直接,而且将视图控制逻辑从Java代码中分离出来,单独在XML文件中控制,更好地体现了MVC原则。
在前面介绍项目的结构目录时,布局文件是放在
app\src\main\res\layout
文件夹下面,然后通过Java代码中setContentView()
方法在Activity中显示该视图的。在实际开发中,当遇到有很多UI组件时(实际上这种情况很常见),各个组件会通过
android:id属性
给每个组件设置一个唯一的标识。当需要在代码中访问指定的组件时(例如设置单击事件),就可以通过id值,利用方法findViewById(R.id.id值)
来访问。在设置UI组件时有两个属性值最常用:
android:layout_height
、android:layout_width
,这两个属性支持两种属性值:- (1)match_parent:指定子组件的高度和宽度与父组件的高度和宽度相同(实际还有填充的空白距离)。
- (2)wrap_content:指定组件的大小恰好能包裹它的内容。
Android机制决定了UI组件的大小不仅受它实际宽度和高度的控制,还受它所在布局的高度和宽度控制,所以在设置组件的宽高时还要考虑布局的宽高。
其实在XML文件中编写界面还有很多的属性,比如gravity、LinearLayout中的orientation、RelativeLayout中的centerInParent属性等等,这些属性在之后的内容中都会讲到。
菜单分类
Android中的菜单(menu)在桌面应用中十分广泛,几乎所有的桌面应用都会使用到。Android应用中的菜单分为三种:选项菜单( OptionMenu )、上下文菜单( ContextMenu )、弹出式菜单( PopupMenu )
事件监听实现
- Android的事件处理机制采用了一种委派式的事件处理方式:普通组件(事件源)将整个事件处理委派给特定的对象(事件监听器),当该组件发生指定的事件时,就通知所委托的事件监听器,由该事件监听器处理该事件。该流程如图所示。
- 这种委派式的处理方式很类似于人类社会的分工合作。举一个简单例子,当人们想邮寄一份快递(事件源)时,通常是将该快递交给快递点(事件监听器)来处理,再由快递点通知物流公司(事件处理器)运送快递,而快递点也会监听多个物流公司的快递,进而通知不同的物流公司。这种处理方式将事件源与事件监听器分离,从而提供更好的程序模型,有利于提高程序的可维护性。
- 基于上面程序可以总结出基于监听的事件处理模型的编程步骤:
- (1)获取要被监听的组件(事件源)。
- (2)实现事件监听器类,该类是一个特殊的Java类,必须实现一个XxxListener接口。
- (3)调用事件源的setXxxListener方法将事件监听器对象注册给事件源。
- 当用户操作应用界面,触发事件源上指定的事件时,Android会触发事件监听器,然后由该事件监听器调用指定的方法(事件处理器)来处理事件。 实际上,对于上述三个步骤,最关键的步骤是实现事件监听器类。实现事件监听器其实就是实现了特定接口的Java类实例,在程序中实现事件监听器,通常有如下几种形式。
- 内部类形式:将事件监听器类定义成当前类的内部类。
- 外部类形式:将事件监听器类定义成一个外部类。
- Activity本身作为事件监听器类:让Activity本身实现监听器接口,并实现事件处理方法。
- 匿名内部类形式:使用匿名内部类创建事件监听器对象。
四大组件及其启动方式
Android基本组件包括Activity、Service、BroadcastReceiver、ContentProvider等组件,
- 配置Activity时的属性lanuchMode——启动模式。该属性支持4种属性值。如表所示。
例如:android:launchMode=singleTop
- Android系统以栈(Task)的形式管理应用中的Activities:先启动的Activity放在Task栈底,后启动的Activity放在Task栈顶,满足“先进后出”的原则。
- Activity的启动模式,就是负责管理Activity的启动方式、已经实例化的Activity,并控制Activity与Task之间的加载关系。
下面详细介绍Activity这4种启动模式。
- 1.standard模式
- standard模式是默认的启动模式,当一个Activity在清单文件中没有配置launchMode属性时默认就是standard模式启动。
- 在这种模式下,每次启动目标Activity时,Android总会为目标Activity创建一个新的实例,并将该实例放入当前Task栈中(还是原来的Task栈,并没有启动新的Task)。
- 2.singleTop模式
- 这种模式与standard模式很相似,不同点是:当要启动的目标Activity已经位于栈顶时,系统不会重新创建新的目标Activity实例,而是直接复用栈顶已经创建好的Activity。
- 不过要注意的是,如果要启动的目标Activity不是位于栈顶,那么系统将会重新实例化目标Activity,并将其加入Task栈中,这时singleTop模式与standard模式完全一样。
- 3.singleTask模式
- 当一个Activity采用singleTask启动模式后,整个Android应用中只有一个该Activity实例。
- 系统对它的处理方式稍显复杂,首先检查应用中是否有该Activity的实例存在,如果没有,则新建一个目标Activity实例;如果已有目标Activity存在,则会把该目标Activity置于栈顶,在其上面的Activity会全部出栈。
- 4.singleInstance模式
- 设置为 singleInstance 模式的 Activity 将独占一个任务栈task,此时可以把该Activity看作是一个应用,这个应用与其他Activity是相互独立的,它有自己的上下文Activity。
- 例如,现有以下三个Activity: Act1、Act2、Act3,其中Act2 为 singleInstance 模式。它们之间的跳转关系为: Act1 → Act2 → Act3 ,现在在Act3中按下返回键,由于Act2位于一个独立的task中,它不属于Act3的上下文activity,所以此时将直接返回到Act1。这就是singleInstance模式。
Android资源分类
Android应用资源可分为两大类:
- 第一种是无法通过R资源清单类访问的原生资源,保存在assets目录下,应用程序需要通过AssetManager以二进制流的形式读取该资源。
- 第二种是可以通过R资源清单类访问的资源,保存在res目录下,AndroidSDK会在编译该应用时自动为该类资源在R.java文件中创建索引。
Sd卡数据操作流程
在SD卡上读写文件的步骤如下:
- (1)调用Environment的getExternalStorageState()方法判断手机是否插入SD卡,并且该应用程序是否具有读写SD卡的权限。很多时候使用如下代码进行判断:
1 | Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); |
- (2)调用Environment的getExternalStorageDirectory()方法获取SD卡的文件目录。
- (3)使用FileInputStream、FileOutputStream、FileReader或FileWriter读写SD卡中的文件。
需要注意的是,读写SD卡上的数据时必须在程序的清单文件AndroidManifest.xml中添加读写SD卡的权限,具体如下所示:
简答
1. 简述Android中的四大组件及其作用
Activity是Android应用中负责与用户交互的组件,凡是在应用中看到的界面,都是在Activity中显示。
Service看作是没有View的Activity,事实上Service也没有可以设置显示View的方法。因为不用显示View,也就不需要与用户交互,故它一般在后台运行,用户是看不到它的。
BroadcastReceiver翻译过来就是广播接收器,事实上它在Android中作用也是广播。
ContentProvider是一种跨进程间通信。比如当发送短信时,需要在联系人应用中读取指定联系人的数据,这时就需要两个应用程序之间进行数据交换。而ContentProvider提供了这种数据交换的标准。
2. 简述Intent和IntentFilter的作用及Intent的分类
Intent并不是Android应用的组件,但它对Android应用的作用非常大,它是Android应用内不同组件之间通信的载体。当一个Android应用内需要有不同组件之间的跳转,例如一个Activity跳转到另一个Activity,或者Activity跳转到Service时,甚至发送和接收广播时,都需要用到Intent。
Intent可以分为两类:
(1)显式Intent
(2)隐式Intent
Intent的概念:Intent主要的作用是方便各个应用组件之间的通信,它主要有三个基本的应用场合:①启动一个Activity②启动一个Service③发送一个广播(broadcast)
隐式Intent的使用机制:需要Android解析,通过解析,将Intent映射给可以处理该Intent的Activity,Service等。Intent的解析机制主要是通过查找已经注册在AndroidManifest.xml中的所有IntentFilter以及其中定义的Intent,最终找到匹配的Intent。
隐式Intent与显式Intent的区别:显式intent需要指定动作的执行对象,即执行某个动作的应用组件(Activity或Service)的组件名称;隐式intent通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间。
3. 简述Android 的UI组件实现原理及自定义View时使用的重要方法。
View组件在布局中是一个矩形的空白区域,没有任何内容。而UI组件之所以有内容,是因为继承了View组件之后在其提供的空白区域上重新绘制外观。这就是Android 的UI组件实现原理。
自定义View时,有三个方法很重要,分别是onMeasure()、onLayout()和onDraw()方法。
4. 简单介绍常见的布局管理器(说出5种即可)。
- LinearLayout(线性布局)
- 按照垂直或者水平方向布局的组件。
- FrameLayout(帧布局)
- 组件从屏幕左上方布局组件。帧布局是从屏幕的左上角(0,0)坐标开始布局,多个组件层叠排列,第一个添加的组件放到最底层,最后添加到框架中的视图显示在最上面。上一层的会覆盖下一层的控件。
- RelativeLayout(相对布局)
- 相对其它组件的布局方式,相对布局是按照组件之间的相对位置来布局,比如在某个组件的左边,右边,上面和下面等。
- AbsoluteLayout(绝对布局)
- 按照绝对坐标来布局组件,绝对布局通过指定子组件的确切X,Y坐标来确定组件的位置,在Android2.0 API文档中标明该类已经过期,可以使用FrameLayout或者RelativeLayout来代替。
- TableLayout(表格布局)
- 按照行列方式布局组件,表格布局是一个ViewGroup以表格显示它的子视图(view)元素,即行和列标识一个视图的位置。
- GridLayout(网格布局)
5. 简述使用PopupMenu的步骤。
(1)调用new PopupMenu(Context context, View anchor)创建下拉菜单,anchor代表要激发弹出菜单的组件。
(2)调用MenuInflater的inflate()方法将菜单资源填充到PopupMenu中。
(3)调用PopupMenu的show()方法显示弹出式菜单。
6. 简述事件监听的处理模型及Android的事件处理机制。
当用户在程序界面操作时,会激发一个相应的事件,该事件就会触犯事件源上注册事件监听器,事件监听器再调用对应的事件处理器做出相应的反应。
Android的事件处理机制采用了一种委派式的事件处理方式:普通组件(事件源)将整个事件处理委派给特定的对象(事件监听器),当该组件发生指定的事件时,就通知所委托的事件监听器,由该事件监听器处理该事件。
7. 简述基于监听的事件处理模型的编程步骤。
(1)获取要被监听的组件(事件源)。
(2)实现事件监听器类,该类是一个特殊的Java类,必须实现一个XxxListener接口。
(3)调用事件源的setXxxListener方法将事件监听器对象注册给事件源。
8. 简述在程序中实现事件监听器时通常采用的形式。
外部类形式:将事件监听器类定义成一个外部类。
内部类形式:将事件监听器类定义成当前类的内部类。
Activity本身作为事件监听器类:让Activity本身实现监听器接口,并实现事件处理方法。
匿名内部类形式:使用匿名内部类创建事件监听器对象。
9. 比较基于回调机制和基于监听机制的事件处理的特点。
- 基于监听的事件处理模型比较有优势:
- 分工明确,事件源与事件监听器分来实现,可维护性较好。
- 优先被触发。
- 基于监听机制的事件处理
- 但在某些特定情况下,基于回调的事件处理机制能更好地提高程序的内聚性。
- 基于回调的事件处理更适合解决事件处理逻辑比较固定的View
10. 简述Handler、Loop及MessageQueue三者的关系。
类 | 作用 |
---|---|
Looper | 每个线程只有一个Looper,负责管理MessageQueue,并不断从MessageQueue中取出消息分发给对应的Handler处理 |
MessageQueue | 消息队列,采用先进先出的方式管理Message |
Handler | 发送消息给MessageQueue,接受从Looper发来的消息并处理 |
11. 简述Activity的生命周期的各种状态。
- (1)运行状态:当前Activity位于前台,用户可见,可以获取焦点。
- (2)暂停状态:其他Activity位于前台,该Activity依然可见,只是不能获取焦点。
- (3)停止状态:该Activity不可见,失去焦点。
- (4)销毁状态:该Activity结束,或所在的进程结束。
Activity是在Android应用内用于呈现一个作为用户界面的屏幕显示。
生命周期:Activity是由Activity栈进管理,当来到一个新的Activity后,此Activity将被加入到Activity栈顶,之前的Activity位于此Activity底部。Activity一般意义上有四种状态:
①当Activity位于栈顶时,此时正好处于屏幕最前方,此时处于运行状态(running或active);
②当Activity失去了焦点但仍然对用于可见,此时处于暂停状态(paused);
③当Activity被其他Activity完全遮挡,此时此Activity对用户不可见,此时处于停止状态(stop);
④当Activity由于人为或系统原因(如低内存等)被销毁,此时处于销毁状态(finish);
12. 简述Activity的4种启动模式
standard模式,是默认的启动模式,当一个Activity在清单文件中没有配置launchMode属性时默认就是standard模式启动。
singleTop模式,当要启动的目标Activity已经位于栈顶时,系统不会重新创建新的目标Activity实例,而是直接复用栈顶已经创建好的Activity。
singleTask模式,当一个Activity采用singleTask启动模式后,整个Android应用中只有一个该Activity实例。
singleInstance模式,Activity 将独占一个任务栈task,此时可以把该Activity看作是一个应用,这个应用与其他Activity是相互独立的,它有自己的上下文Activity。
13. 简述Fragment与Activity关系。
Fragment是依赖于Activity的,不能独立存在的。
一个Activity里可以有多个Fragment。
一个Fragment可以被多个Activity重用。
Fragment有自己的生命周期,并能接收输入事件。
能在Activity运行时动态地添加或删除Fragment。
14. 简述Android Studio在res目录下自动生成的子目录及存放的内容。
drawable文件夹中存放各种位图文件,包括
*.png、*.png、*.jpg、*.gif
等,还包括一些XML
文件;layout文件夹中存放各种用户界面的布局文件;
menu文件夹中存放应用程序定义各种菜单的资源;
mipmap文件夹中存放图片资源,按照同一种图片不同的分辨率存放在不同的文件夹下;
values文件夹中存放各种简单值的XML文件,包括字符串值、整数值、颜色值、数组等。
15. 简述Android中颜色值的定义及常见的4种颜色值表示形式。
Android中的颜色值是通过红(Red)、绿(Green)、蓝(Blue)三原色以及一个透明度(Alpha)值来表示的,以
#
开头,后面拼接Alpha-Red-Green-Blue的形式。若Alpha值省略代表该色值完全不透明。Android颜色值支持常见的4种形式:
#RGB
、#ARGB
、#RRGGBB
、#AARRGGBB
,- 其中A、R、G、B都代表一个十六进制的数,A代表透明度,R代表红色数值,G代表绿色数值,B代表蓝色数值。
16. 在Java代码中引用R资源清单类中的图片资源的几种格式。
- 在Java代码中引用该图片资源,引用格式如下:
R.drawable.<image_name>
- 在XML中引用格式如下:
@drawable/<image_name>
- 在程序中获取实际的图片资源,Resources提供了
Drawable getDrawable(int id)
方法
17. 定义补间动画的XML资源文件根元素取值情况及其含义。
alpha:设置透明度的改变。
scale:设置图片进行缩放变换。
translate:设置图片进行位移变化。
rotate:设置图片进行旋转。
18. 简述样式资源和主题资源的区别
样式资源是指在Android应用中为某个组件设置样式时,该样式所包含的全部格式将会应用于该组件,一个样式相当于多个格式的合集,其他UI组件通过style属性来指定样式。
主题资源的XML文件通常也放在
/res/values
目录下,主题同样使用<style... />
元素来定义主题。两者在使用的场所上有所区别,主题是在清单文件中使用,样式是在布局文件中使用,具体如下:
- (1) 主题不能作用于单个的View组件,主题应该对整个应用中的所有Activity起作用,或对指定的Activity起作用。
- (2) 主题定义的格式应该是改变窗口的外观的格式,例如窗口标题,窗口边框等。
19. 简述Canvas绘图的三个基本要素及含义。
Canvas绘图有三个基本要素:
Canvas、绘图坐标系以及Paint。
Canvas是画布,通过Canvas的各种drawXxx方法将图形绘制到Canvas上面,在drawXxx方法中需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint。drawXxx方法以及传入其中的坐标决定了要绘制的图形的形状。
20. 简述使用Matrix控制图形或组件变换的步骤。
获取Matrix对象;
调用Matrix的方法进行相应变换;
将程序对Matrix所做的变换应用到指定图形或组件
21. 简述使用ValueAnimator创建动画的步骤。
(1)调用ValueAnimator的ofInt()、ofFloat()或ofObject()静态方法创建ValueAnimator实例。
(2)调用ValueAnimator的setXxx()方法设置动画属性:如持续时间、插值方式、重复次数等。
(3)调用ValueAnimator的start()方法启动动画。
(4)为ValueAnimator注册AnimatorUpdateListener监听器,在该监听器中可以监听ValueAnimator计算出来的值的改变,并将这些值应用到指定对象上。
22. 使用属性动画的步骤
(1)创建ValueAnimator或ObjectAnimator对象。
(2)根据需要为Animator对象设置属性。
(3)如果需要监听Animator的动画开始事件、动画结束事件、动画重复事件、动画值改变事件,并根据事件提供相应的处理代码,则应该为Animator对象设置事件监听器。
(4)如果有多个动画需要按次序或同时播放,则需要使用AnimatorSet组合这些动画。
(5)调用Animator对象的start()方法启动动画。
23*.Service的概念与类别,两种类别Service的区别
服务(Service)是可以在后台执行长期操作的应用组件,它没有用户界面。
类别:启动型服务(Started) 和 绑定型服务(Bound);
区别:
当应用组件(如一个活动)通过调用startService()方法启动服务时,这个服务就是启动型服务。一旦服务被启动,即使启动它的组件被销毁,服务也会一直在后台运行。通常启动型服务执行单一的操作,并且不会向启动它的组件返回结果。
当应用组件通过调用bindService()方法与服务绑定时,这个服务就是绑定型服务。绑定型服务提供一个客户端-服务端的接口,通过这个接口应用组件可以与服务交互,发送请求,接收返回结果,甚至用IPC在进程间完成这些操作。
24*.普通广播与有序广播的区别
普通广播:通过Context.sendBroadcast()方法来发送,它是完全异步的。
所有的receivers(接收器)的执行顺序不确定,因此所有的receivers(接收器)接收broadcast的顺序不确定。这种方式效率更高,但是BroadcastReceiver无法使用setResult系列、getResult系列及abort(中止)系列API。
有序广播:是通过Context.sendOrderedBroadcast来发送,所有的receiver依次执行。
从优先级别最高的广播接收器开始接收,接收完了如果没有丢弃,就下传给下一个次高优先级别的广播接收器进行处理,依次类推,直到最后。如果多个应用程序设置的优先级别相同,则谁先注册的广播,谁就可以优先接收到广播。
25*.简要描述Android项目的基本结构
一个android项目的包括两大部分,
第一部分是app目录,里面包括manifests目录、java目录以及res目录
其中,manifests中存放了AndroidManifest.xml文件,它是Android程序的全局配置文件,位于应用程序的根目录下,描述了package中的全局数据,包括package中暴露的组件,以及他们各自的实现类,各种能被处理的数据和启动位置等重要信息。
java目录是编写和存放java源代码的地方。
res目录,这个目录是安卓应用使用到的所有资源和布局的存放地点。
另一部分是Gradle Scripts:它是一个批处理框架,也可以认为是任务框架。它的作用就是把工程常用的操作编写成可重复执行脚本程序,然后在需要的时候可以方便的执行和调用。
综合题
自定义组件的使用
https://zlogs.net/note/learn-android/page/1005.html
Activity的显示启动与隐式启动,两个Activity之间切换,例5-2
https://zlogs.net/note/learn-android/page/1007.html
使用Bundle在Activity之间交换数据5.1.4
https://zlogs.net/note/learn-android/page/1017.html
事件处理:4.1
https://zlogs.net/note/learn-android/page/1012.html
Xml文件的解析 7.5.2
https://zlogs.net/note/learn-android/page/1015.html
图片的显示、绘图 8-1、8-2、8-4
https://zlogs.net/note/learn-android/page/1013.html
逐帧动画、补间动画的定义和使用8.4,8.5
https://zlogs.net/note/learn-android/page/1013.html
Sp的使用
https://zlogs.net/note/learn-android/page/1020.html
读写sd卡文件
https://zlogs.net/note/learn-android/page/1016.html