Android面试题

1.加密

  对称加密:加密和解密数据都是使用同一个key,如DES

  非对称加密:加密和解密使用不同的key.发送数据之前要先和服务器约定生成公钥和私钥,使用公钥加密的数据可以用私钥解密,反之不行。如RSA、ssh、ssl。

2.android的安全问题

  ①错误导出组件

  ②参数校验不严

  ③WebView引入各种安全问题(JS注入)

  ④不混淆、不妨二次打包

  ⑤明文存储关键信息

  ⑥错误使用HTTPS

  ⑦山寨加密方法

  ⑧滥用权限、内存泄漏、使用debug签名

3.设备横竖屏切换的时候,生命周期

  ①不设置android:configChanges时,切屏会重新调用生命周期,切横屏时会执行一次,切竖屏时会执行两次。

  ②设置android:configChanges = "orientation"时,切横竖屏时各个生命周期都只执行一次

  ③设置android:configChanges = "orientation|keyboard"切屏时不会调用各个生命周期,只会走onConfigurationChanged方法

4.android进程间通信方式

  intent,Binder(AIDL),Messenger,BroadcastReceiver

5.Parcelable和Serializable的区别

  serializable: 简单易用。缺点:使用了反射,序列化过程较慢。使用IO读写存储在硬盘上。

  parcelable:速度至上。直接在内存中读写。

6.wait()和sleep()的区别

  ①sleep来自thread类,wait()来自object类

  ②调用sleep()方法过程中,线程不会释放对象锁。而wait方法会释放

  ③sleep睡眠后不出让系统资源,wait出让系统资源其他线程可以占用CPU

  ④sleep需要指定一个睡眠时间,时间一到会自动唤醒

7.堆和栈的区别

  ①基本数据类型的变量和对象的引用都是在栈分配的

  ②堆内存用来存放有new创建的对象和数组

  ③类变量(静态变量)程序一加载类就在堆中为类变量分配内存,堆中的内存地址存放在栈中

  ④实例变量:当new的时候,系统在堆中开辟并不一定连续的空间给变量,当引用丢失后,被列入可回收名单,不会马上就释放堆中内存

  ⑤局部变量:声明在某个方法或代码段里,会在栈中开辟内存,当局部变量一旦脱离作用域,内存立即释放。

8.TCP/IP模型四层

  应用层---传输层(TCP/UDP)---网络互联层(IP)---主机到网络层

  

  建立一个TCP连接需要“三次握手”:

  第一次握手:客户端发送syn包到服务器,并进入SYN_SEND状态,等待服务器确认;

  第二次握手:服务器收到syn包,必须确认客户的SYN,同时自己也发送一个SYN包,此时服务器进入SYN_RECV状态;

  第三次握手:客户端收到服务器的SYN包,想服务器发送确认包,此包发送完毕,客户端和服务器进入连接状态,完成三次握手。

9.Android系统结构

  应用层---应用框架层---函数库---Linux内核

10.常用布局

  LinearLayout---RelativeLayout---FrameLayout---TableLayout---AbsoluteLayout

11.Handler机制

  主线程的main方法一运行会准备一个looper轮询器,looper在创建时会new一个MessageQueue消息队列,所以一个线程对应一个looper,一个looper对应一个MQ。

  looper创建后,必须调用loop方法,这个方法有个死循环,会不断从消息队列中取消息,如果消息不为空,会调用handler的handleMessage方法处理消息。

  如果要做耗时操作时,我们要开一个子线程new Thread,把耗时操作交给子线程处理,但是子线程不能更新UI,需要调用handler的sendMessage方法把更新UI的消息发送到消息队列中,交给主线程处理。

  Handler的两种作用:①线程间的通信    ②在未来某个时间点执行一个消息

12.事件分发机制

  事件分发的主角有View和ViewGroup。

  View有两个方法:dispatchTouchEvent(分发事件)和onTouchEvent(处理事件);

  ViewGroup有三个方法:dispatchTouchEvent(分发事件)和onTouchEvent(处理事件),还有onInterceptTouchEvent(拦截事件)。

  结构的模型类似下图

  外层是ViewGroup,最内层是View。(只要是View,就表示最内层)

  触摸时,事件来了:①最外层ViewGroup开始接收,在dispatchTouchEvenet()方法中,调用onInterceptTouchEvent(拦截事件):意思是问自己是否拦截此事件,返回true,表示拦截事件,调用自己的onTouchEvent方法;返回false,表示不拦截事件,事件下传子类;

  ②如果子类是ViewGroup,继续执行①的流程;

  ③如果子类是最内层View,在dispatchTouchEvenet()方法中,调用onTouchEvent():意思是问自己是否消费事件,返回true,表示消费事件,事件终止;返回false,表示不消费事件,事件返回给父类(就是上一级)。

  ④父类接受到返回的事件,调用onTouchEvent方法:返回true,消费事件,事件终止;返回false,不消费事件,事件继续返回。依次类推,返回到最外层ViewGroup,如果没人消费事件,事件丢失。

 

  在触摸时分发机制会确定消费事件的目标,所谓的拦截事件:例如内部子类要消费事件,父类不同意,拦截了事件,事件就落在父类上了(拦截事件其实是将确定的目标为null,子类的事件得不到确定);还有一种情况,父类拦截了子类的事件,但是子类可以请求父类不要拦截,在分发事件中添加getParent().requestDisallowInterceptTouchEvent(true);这样,子类又会获得事件了(这行代码会使拦截事件的置空方法进不去,子类的事件会得到确定)

