Android项目面试知识汇集

如果文中有什么纰漏或错误的话,请留言指正,我会及时修改。

如果你觉得本文还不错的话,记得点个赞呦,希望能帮到你。谢谢!

这里写图片描述 这里写图片描述 这里写图片描述


1. 要做一个尽可能流畅的ListView,你平时在工作中如何进行优化的?

1.Item布局,层级越少越好,使用UI检视利器:Hierarchy Viewer
注:Hierarchy Viewer 1). 从可视化的角度直观地获得UI布局设计结构和各种属性的信息
                    帮助我们优化布局设计
                    2). 结合debug帮助观察特定的UI对象进行invalidate和requestLayout
                    操作的过程。

2.复用convertView, 使用ViewHolder
3.item中有图片时,异步加载
4.快速加载时,不加载图片
5.实现数据的分页加载

2.对于Android的安全问题你知道多少?

1.错误导出组件
2.参数校验不严
3.WebView引入各种安全问题,WebView中的JS介入
4.不混淆,不防二次打包
5.明文储存关键信息
6.错误使用HTTPS
7.滥用权限,内存泄露,使用debug签名

3.Android与服务器交互的方式中对称加密和非对称加密是什么?

对称加密: 就是加密和解密数据都是使用同一个key,算法是DES
非对称加密: 加密和解密使用不同的key,发送数据之前要先和服务端约定生成的公钥和私钥,使用公钥加密的数据
可以使用私钥解密,反之,使用私钥加密的数据可以使用公钥解密.算法有RSA,SSH和SSL经典对称加密

4.Service的onCreate回调是在UI线程中吗?

Service生命周期的各个回调和其他应用组件一样,都是跑在主线程中,会影响到你的UI操作或者
阻塞主线程中的其他事情(尤其是bind Service时)

5.请你介绍一下AsyncTask的内部应用,应用场景是怎样的?

AsyncTask内部也是 Handler 机制来完成的,只不过Android提供了执行框架来提供线程池来执行相应任务。
因为线程池大小的问题,所以AsyncTask只应该用来执行耗时较短的任务,比如 Http 请求,大规模的下载
和数据库更改不适用与AsyncTask,因为会导致线程池堵塞,没有线程来执行其他任务,导致的情形是会发生
AsyncTask根本执行不了的问题。

6.谈谈你对binder机制的理解?

binder是一种 IPC 机制,进程通讯的一种工具
Java层可以利用 AIDL 工具来实现相应的接口,生成通讯代码

7.Android中 进程间 通信有哪些实现方式?

1.Intent 连接四大组件的纽带
2.Binder AIDL工具来实现相应的接口,生成通讯代码
3.Messenger 是基于 AIDL 实现的,服务端(被动方)提供一个Service来处理客户端(主动方)连接
4.BroadcastReceiver 广播服务
5.contentprovider 数据共享
6.ServiceContent Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider
返回的是 Cursor 对象,而Service返回的是 Java 对象,这种可以跨进程通讯的服务叫AIDL服务

8.介绍一下实现一个自定义View的基本流程

1.自定义View的属性,编写 attr.xml 文件
2.layout 布局中引用,同时引用命名空间
3.在View的构造方法中获得我们自定义的属性,在自定义控件中进行读取
4.重写 onMesure (如果自定义ViewGroup还需要重写onLayout)
5.重写 onDraw (如果自定义ViewGroup可以不用重写该项)

9.Android多线程的实现方式有哪些?

Thread 和 AsyncTask
Thread 可以与 Loop 和 Handler 共用建立消息处理列队
AsyncTask 可以作为线程池并行处理多任务

10.Android开发中何时使用多进程? 使用多进程的好处是什么?

 要想知道何时使用多进程,要先知道Android多进程的理念:
 一般情况下,一个应用程序就是一个进程.这个进程名称就是应用程序包名。
 进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的资源和内存空间,
 别的进程是不能随意访问其他进程的内存和资源的

那如何让自己的应用拥有多进程?
我们的四大组件在AndroidManifest文件中注册的时候,这个属性是andriod:process

1.这里可以指定组件的所处进程。默认为应用的主进程。指定为别的进程之后,系统会在启动这个组件的时候
先创建(如果还没有创建的话)这个进程,然后再创建该组件。可以重载Application类的onCreate方法
打印出它的进程名称,这样就可以清楚的看见了。

