2018-04-12 Android面试题整理

一、Android 基本常识

1、写10 个简单的linux 命令

mkdir 创建文件夹

rmdir 删除文件夹

rm 删除文件

mv 移动文件

cp 拷贝文件

cat 查看文件

tail 查看文件尾部

more 分页查看文件

cd 切换当前目录

ls 列出文件清单

reboot 重启

date 显示日期

cal 显示日历

ps 查看系统进程相当于windows 的任务管理器

ifconfig 配置网络

2、书写出android 工程的目录结构

src 源文件

gen 生成的文件R 文件就在此

android. jar 依赖的android sdk

assets 资源文件

bin 生成的字节码apk 在此

libs 依赖jar 和so

res 资源文件

drawable

drawable-hdpi

layout

menu

values

AndroidManifest.xml

project.properties

3、什么是ANR 如何避免它?

在Android 上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR 给用户。不同的组件发生ANR 的时间不一样,主线程(Activity、Service)是5 秒,BroadCastReceiver 是10 秒。

解决方案:

将所有耗时操作,比如访问网络,Socket 通信,查询大量SQL 语句,复杂逻辑计算等都放在子线程中去,然后通过handler.sendMessage、runonUITread、AsyncTask 等方式更新UI。无论如何都要确保用户界面操作的流畅度。如果耗时操作需要让用户等待,那么可以在界面上显示进度条。

4、谈谈Android 的优点和不足之处

优点:

1、开放性,开源,免费,可定制

2、挣脱运营商束缚

3、丰富的硬件选择

4、不受任何限制的开发商

5、无缝结合的Google 应用

缺点:

1、安全问题、隐私问题

2、同质化严重

3、运营商对Android 手机仍然有影响

4、山寨化严重

5、过分依赖开发商,缺乏标准配置

5、一条最长的短信息约占多少byte?

在国内的三大运营商通常情况下中文70(包括标点),英文160 个。对于国外的其他运行商具体多长需要看运营商类型了。android 内部是通过如下代码进行判断具体一个短信多少byte 的。ArrayList android.telephony.SmsManager.divideMessage(String text)

7、如何判断是否有SD 卡?

通过如下方法:Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)如果返回true 就是有sdcard,如果返回false 则没有。

8、dvm 的进程和Linux 的进程, 应用程序的进程是否为同一个概念?

dvm 指dalvik 的虚拟机。每一个Android 应用程序都拥有一个独立的Dalvik 虚拟机实例,应用程序都在它自己的进程中运行。而每一个dvm 都是在Linux 中的一个进程,所以说可以近似认为是同一个概念。什么是android DVM:Dalvik 是Google 公司自己设计用于Android 平台的Java 虚拟机,每一个Dalvik 应用作为一个独立的Linux 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。

Dalvik 和Java 虚拟机的区别

1:Dalvik 主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。

2:Dalvik 负责进程隔离和线程管理,每一个Android 应用在底层都会对应一个独立的Dalvik 虚拟机实例,其代码在虚拟机的解释下得以执行。

3:不同于Java 虚拟机运行java 字节码,Dalvik 虚拟机运行的是其专有的文件格式Dex

4: dex 文件格式可以减少整体文件尺寸,提高I/O 操作的类查找速度。

5: odex 是为了在运行过程中进一步提高性能,对dex 文件的进一步优化。

6:所有的Android 应用的线程都对应一个Linux 线程,虚拟机因而可以更多的依赖操作系统的线程调度和管理机制

7:有一个特殊的虚拟机进程Zygote,他是虚拟机实例的孵化器。它在系统启动的时候就会产生,它会完成虚拟机的初始化,库的加载,预制类库和初始化的操作。如果系统需要一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统。对于一些只读的系统库,所有虚拟机实例都和Zygote 共享一块内存区域。

9、Android 程序与Java 程序的区别?

Android 程序用android sdk 开发,java 程序用javasdk 开发.

Android SDK 引用了大部分的Java SDK,少数部分被Android SDK 抛弃,比如说界面部分,java.awt swing

package 除了java.awt.font 被引用外,其他都被抛弃,在Android 平台开发中不能使用。android sdk 添加工具jar

httpclient , pull opengl

10、启动应用后,改变系统语言,应用的语言会改变么?

这个一般是不会的,一般需要重启应用才能改变应用语言。但是对应应用来说如果做了国际化处理则支持如果没有处理那系统语言再更改也是无用的。