13.activity的生命周期

  当一个新的页面运行的时候执行顺序onCreate--onStart--onResume,当onResume执行后,页面处于可见可操作(运行状态);

  当onRause运行后,页面处于可见但不可操作(暂停状态),走onResume可回到可被操作状态;

  当onStop运行后,activity处于不可见不可操作(停止状态),走onRestart--onStart--onResume可回到运行状态;

  当onDestroy运行后activity会被销毁;

  当onRestart运行后,页面会回到最前面;

 

  系统不经过用户同意将activity销毁时,会调用onSaveInstanceState()方法,可以重写这个方法保存一些数据到Bundle类型对象中,当用户再重启这个界面时Bundle对象会被作为参数传递给onCreate方法,利用这些数据将activity恢复到被摧毁之前的状态。

14.activity的四种启动模式

  ①standard:默认启动模式,调用startActivity方法,就会在任务栈中创建一个实例

  ②singleTop:栈顶模式,栈顶只有一个实例。如a开启b,b如果配置了singleTop,则不能开启新的b;

  ③singleTask:当前任务栈只有一个实例,a-->b-->c-->d,b配置singleTask,d再开启b时会把上面的c和d全部摧毁,把b暴露在栈顶;

  ④singleInstance:应用中只有一个实例,这个实例会单独占一个任务栈

15.广播

  步骤:①写一个类继承BroadcastReceiver

     ②重写onReceive方法

     ③清单文件中注册广播接收者

     ④有的广播需要权限

 

  有序广播:①发送方法 sendOrderedBroadcast ②接收顺序:可以指定优先级 ③可被中断

  无序广播:①发送方法 sendBroadcast(intent)②接收顺序:没有顺序,同时接收 ③不可被中断

 

16.进程的优先级

  ①前台进程 ②可视进程 ③服务进程 ④后台进程 ⑤空进程

17.service服务

  开启服务有两种方式:startService和bindService

  startservice:①调用startservice后,走onCreate--onStartCommend ②多次调用startservice,onCreate只会走一次,onStartCommend会调用多次 ③通过startservice开启的service在activity退出后,不会销毁 ④只有手动调用stopservice方法,才会销毁服务 ⑤startservice方式开启的服务可以提升应用的进程优先级

  bindservice:①调用bindservice后,走onCreate--onBind ②多次调用bindservice,这两个方法都只会执行一次 ③通过bindservice开启的service生命周期与activity的生命周期关联起来了 ④在activity退出时必须解绑 unbindservice(只能调用一次) ⑤service中的onBind方法中有返回值,那么在serviceConnection中第二个参数就是onBind方法的返回值

 

  服务中可做耗时操作。

18.AIDL 安卓接口定义语言(解决的是跨进程调用的问题)

19.ContentProvider 内容提供者 

   跨应用 共享数据

  内容观察者contentobserver :当数据发生变化时,会发一个notifychanged消息。

20.Context 上下文

  getApplicationContext获取的是应用的上下文,生命周期是整个应用;而Activity.this获取的是这个Activity的上下文,生命周期是所在的Activity.

  只有在创建对话框AlertDialog时必须使用activity作为上下文,因为AlertDialog是要显示在activity的上面,必须传一个activity的上下文才能正常显示;Toast跟AlertDialog不同,Toast是系统级的显示控件,会显示在所有应用的最上层不会被其他节目遮挡,所有传应用的上下文也可以显示Toast

  上下文的计算公式 = 服务的个数 + activity的个数 + 1;

21.动画 

  动画分为两类:属性动画和View动画

  View动画又分为:帧动画和补间动画

  帧动画就是在xml文件中配置的一帧一帧的图片

  属性动画和补间动画都可以旋转、平移和缩放,属性动画会改变原来控件的属性和位置,补间动画播放时则不改变原控件的属性。

