Android面试常见问题及解答 您所在的位置:网站首页 环境专业答辩问题及答案有哪些 Android面试常见问题及解答

Android面试常见问题及解答

2024-07-06 00:49| 来源: 网络整理| 查看: 265

性能优化

性能优化包含了性能设计和性能优化两个阶段.

通过充分利用底层实现机制,诸如:局部算法、代码写法、编程语言技巧、界面Layout优化、控件的选择、编译器选项等,围绕性能关键流程去优化代码细节。

内存泄露主要原因:

内存泄露:程序中存在对无用对象的引用,导致GC无法回收。

内存超限:保存了多个耗用内存过大的对象(如Bitmap)。

常见导致内存泄露的问题:

注册没取消造成内存泄露,如:广播:在onPause或onDestory方法中取消注册。

静态变量持有Activity的引用:将静态变量对应的类声明为静态类,将内部类声明为静态的。

单例模式持有Activity的引用:单例的生命周期是和app的生命周期一致,持有Activity的引用时容易产生内存泄露,解决方案:1.实现Application,在实现里面提供一个实例,通过此实例来获取ApplicationContext。2.重构Singleton,把构建单例时的参数context去掉,避免错误引用。

查询数据库后没有关闭游标cursor:不使用时关闭游标。

构造Adapter时,没有使用 convertView 重用

Bitmap对象不在使用时调用recycle()释放内存:1.bitmap使用完毕后,及时回收bitmap。2.捕获异常。3.缓存通用的bitmap对象,即定义成全局变量或静态变量。4.压缩图片。

对象被生命周期长的对象引用,如activity被静态集合引用导致activity不能释放:将内部类声明为静态的。

使用Handler造成的内存泄露:将Hnandler声明为静态内部类;如果持有context对象,可以使用弱引用;Looper线程的消息队列中可能还有待处理的消息,在Activity的onDestory方法中移除消息队列中待处理的消息。

集合里面的对象要及时删除。

使用 LeakCanary 检测 Android 的内存泄漏http://www.cnblogs.com/andashu/p/6440944.html(Android常见内存泄露原因及解决办法)

Android内存泄漏可以引发什么问题? 答:可能使程序造成卡顿的现象,或者莫名的消失,因为内存过大,系统就更可能的回收这一块的内存,或者直接崩溃.

分析内存泄漏(DDMS dump + MAT分析)

优化方法:Coding、Bitmap、ListView、SoftReference & WeakReference、UI

http://blog.csdn.net/tiantangrenjian/article/details/39182293

http://yuweiguocn.github.io/android-interview-peformance/

Android怎么优化启动速度?

答:因为Android启动应用程序一般分为两种,一种是冷启动,就是要启动的应用程序没有后台进程的启动,这个时候需要重新分配一个进程给他,所以这个时候会先初始化Application类,再创建和初始化MainAcitvity 类,最后显示到界面上,还有一种是热启动,就是后台还有该应用的进程,比如说按下的home键或者返回键,虽然表面上退出了,但是在任务栈里面仍然还存在的,这个时候就不需要再初始化Application类了,只要重新初始化MainActivity了。因为大多数应用的启动都是冷启动(用户习惯将应用程序在任务栈中删除),所以这个时候可以采取这几个步骤,比如尽量不在Application的构造器,attachBaseContext方法和onCreaete方法中做过多的耗时操作,将一些数据预取放在异步线程中,可以采Callback的方式。优化MainActivity,尽量不要在MainActivity的onCreate,onStart和onResume等方法里面做过多的耗时操作。 Android怎么加快Activity的显示速度?

答:首先因为Activiy的显示是在这几个生命周期之间的,onCreate,onStart,和onResume,这个时候我们需要将我们需要初始化的数据分类,比如说我们将一些只需要初始化的一次的数据放到onCreate中,尽量不要在onCreate中做耗时的操作,然后将需要加载比较长时间的数据放到onResume中,可以利用handler的机制进行更新UI,或者放到AsyncTask逐个显示,然后可以设置一些动画进行显示,如果这个时候有许多数据都是一次显示的,那么可以在onCreate里面进行标记,并且在onResume里面判断是否需要初始化,初始化完成以后就立刻false掉,这样就可以避免多次初始化了,也可以提升Activity的显示速度。

 

1、button 响应流程(事件分发机制)

Button要注册监听器setOnClickListener,参数是OnClickListener对象,点击时会回调到OnClickListener对象的onClick方法,在该方法中处理。

当我们点击按钮的时候,就会调用Button的dispatchTouchEvent方法,Button是继承TextView,TextView继承View,在View中实现了dispatchTouchEvent方法,先响应onTouch事件,再响应onClick事件。