在设置android:process属性的时候,需要注意的是:如果是android:process=":deamon",以:开头的名字
则表示这是一个应用程序的私有进程,否则它是一个全局进行。私有进程的进程名称是会在冒号前自动加上包名,而
全局进程则不会。一般我们都是有私有进程,很少使用全局进程。

2.使用多进程显而易见的好处就是分担主进程的内存压力。我们的应用越做越大,内存越来越多,将
一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有心人会发现
Android后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用
,不过现在多进程已经被用烂了。典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,
或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。还有就是防止主进程被杀守护进程,
守护进程和主进程之间相互监视,有一方被杀就重新启动它

3.坏处的话,多占用了系统的空间,大家都这么用的话系统内存很容易占满而导致卡顿。消耗用户的
电量。应用程序架构会变复杂,应为要处理多进程之间的通信。

11.多进程有哪些缺陷,应该怎么解决

首先要明确的一点是进程间的内存空间是不可见的。从而,开启多进程后,我们需要面临这样几个
问题:
1)Application的多次重建。
2)静态成员的失效。
3)文件共享问题。
4)断点调试问题。
解决:

1),可以在ApplicationonCreate中获取进程Id来判断不同进程然后做不同的事情
2)使用Intent或者aidl等进程通讯方式传递内容不能用静态或者单例模式
3)多进程情况下会出现两个进程在同一时刻访问同一个数据库文件的情况。这就可能造成资源的
竞争访问,导致诸如数据库损坏、数据丢失等。在多线程的情况下我们有锁机制控制资源的共享,但是
在多进程中比较难,虽然有文件锁、排队等机制,但是在Android里很难实现。解决办法就是多进程
的时候不并发访问同一个文件,比如子进程涉及到操作数据库,就可以考虑调用主进程进行数据库的操
作。
4)调试就是跟踪程序运行过程中的堆栈信息,由于每个进程都有自己独立的内存空间和各自的堆
栈,无法实现在不同的进程间调试。不过可以通过下面的方式实现:调试时去掉
AndroidManifest.xmlandroid:process标签,这样保证调试状态下是在同一进程中,堆栈信
息是连贯的。待调试完成后,再将标签复原。

12.ANR是什么?怎样避免和解决ANR?

ANR:Application Not Responding,即应用无响应

ANR一般有三种类型:
1:KeyDispatchTimeout(5 seconds) –主要类型
按键或触摸事件在特定时间内无响应

2:BroadcastTimeout(10 seconds)
BroadcastReceiver在特定时间内无法处理完成

3:ServiceTimeout(20 seconds) –小概率类型
Service在特定的时间内无法处理完成

13.Android下解决滑动冲突的常见思路是什么?

相关的滑动组件重写 onInterceptTouchEvent,然后根据判断x,y值 来决定是否要拦截当前操作

14.如何把一个应用设置为系统应用?

成为系统应用,首先要在对应设备的 Android源码SDK下编译,编译好之后:
此 Android设备是Debug版本,并且已经root,直接将此apk用adb 工具pushsystem/app或sy
stem/priv-app下即可。
如果非root设备,需要编译后重新烧写设备镜像即可。
有些权限(如 WRITE_SECURE_SETTINGS),是不开放给第三方应用的,只能在对应设备源码中编译
然后作为系统 app 使用。

15.内存泄露检测有什么好方法?

检测:
1.DDMS Heap发现内存泄露
dataObject totalSize的大小,是否稳定在一个范围内,如果操作程序,不断增加,说明内存泄露
2.使用Heap Tool进行内存快照前后对比
BlankActivity手动触发GC进行前后对比,对象是否被及时回收
定位:
1、MAT插件打开.hprof具体定位内存泄露:
查看histogram项,选中某一个对象,查看它的GC引用链,因为存在GC引用链的,说明无法回收
2、AndroidStudio的Allocation Tracker:
观测到期间的内存分配,哪些对象被创建,什么时候创建,从而准确定位

16.谈谈你对Android中Context的理解?

Context:包含上下文信息(外部值) 的一个参数. Android 中的 Context 分三种,Application
Context ,Activity Context ,Service Context.
它描述的是一个应用程序环境的信息,通过它我们可以获取应用程序的资源和类,也包括一些应用级别
操作,例如:启动一个Activity,发送广播,接受Intent信息等

17.请问平时开发过程中,你是如何做到多分辨率适配的?