11、请介绍下adb、ddms、aapt 的作用

adb 是Android Debug Bridge ,Android 调试桥的意思,ddms 是Dalvik Debug Monitor Service,dalvik 调试监视服务。aapt 即Android Asset Packaging Tool,在SDK 的build-tools 目录下。该工具可以查看,创建, 更新ZIP 格式的文档附件(zip, jar, apk)。也可将资源文件编译成二进制文件,尽管我们没有直接使用过该工具,但是开发工具会使用这个工具打包apk 文件构成一个Android 应用程序。Android 的主要调试工具是adb(Android debuging bridge),ddms 是一个在adb 基础上的一个图形化工具。adb,它是一个命令行工具。而ddms 功能与adb 相同,只是它有一个图形化界面。对不喜欢命今操作方式的人来说是一个不错的选择。

12、ddms 和traceview 的区别

ddms 原意是:davik debug monitor service。简单的说ddms 是一个程序执行查看器,在里面可以看见线程和堆栈等信息,traceView 是程序性能分析器。traceview 是ddms 中的一部分内容。

13、补充知识:TraceView 的使用

一、TraceView 简介

Traceview 是Android 平台特有的数据采集和分析工具,它主要用于分析Android 中应用程序的hotspot(瓶颈)。Traceview 本身只是一个数据分析工具,而数据的采集则需要使用Android SDK 中的Debug 类或者利用DDMS 工具。二者的用法如下:

开发者在一些关键代码段开始前调用Android SDK 中Debug 类的startMethodTracing 函数,并在关键代码段结束前调用stopMethodTracing 函数。这两个函数运行过程中将采集运行时间内该应用所有线程(注意,只能是Java线程)的函数执行情况,并将采集数据保存到/mnt/sdcard/下的一个文件中。开发者然后需要利用SDK 中的Traceview工具来分析这些数据。借助Android SDK 中的DDMS 工具。DDMS 可采集系统中某个正在运行的进程的函数调用信息。对开发者而言,此方法适用于没有目标应用源代码的情况。DDMS 工具中Traceview 的使用如下图所示。

14、Android 中数据存储方式有哪些?

a) 文件存储

b) xml,SharedPreference

c) SQLiteDatabase

d) ContentProvider

e) 网络

15、DVM 和JVM 的区别?

a) dvm 执行的是.dex 文件,而jvm 执行的是.class。Android 工程编译后的所有.class 字节码会被dex 工具抽取到一个.dex 文件中。

b) dvm 是基于寄存器的虚拟机而jvm 执行是基于虚拟栈的虚拟机。寄存器存取速度比栈快的多,dvm 可以根据硬件实现最大的优化,比较适合移动设备。

c) .class 文件存在很多的冗余信息,dex 工具会去除冗余信息,并把所有的.class 文件整合到.dex 文件中。减少了I/O 操作,提高了类的查找速度。

16、谈一谈Android 的安全机制

1、Android 是基于Linux 内核的,因此Linux 对文件权限的控制同样适用于Android在Android 中每个应用都有自己的/data/data/包名文件夹,该文件夹只能该应用访问,而其他应用则无权访问。

2、Android 的权限机制保护了用户的合法权益如果我们的代码想拨打电话、发送短信、访问通信录、定位、访问sdcard 等所有可能侵犯用于权益的行为都是必须要在AndroidManifest.xml 中进行声明的,这样就给了用户一个知情权。

3、Android 的代码混淆保护了开发者的劳动成果

17、Android 的四大组件都需要在清单文件中注册吗?

Activity 、Service 、ContentProvider 如果要使用则必须在AndroidManifest.xml 中进行注册, 而BroadcastReceiver 则有两种注册方式,静态注册和动态注册。其中静态注册就是指在AndroidManifest.xml 中进行注册,而动态注册时通过代码注册。

18、在Android 中进程的级别有哪些?

a) Foreground process 

b) Visible process

c) Service process

d) Background process

e) Empty process

二、Activity

1、什么是Activity?

四大组件之一,通常一个用户交互界面对应一个activity。activity 是Context 的子类,同时实现了window.callback

和keyevent.callback, 可以处理与窗体用户交互的事件。

常见的Activity 类型有FragmentActivitiy,ListActivity,TabAcitivty 等。

如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity。

2、请描述一下Activity 生命周期