2、为什么使用Handler

更新UI线程的机制,也是一套消息处理机制,可以通过Handler来处理消息,更新UI等。

Handler机制大约是这样的:首先Handler发送一个消息MessageQueue里面,然后通过Looper的loop方法进行无限循环,如果产生了一个新消息,那么就调用handler的handlermessage方法进行余下的操作。之所以这样做的原因是因为避免多线程并发更新UI线程所产生的问题的,如果我们允许其他子线程都可以更新界面,那么势必会造成界面的错乱(因为没有加锁机制),如果我们加锁,又会影响速度,所以,只能在主线程即UI线程里面更新界面。

HandlerThread是Android官方给我们提供好的一套子线程的Handler,也就是异步处理机制,它是为了避免线程切换导致空指针异常的错误。

可以利用HandlerThread进行生成一个子线程的Handler,并且实现handlerMessage方法,然后在主线程里面也生成一个Handler,然后通过调用sendMessage方法进行通知子线程。同样,子线程里面也可以调用sendMessage方法进行通知主线程。这样做的好处比如有些图片的加载啊,网络的访问啊可能会比较耗时,所以放到子线程里面做是比较合适的。

3、实现一个view的过程,自定义view

4、广播的动态注册和静态注册有什么区别?

答:静态注册:在AndroidManifest.xml文件中进行注册,当App退出后,Receiver仍然可以接收到广播并且进行相应的处理

动态注册:在代码中动态注册,当App退出后,也就没办法再接受广播了。

6、Android存储形式有几种?

答:1.SQLite方式,SQLite是一个轻量级的数据库, 支持基础的SQL语法,官方提供了一个SQLiteDatabase的类,并提供一些api。

2.SharedPreference:存储简单的参数信息,本质上是xml.

3.File:文件存储,常用来存储大数据量的数据,但是更新麻烦。

4.ContentProvide,一般情况下数据在各个应用中是私密的,但是因为它也是可以用来存储分享数据。

5.网络存储,将数据放到网络云里面,然后通过网络进行访问。

7、如果面试腾讯要多了解网络相关的知识,HTTP、TCP/IP、三次握手协议等基础知识都要懂。

三次握手、四次挥手:http://www.cnblogs.com/wuyuan2011woaini/p/4876588.html

8、Activity的启用模式有哪些?

四种启动模式:

l Standard:每次都生成新的实例;

l singleTop:如果需要的实例在栈顶,则使用该实例,不再创建新的实例;否则创建新的实例;

l singleTask:跳转时发现有跳转对象的实例,则不再生成新的实例,而是将该对象之上的实例统统出栈,该对象成为栈顶对象;

l singleInstance:跳转时会启用一个新的栈结构,并保证不再有其他activity加入。

9、Service有哪几种注册方式

Service的启动有两种方式:context.startService() 和 context.bindService()

context.startService()  ->onCreate()  -> onStart()  -> Service running  -> context.stopService()  -> onDestroy()  -> Servicestop

context.bindService() -> onCreate()  -> onBind()  -> Servicerunning  -> onUnbind()  -> onDestroy() -> Service stop

10、PackageManagerService:

1、PackageManagerService服务负责各种APK包的安装、卸载、优化和查询;

2、/data/app目录或者/system/app目录下存放的是以应用名称命名的目录,在这个目录下存放的是apk文件和一个lib目录,lib目录存放的是应用的so文件。

3、系统应用是不能删除的,但是可以升级。升级的方法是安装一个包名相同,但是具有更高版本号的应用在/data/app目录下。对于系统中的这种升级情况,Android会在/data/system/packages.xml文件中用标签记录被覆盖的系统应用的信息。

4、每个应用都有保存数据的目录,位于/data/data//目录下。其中数据目录下常见的两个子目录:shared_prefs目录中保存的是应用的设置文件,database保存的是应用的数据库文件。

5、PMS的构造方法主要完成两件事,第一是把系统中的apk文件和jar包从dex格式转换成ART的oat格式;第二是扫描系统中所有安装的应用,把他们的信息提取出来。

6、构造方法过程:

Ø 添加用户:shell、phone、bluetooth;

Ø 建立PackageHandler;

Ø 扫描permission文件;

Ø 扫描packages.xml文件;

Ø so、jar进行dexopt()优化;

Ø scanDirLI解析apk文件;

7、应用安装流程:

应用安装的过程大概分成两个阶段,第一阶段把需要安装的应用复制到/data/app目录下,第二阶段是对apk文件进行扫描优化,然后装载到内存中。

首先检查调用进程是否有安装应用的权限,再检查调用进程的所属用户是否有权限安装应用;

把调用的参数保存在InstallParams对象中,然后发送INIT_COPY消息