1.根据不同分辨率建立不同的布局文件
2.根据分辨率不同建立不同分辨率的资源图片
3.在程序启动时,获取当前屏幕的密度和分辨率,在代码中进行适配
4.为不同分辨率写不同的dimen文件
5.使用fragment

18.谈谈你在工作中时怎样解决一个BUG的?

1.Log日志
2.可以断点调试
3.可以在异常代码附近逐一输出Log信息,看结果提示
4.找问题,找思路,如果遇到技术瓶颈可以查看博客、论坛、百度、咨询朋友、同事等

19.声明ViewHolder(或Handler)内部类时,为什么建议使用static关键字?

1.其实这个是考 静态内部类和非静态内部类的区别:
非静态内部类会隐式持有外部类的引用,如果你将内部类定义为static时,就调用不了外部类的实例方法了
这个时候静态内部类是不持有外部类的引用的声明ViewHolder静态内部类,可以将ViewHolder和外部类解
引用。大家会说一般ViewHolder都很简单,不定义为static也没事吧。确实如此,但是如果你将它
定义为static的,说明你懂这些含义。万一有一天你在这个ViewHolder加入一些复杂逻辑,做了一
些耗时工作,那么如果ViewHolder是非静态内部类的话,就很容易出现内存泄露。如果是静态的话,
你就不能直接引用外部类,迫使你关注如何避免相互引用。所以将ViewHolder内部类定义为静态的,
是一种好习惯

2.非静态内部类隐式持有外部类的强引用,只是可能会导致内存泄露,而一般情况下在使用viewhod
ler是不会导致内存泄露的,加static是一个比较好的习惯而已

3.针对Handler则建议使用static,然后需要引用外部类内容时先将外部类以弱引用(WeakRefer
ence)保存起来,然后再取出调用。

如例:

    static class MyHandler extends Handler {
        private WeakReference<Context> mActivity;

        public MyHandler(Context activity) {
            this.mActivity = new WeakReference<Context>(activity);
        }

        public void handleMessage() {
            //...
            Context c = mActivity.get();
            c.sendBroadcast(...);
        }
    }

20.如何在不失真的情况下显示一张超清图或者长图?

1. 通过计算BitmapFactory.Options 对象的inSamleSize值等比压缩图片
2. 使用WebView来加载图片
3. 使用MapView或者TileView来显示图片(类似地图的机制)
4. BitmapRegionDecoder局部加载

21.你应用中的网络层是怎样设计的?

1. 在HttpUrlConnection基础上封装了常用的方法,getpost、上传、下载、(断点续传)
包括请求成功、失败、请求中、处理成功以及网络问题等封装,利用接口回调或者广播与UI交互
关于网络请求结果的缓存,单独处理,比如像图片缓存用Lrucache以及File.并没有放在网络层

2.android-async-http,封装了常用的方法,getpost、上传、下载;具体的用法一般都是和
业务逻辑在一起,而我的业务逻辑是用异步去处理的.

3.直接使用xUtils,afinal,okHttp,Volley等开源第三方框架

22.如何理解Bitmap,以及相关的优化方式?

itmap是android中经常使用的一个类,它代表了一个图片资源。
Bitmap消耗内存很严重,如果不注意优化代码,经常会出现OOM问题,优化方式通常有这么几种:
1. 使用缓存
2. 压缩图片
3. 及时回收 :至于什么时候需要手动调用recycle,这就看具体场景了,原则是当我们不再使用
Bitmao时,需要回收之。另外,我们需要注意,2.3之前Bitmap对象与像素数据是分开存放的
Bitmap对象存在Java Heap中而像素数据存放在Native Memory中,这时很有必要调用recycle回收内存
但是2.3之后,Bitmap对象和像素数据都是存在Heap中,GC可以回收其内存。

23.ViewPager中加载Fragment的优化问题?如何做到微信那样切换界面时的延时加载?

利用fragment中的setUserVisibleHint这个方法可以来做到
private boolean hasLoadedOnce = false; 
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (this.isVisible()) {
        // 检查这个片段是否可见
        if (isVisibleToUser && !hasLoadedOnce) {
            //代码区
             }
         }
     }
 }

24.什么是aar?aar和jar有什么区别?

1."aar"包是 Android 的类库项目的二进制发行包
文件扩展名是.aar、maven项目类型应该也是aar,但文件本身是带有以下各项的zip文件:
/AndroidManifest.xml (强制)
/classes.jar (强制)
/res/ (强制)
/R.txt (强制)