Activity 从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:

onCreate --> onStart -->onResume -->onPause -->onStop -->onDestroy

其实这些方法都是两两对应的,onCreate 创建与onDestroy 销毁;

onStart 可见与onStop 不可见;onResume 可编辑(即焦点)与onPause;

这6 个方法是相对应的,那么就只剩下一个onRestart 方法了,这个方法在什么时候调用呢?

答案就是:在Activity 被onStop 后,但是没有被onDestroy,在再次启动此Activity 时就调用onRestart(而不再调用onCreate)方法;

如果被onDestroy 了,则是调用onCreate 方法。

3、Activity 的状态都有哪些?

a) foreground activity

b) visible activity

c) background activity

d) empty process

4、如何保存Activity 的状态?

Activity 的状态通常情况下系统会自动保存的,只有当我们需要保存额外的数据时才需要使用到这样的功能。一般来说, 调用onPause()和onStop()方法后的activity 实例仍然存在于内存中, activity 的所有信息和状态数据不会消失, 当activity 重新回到前台之后, 所有的改变都会得到保留。但是当系统内存不足时, 调用onPause()和onStop()方法后的activity 可能会被系统摧毁, 此时内存中就不会存有该activity 的实例对象了。如果之后这个activity 重新回到前台, 之前所作的改变就会消失。为了避免此种情况的发生,我们可以覆写onSaveInstanceState()方法。onSaveInstanceState()方法接受一个Bundle 类型的参数, 开发者可以将状态数据存储到这个Bundle 对象中, 这样即使activity 被系统摧毁, 当用户重新启动这个activity 而调用它的onCreate()方法时, 上述的Bundle 对象会作为实参传递给onCreate()方法, 开发者可以从Bundle 对象中取出保存的数据, 然后利用这些数据将activity 恢复到被摧毁之前的状态。需要注意的是, onSaveInstanceState()方法并不是一定会被调用的, 因为有些场景是不需要保存状态数据的. 比如用户按下BACK 键退出activity 时, 用户显然想要关闭这个activity, 此时是没有必要保存数据以供下次恢复的, 也就是onSaveInstanceState()方法不会被调用. 如果调用onSaveInstanceState()方法, 调用将发生在onPause()或onStop()方法之前。

@Override

protected void onSaveInstanceState(Bundle outState) {

// TODO Auto-generated method stub

super.onSaveInstanceState(outState);

}

5、两个Activity 之间跳转时必然会执行的是哪几个方法?(重要)

一般情况下比如说有两个activity,分别叫A,B,当在A 里面激活B 组件的时候, A 会调用onPause()方法,然后B 调

用onCreate() ,onStart(), onResume()。

这个时候B 覆盖了窗体, A 会调用onStop()方法. 如果B 是个透明的,或者是对话框的样式, 就不会调用A 的

onStop()方法。

如下图,打开一个MainActivity,然后点击MainActivity 中的按钮跳转到SecondActivity 的日志。


6、横竖屏切换时Activity 的生命周期

此时的生命周期跟清单文件里的配置有关系。

1、不设置Activity 的android:configChanges 时,切屏会重新调用各个生命周期默认首先销毁当前activity,然后重新加载。

如下图,当横竖屏切换时先执行onPause/onStop 方法


2、设置Activity 的android:configChanges="orientation|keyboardHidden|screenSize"时,切屏不会重新调

用各个生命周期,只会执行onConfigurationChanged 方法。

通常在游戏开发, 屏幕的朝向都是写死的。

7、如何将一个Activity 设置成窗口的样式?

只需要给我们的Activity 配置如下属性即可。

android:theme="@android:style/Theme.Dialog"

8、如何退出Activity?如何安全退出已调用多个Activity 的Application?

1、通常情况用户退出一个Activity 只需按返回键,我们写代码想退出activity 直接调用finish()方法就行。2、记录打开的Activity:每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity 即可。

//伪代码Listlists ;

// 在application 全局的变量里面

lists = new ArrayList();

lists.add(this);

for(Activity activity: lists){

activity.finish();

}

lists.remove(this);

3、发送特定广播:

在需要结束应用时,发送一个特定的广播,每个Activity 收到广播后,关闭即可。

//给某个activity 注册接受接受广播的意图

registerReceiver(receiver, filter)

//如果过接受到的是关闭activity 的广播就调用finish()方法把当前的activity finish()掉