MCS_BOUND消息:调用InstallParams类的startCopy()方法来执行安装

handleStartCopy(),如有异常发送MCS_RECONNECT,重新连接,重新执行startCopy();

重试的次数如果超过4次,安装失败。如果安装成功,调用handleReturnCode方法继续处理。

确定安装位置是否还有足够空间,没有则释放空间;

ACTION_PACKAGE_NEEDS_VERIFICATION,处理APK的校验,

copyApk()—》copyPackage()将应用的文件以及动态库等复制到/data/app下。

所有的应用都安装完毕,然后发送一个延时10秒的MCS_UNBIND消息。

如果发现mPendingInstalls列表中又有数据了,则发送MCS_BOUND消息继续安装;否则断开和DefaultContainerService的连接,安装过程就此结束

 

第二阶段:将应用的格式转化为oat格式,为应用创建数据目录,最后把应用的信息装载进PMS的数据结构中

在前面的startCopy()方法中已经看到,最后它会调用handleReturnCode()方法。

post了一个消息,这样安装过程将以异步的方式继续执行

调用installPackageLI()来装载应用,接下来的一大段代码都是执行备份操作;

解析apk文件

判断是否是更新安装;

备份完成后,通过发送POST_INSTALL消息来继续处理

POST_INSTALL消息的处理主要就是发送广播,应用安装完成后要通知系统中其他的应用开始处理

最后通过参数中的回调接口通知调用者安装的结果

11、开机流程:

bootloader,软件启动的大致流程应该是启动kernel-> 运行servicemanager 把一些native的服务用命令启动起来(包括wifi, power, rild, surfaceflinger, mediaserver等等)-> 启动Dalivk中的第一个进程Zygote -> 启动java 层的系统服务system_server(包括PowerManagerService, ActivityManagerService , telephony.registry,DisplayManagerService等等)该服务中的这些部件跟native的那些服务关联在一起 -> 启动Luncher和Persistent的App,该程序是系统级的在AndroidManifest.xml里声明android:persistent="true" -> 发出ACTION_BOOT_COMPLETED广播给其他应用

12、第三方应用应当至少晚于Phone APP启动,如何判断呢?最简单的办法看其PID的大小,PID值越小越先启动

13、Activity的启动模式,为什么需要除了standard以外的启动模式

http://blog.csdn.net/codeemperor/article/details/50481726

14、Service有没有隐式启动方式,(从某一个版本开始)为什么没有

从5.0开始不再使用隐式启动方式。导致系统进程挂掉,不断重启。

15、广播的问题

1.广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁 2.广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框 3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉 4.耗时的较长的工作最好放在服务中完成

16、讲一下对Content Provider的理解以及用法

ContentProvider是允许不同应用进行数据交换的标准的API,ContentProvider以Uri的形式对外提供数据的访问操作接口,而其他应用则通过ContentResolver根据Uri去访问指定的数据。

URI是统一资源标识符,三个组成部分:访问资源的命名机制、存放资源的主机名、资源自身的名称,由路径表示。

用法:1。首先自定义一个ContentProvider类,该类继承ContentProvider类,并在manifest文件中配置自定义的ContentProvider类;2.

17.对permission的认识

18.认为什么样的代码是好的代码,自己的代码是好的代码么

19.HashMap的底层实现

20.谈一下自己了解的设计模式

21.自己了解的开源框架(说的volley,面试官让多去了解一下RxJAVA和Retrofit)

22、多线程的相关知识(多线程的各种实现以及区别)

实现方式:1.继承Thread类;2.实现Runnable接口。       重写run()方法,start()方法启动多线程;

区别:1.Thread是Runnable的子类,实现Runnable的方式解决了java单继承的局限;2.Runnable接口实现多线程比继承Thread类更加能体现数据共享的概念。

http://www.cnblogs.com/Mindreader/p/5472409.html

23.谈一下客户端向服务端发送请求的时候,对于中途被人截取并修改信息的解决办法

将要提交的参数先做加密,然后把加密的信息做一次md5摘要,也就是签名,然后把摘要连同参数一起回传给服务器,服务器拿到参数后,同样的方式加密做md5摘要,然后两个摘要做对比,如果不相等参数便是被篡改了,否则可信。

24、是否自己添加过一个服务,服务的作用是干什么的;

Binder流程

安全机制:selinux及框架,上层的类

25、Service的作用:

Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!   既然这样,那么我们为什么要用 Service 呢?其实这跟android 的系统机制有关,我们先拿 Thread 来说。Thread的运行是独立于 Activity 的,也就是说当一个Activity 被 finish 之后,如果你没有主动停止Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。   举个例子:如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)。   因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有