22.JNI   Java Native Interface(java本地接口) 

  JNI可以看做是一个翻译,实现JAVA语言和本地语言之间的互相调用

  交叉编译原理:在一个平台上模拟另一个平台的特性进行编译

  NDK:native develop kit 本地开发工具包

23.序列化和反序列化

  把对象转换为字节序列的过程,叫对象的序列化

  把字节序列恢复为对象的过程,叫对象的反序列化

24.内存泄露

  分配的内存空间使用完毕后,没有得到释放。运行时间越长,占的内存越多,直至崩溃。

  ①对象内存过大

  ②资源释放问题:使用完资源,没有及时释放

  ③static变量生命周期长,要是与组件引用起来,组件很难被释放

25.ANR Application Not Responding

  应用在特定时间内无响应

  避免方法:①避免在主线程上进行复杂耗时的操作;

       ②broadCastReceiver 要进行复杂操作的的时候,可以在onReceive()方法中启动一个Service来处理;

       ③在设计及代码编写阶段避免出现出现同步/死锁或者错误处理不恰当等情况。

26.线程间通信

  ①共享内存 ②文件、数据库 ③handler ④java中的wait,notify,notifyAll

27.屏幕适配

  px:像素   dp:像素密度

 

28.Socket和Http的区别

  TCP/IP的参数模型有四层:应用层---传输层---网络互联层---主机到网络层

  HTTP:首先是一个协议,是基于TCP/IP协议基础上的应用层协议,TCP/IP协议是传输层协议,主要解决数据如何在网络中传输;HTTP是应用层协议,主要解决如何包装数据。---短连接。

  

  Socket:不属于协议范畴,而是一个调用接口(API),是对TCP/IP协议的封装,调用socket,才能使用TCP/IP协议。---长连接。

  

  HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束猴,主动释放连接,由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是“短连接”。要保持客户端程序的在线状态,需要不断向服务器发起连接请求。服务器在收到该请求后对客户端进行回复,表示客户端“在线”;若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。

 

  Socket连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

  服务器监听:服务器套接字并不定位具体客户端套接字,而是出于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

  客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器的套接字。客户端的套接字必须先描述它要连接的服务器的套接字,指出服务器套接字的地址和端口号,然后向服务器套接字提出连接请求。

  连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

 

  socket的应用场景:网络游戏、银行交易、支付系统;

  http的应用场景:OA(办公网络)、互联网;

 

 

 29.对多线程的认识

  主线程一般负责用户界面的绘制和及时响应用户的操作,让子线程在后台执行一些比较耗时的任务。

  Android中使用多线程的原因:

    ①I/O操作:文件、网络和数据库

    ②复杂的运算

    ③定时操作  

    注意:异步就是多线程。对耗时操作应该放到非主线程中运行,避免阻塞主线程。子线程不能更新UI.

  多线程用到的类:Thread、Handle、Runable、AsyncTask

  AsyncTask是对Handler与线程池的封装。Handler是为了将消息发送给主线程。使用线程池的主要原因是避免不必要的创建及销毁线程的开销。

 

  并发和并行:单核机器上,操作系统快速在进程间切换而模拟出的多线程---并发;多核情况下,并发就变为并行了。

  阻塞状态:I/O操作访问磁盘时,相对于访问内存和简单计算,需要的时间比较长,此时就是阻塞状态,会阻塞进程(操作系统会让当前进程暂时休眠,去执行别的进程,以免浪费时间,当该进程处理完后,会发出信号通知操作系统来继续执行该进程)。

  进程就是执行中的程序实例,而线程可以看作是进程中的最小执行单元。

  创建一个新线程:①通过实现Runnable接口

          实现Runnable接口并实例化,将这个对象传给Thread的构造器来创建一个新的线程

          ②通过继承Thread抽象类

          继承并实例化直接创建一个新线程

        二者比较:Thread虽然简单但是不能多继承,Runnable麻烦但是可以继承其他类

  线程的生命周期:

    ①新建(new Thread)

    ②就绪(runnable):线程对象调用start方法后,会进入Runnable状态(在就绪队列中排队等待CPU资源)

    ③运行(running):线程获取CPU资源执行任务(run方法)

    ④死亡(dead):当前线程执行完毕或被其他线程杀死,该线程不能进入就绪状态;自然终止:run方法运行结束;异常终止:调用stop方法终止

    ⑤阻塞(blocked):由于某种原因正在运行的线程让出CPU并暂停自己的执行。睡眠可进入阻塞状态,等待也可进入阻塞状态,还可被另一个线程阻塞(suspend方法)

 

 

 

 

 

 

 

 

 

 

 

  

 

posted @ 2017-02-15 22:31  盗码笔记  阅读(356)  评论(0)    收藏  举报