4、递归退出

在打开新的Activity 时使用startActivityForResult,然后自己加标志,在onActivityResult 中处理,递归关闭。

5、其实也可以通过intent 的flag 来实现intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)激活

一个新的activity。此时如果该任务栈中已经有该Activity,那么系统会把这个Activity 上面的所有Activity 干掉。其

实相当于给Activity 配置的启动模式为SingleTop。


9、请描述一下Activity 的启动模式都有哪些以及各自的特点

启动模式(launchMode)在多个Activity 跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity 实例,是否重用已存在的Activity 实例,是否和其他Activity 实例公用一个task 里。这里简单介绍一下task 的概念,task 是一个具有栈结构的对象,一个task 可以管理多个Activity,启动一个应用,也就创建一个与之对应的task。Activity 一共有以下四种launchMode:

1.standard

2.singleTop

3.singleTask

4.singleInstance

我们可以在AndroidManifest.xml 配置的android:launchMode 属性为以上四种之一即可。

下面我们结合实例一一介绍这四种lanchMode:8.1 standardstandard 模式是默认的启动模式,不用为配置android:launchMode 属性即可,当然也可以指定值

为standard。

我们将创建一个Activity,命名为FirstActivity,来演示一下标准的启动模式。FirstActivity 代码如下:


FirstActivity 界面中的TextView 用于显示当前Activity 实例的序列号,Button 用于跳转到下一个FirstActivity 界面。

然后我们连续点击几次按钮,将会出现下面的现象:



我们注意到都是FirstActivity 的实例,但序列号不同,并且我们需要连续按后退键两次,才能回到第一个FirstActivity。

standard 模式的原理如下图所示:


如图所示,每次跳转系统都会在task 中生成一个新的FirstActivity 实例,并且放于栈结构的顶部,当我们按下后退键时,才能看到原来的FirstActivity 实例。

这就是standard 启动模式,不管有没有已存在的实例,都生成新的实例。

8.2 singleTop我们在上面的基础上为指定属性android:launchMode="singleTop",系统就会按照singleTop 启

动模式处理跳转行为。我们重复上面几个动作,将会出现下面的现象:



我们看到这个结果跟standard 有所不同,三个序列号是相同的,也就是说使用的都是同一个FirstActivity 实例;

如果按一下后退键,程序立即退出,说明当前栈结构中只有一个Activity 实例。singleTop 模式的原理如下图所示:


正如上图所示,跳转时系统会先在栈结构中寻找是否有一个FirstActivity 实例正位于栈顶,如果有则不再生成新的,而是直接使用。也许朋友们会有疑问,我只看到栈内只有一个Activity,如果是多个Activity 怎么办,如果不是在栈顶会如何?我们接下来再通过一个示例来证实一下大家的疑问。

我们再新建一个Activity 命名为SecondActivity,如下:


然后将之前的FirstActivity 跳转代码改为:


这时候,FirstActivity 会跳转到SecondActivity,SecondActivity 又会跳转到FirstActivity。演示结果如下:





我们看到,两个FirstActivity 的序列号是不同的,证明从SecondActivity 跳转到FirstActivity 时生成了新的

FirstActivity 实例。原理图如下:


我们看到,当从SecondActivity 跳转到FirstActivity 时,系统发现存在有FirstActivity 实例,但不是位于栈顶,

于是重新生成一个实例。

这就是singleTop 启动模式,如果发现有对应的Activity 实例正位于栈顶,则重复利用,不再生成新的实例。

8.3 singleTask

在上面的基础上我们修改FirstActivity 的属性android:launchMode="singleTask"。演示的结果如下:



我们注意到,在上面的过程中,FirstActivity 的序列号是不变的,SecondActivity 的序列号却不是唯一的,说明

从SecondActivity 跳转到FirstActivity 时,没有生成新的实例,但是从FirstActivity 跳转到SecondActivity 时生成

了新的实例。singleTask 模式的原理图如下图所示:


在图中的下半部分是SecondActivity 跳转到FirstActivity 后的栈结构变化的结果,我们注意到,SecondActivity消失了,没错,在这个跳转过程中系统发现有存在的FirstActivity 实例,于是不再生成新的实例,而是将FirstActivity之上的Activity 实例统统出栈,将FirstActivity 变为栈顶对象,显示到幕前。也许朋友们有疑问,如果将SecondActivity也设置为singleTask 模式,那么SecondActivity 实例是不是可以唯一呢?在我们这个示例中是不可能的,因为每次从SecondActivity 跳转到FirstActivity 时,SecondActivity 实例都被迫出栈,下次等FirstActivity 跳转到SecondActivity 时,找不到存在的SecondActivity 实例,于是必须生成新的实例。但是如果我们有ThirdActivity,让SecondActivity 和ThirdActivity 互相跳转,那么SecondActivity 实例就可以保证唯一。

这就是singleTask 模式,如果发现有对应的Activity 实例,则使此Activity 实例之上的其他Activity 实例统统出栈,使此Activity 实例成为栈顶对象,显示到幕前。

8.4 singleInstance

这种启动模式比较特殊,因为它会启用一个新的栈结构,将Activity 放置于这个新的栈结构中,并保证不再有其他Activity 实例进入。我们修改FirstActivity 的launchMode="standard",SecondActivity 的launchMode="singleInstance",由于涉及到了多个栈结构,我们需要在每个Activity 中显示当前栈结构的id,所以我们为每个Activity 添加如下代码:


然后我们再演示一下这个流程:


我们发现这两个Activity 实例分别被放置在不同的栈结构中,关于singleInstance 的原理图如下


我们看到从FirstActivity 跳转到SecondActivity 时,重新启用了一个新的栈结构,来放置SecondActivity 实例,然后按下后退键,再次回到原始栈结构;图中下半部分显示的在SecondActivity 中再次跳转到FirstActivity,这个时候系统会在原始栈结构中生成一个FirstActivity 实例,然后回退两次,注意,并没有退出,而是回到了SecondActivity,为什么呢?是因为从SecondActivity 跳转到FirstActivity 的时候,我们的起点变成了SecondActivity 实例所在的栈结构,这样一来,我们需要“回归”到这个栈结构。如果我们修改FirstActivity 的launchMode 值为singleTop、singleTask、singleInstance 中的任意一个,流程将会

如图所示:


singleInstance 启动模式可能是最复杂的一种模式,为了帮助大家理解,我举一个例子,假如我们有一个share 应用,

其中的ShareActivity 是入口Activity,也是可供其他应用调用的Activity,我们把这个Activity 的启动模式设置为

singleInstance,然后在其他应用中调用。我们编辑ShareActivity 的配置:


然后我们在其他应用中这样启动该Activity:


当我们打开ShareActivity 后再按后退键回到原来界面时,ShareActivity 做为一个独立的个体存在,如果这时我

们打开share 应用,无需创建新的ShareActivity 实例即可看到结果,因为系统会自动查找,存在则直接利用。大家

可以在ShareActivity 中打印一下taskId,看看效果。关于这个过程,原理图如下:


10、一个启动模式为singleTop 的activity,如果再试图启动会怎样? 面试官想问的是

onNewIntent()

Activity 有一个onNewIntent(Intent intent)回调方法,该方法我们几乎很少使用,导致已经将其忽略掉。该方

法的官方解释如下:

This is called for activities that set launchMode to "singleTop" in their package, or if a client usedthe Intent.FLAG_ACTIVITY_SINGLE_TOP flag when calling startActivity. In either case, when the activityis re-launched while at the top of the activity stack instead of a new instance of the activity being

started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launchit.

An activity will always be paused before receiving a new intent, so you can count on onResume being calledafter this method.Note that getIntent still returns the original Intent. You can use setIntent to update it to this newIntent.

上文大概意思如下:

该方法被启动模式设置为“singleTop”的Activity 回调,或者当通过设置Intent.FLAG_ACTIVITY_SINGLE_TOP的Intent 启动Activity 时被回调。在任何情况下,只要当栈顶的Activity 被重新启动时没有重新创建一个新的Activity实例而是依然使用该Activity 对象,那么onNewIntent(Intent)方法就会被回调。当一个Activity 接收到新Intent 的时候会处于暂停状态,因此你可以统计到onResume()方法会被再次执行,当然这个执行是在onNewIntent 之后的。

注意:如果我们在Activity 中调用了getIntent()方法,那么返回的Intent 对象还是老的Intent(也就是第一次启动该Activity 时的传入的Intent 对象),但是如果想让getIntent()返回最新的Intent,那么我们可以通过setIntent(Intent)方法设置。

你可能感兴趣的:(2018-04-12 Android面试题整理)