/assets/ (可选择)
/libs/*.jar (可选择)
/jni/*.so (可选择)
/proguard.txt (可选择)
/lint.jar (可选择)
这些条目是直接位于 zip 文件根目录的
其中R.txt 文件是aapt带参数–output-text-symbols的输出结果。

2、jar打包不能包含资源文件,比如一些drawable文件、xml资源文件之类的,aar可以。

25.如何加密Url防止被黑?

进行Https证书双向加密验证 保证安全性

26.你在平时开发中会使用到哪些设计模式,能谈谈这些设计模式的使用场景吗?

比较常用的有 单例模式(在内存中仅实例化一个对象时使用)、适配器模式(ListView列表和GridView宫格适配器)
建造者模式(AlertDialog.Builder(对话框建造))、观察者模式比较隐蔽,在Adnroid源码中,BaseAdapter的
NotifyDataSetChanged的实现

27.谈谈你对Android线程优先级的看法

Android线程大方向上来说可以分为UI线程和background线程,如果从UI线程启动,则该线程优先级默认为
Default归于default group,会平等的和UI线程争夺CPU资源。这一点尤其注意:在对UI性能要求高的情况下
建议将线程设置为background线程:

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)
//Android开发者需要显式的将工作线程归于background group。
new Thread(new Runnable() {
@Override
public void run() {
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    }
}).start()

28.OOM产生的本质是什么?

Dalvik VM主要是管理的内存Java heap,由于手机设备的限制,一般一个应用使用的内存不能超过默认值32M
不同的设备有差异,可通过adb shell getprop | grepdalvik.vm.heapgrowthlimit命令查看 
当在DVM上申请堆内存大于默认的内存值的时候,这时候应用就会抛出OutOfmemoryError

29.View如何实现刷新,简述什么是双缓冲?

android中实现View的刷新有两个方法,一个是invalidate();另一个是postInvalidate()
其中前者是在UI线程自身中使用,而后者在非UI线程中使用。

出现屏幕闪烁是图形编程的一个常见问题。当进行复杂的绘制操作时会导致呈现的图像闪烁或具有其他不可接受
的外观。双缓冲的使用解决这些问题。双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当使用
双缓冲时,首先在内存缓冲区里完成所有绘制操作,而不是在屏幕上直接绘制。当所有绘制完成之后,把内存
缓冲区完成的图像直接复制到屏幕。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的
图像闪烁问题

在android中实现双缓冲,可以使用一个后台画布backcanvas,先把所有绘制操作都在这上面进行。
等图画好了,然后把backcanvas拷贝到与屏幕相关联的canvas上去 如下:
Bitmap bitmap = new Bitmap()
Canvas backcanvas = new Canvas(bitmap)
backcanvas.draw()...//画图
Canvas c = lockCanvas(null);
c.drawbitmap(bitmap);//把已经画好的图像输出到屏幕上
unlockAndPost(c);

30.一个列表有10个item显示在屏幕上,每个item平均10ms刷新一次可能会出现什么问题怎么解决?

1.由于出现频繁快速的刷新请求,可能会导致画面闪烁
2.程序处理界面刷新可能处理不玩,没有更多资源处理用户操作,会出现滑动无响应。甚至滑动后弹出ANR提示框

解决思路:
缓冲数据,减少刷新次数,人的视觉流畅度的分辨率能力最差的是12fps,电影一般在24fps,而Android就把
达到这种刘畅的帧率规定在60fps,换算关系:60帧/秒约为6ms/帧;因此,尽量保证每次在16ms内处理完所有
的CPU和GPU计算、绘制、渲染等操作,否则会造成丢帧卡顿问题。因此我们应该设计一个内存数据缓冲区,将
要刷新的数据缓冲起来,然后设计刷新控制器至少每隔16ms才来读取内容统一刷新即可。

31.网络层次架构

  • OIS是Open System Interconnect的缩写,意为开放式系统互联、
  • OSI七层参考模型的各个层次的划分遵循下列原则:
1.同一层中的各网络节点都有相同的层次结构,具有同样的功能。
2.同一节点内相邻层之间通过接口(可以是逻辑接口)进行通信。
3.七层结构中的每一层使用下一层提供的服务,并且向其上层提供服务。
4.不同节点的同等层按照协议实现对等层之间的通信。
  • OSI七层模型
应用层 文件传输 电子邮件 文件服务 虚拟终端

未完待续…

猜你喜欢

转载自blog.csdn.net/life_s/article/details/79751737