当前位置:网站首页 > Java基础 > 正文

android 无java基础



写在前面

光阴似箭,不知不觉中,从事Android开发也有些年份了,回想自己的求职历程,感触颇多。求职离不开面试,想要在面试的时候应答如流,还是需要提前准备的,这里只针对Android技术面,做个总结,把这些年我参加面试时遇到的所有问题做个汇总,让我们一起玩转技术面吧!

图片

Dalvik和ART虚拟机的区别

Dalvik是运行在Android平台的Java虚拟机,Android编译后生成dex文件,Dalvik虚拟机下运行Java时,要将字节码通过即时编译器转换为机器码,这会拖慢应用的运行效率,所以Google开发了新的虚拟机ART(Android Runtime),应用在第一次安装的时候,字节码就会预先编译成机器码,也就是预编译,这样首次启动应用会变得更快。

进程的划分

  • 前台进程:用户正在使用的,比如某个进程持有一个正在与用户交互的Activity并且该Activity正处于Resume状态。系统一般不会杀死前台进程,除非用户强制停止应用。
  • 可见进程:用户正在使用,看得到摸不着,或者没有覆盖到整个屏幕,比如不在前台,但仍对用户可见的Activity。系统一般也不会杀死可见进程,除非在资源吃紧的情况下。
  • 服务进程:比如某个进程中运行着一个Service且该Service是通过startService()启动,与用户界面没有直接关联。在内存不足的情况下,服务进程会被杀死。
  • 后台进程:比如在用户按了Home键,程序本身看不到,但其实还在运行,系统可能随时终止,回收内存。
  • 空进程:某个进程不包含任何活跃组件时该进程就会被置为空进程,完全没用,第一个干它。

Activity生命周期

图片

各种情况的生命周期变化:

  1. 两个Activity(A到B,B为正常Activity)切换的生命周期:onPause(A) – onCreate(B) – onStart(B) --onResume(B) – onStop(A),这时回退到A:onPause(B) – onRestart(A) – onStart(A) – onResume(A) – onStop(B) --onDestory(B)
  2. 两个Activity(A到B,B为Dialog风格的Activity)切换的生命周期:onPause(A) – onCreate(B) – onStart(B) – onResume(B),这时回退到A :onPause(B) – onResume(A) – onStop(B) – onDestory(B)

  3. Activity启动后点击Home键再回到应用的生命周期:onPause – onStop – onRestart --onStart – onResume

  4. 横竖屏切换(切换竖屏时会打印两次相同的log):onPause – onStop – onDestory --onCreate – onStart – onResume。如果清单文件中配置了android:configChanges=“orientation|keyboardHidden|screenSize”,横竖屏切换时不会重新创建Activity,只会调用onConfigurationChanged方法

  5. 电源键关:onPause – onStop,重新开电源键:onRestart – onStart – onResume

Activity启动模式

在AndroidManifest的Activity中,launchMode属性可以设置启动模式,默认standard模式。

  • standard:每启动一个Activity,就会创建该Activity一个新实例。
  • singleTop:每启动一个Activity,都会检查该Activity是否处于栈顶,如果处于栈顶则不创建新实例。适用于接受到消息后显示的界面,例如接受到消息后点击弹出Activity,如果一次来10条消息,总不能一次弹10个Activity。
  • singleTask:每启动一个Activity,都会检查该Activity是否存在返回栈中,如果存在,则直接跳转至该Activity在返回栈中的位置并启动,如果不存在则创建新实例。适合作为程序入口点,例如手机系统浏览器的主界面,不管从多少个应用启动系统浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上其他的页面,不再新建。
  • singleInstance:每启动一个Activity,都会为其创建一个独立的返回栈。适用需要与程序分开的页面,例如系统的通话界面,Activity同时接听两个电话。
图片

onNewIntent与启动模式

当Activity的launchMode为SingleTop时,如果Activity在栈顶,且现在要启动该Activity,这时会调用onNewIntent方法 ,生命周期顺序为:onNewIntent — onResume。

当Activity的launchMode为SingleInstance或SingleTask时,如果Activity已经在任务栈中,再次启动Activity,那么此时会调用onNewIntent方法,生命周期调用顺序为:onNewIntent — onRestart — onStart — onResume

Activity缓存

android 无java基础

图片

Activity中的onSaveInstanceState回调方法用于保存临时数据和状态,这个方法会在Activity的onStop方法之前调用,在onSaveInstanceState方法中有个参数Bundle,可传入需要保存的数据和状态。

图片

Activity中的onRestoreInstanceState回调方法用于恢复数据和状态,这个方法会在Activity的onResume之前调用。在onRestoreInstanceState方法中有个参数Bundle,它会传递到Activity的onCreate中,所以也可以在onCreate方法中做数据和状态还原。

当某个Activity变得容易被系统销毁时,例如按下Home键,关闭电源键等,onSaveInstanceState就会被执行。

onSaveInstanceState和onRestoreInstanceState不一定成对调用的,例如当正在显示Activity的时候,用户按下HOME键回到主界面,然后又返回到Activity,这种情况下Activity一般不会因为内存原因被系统销毁,故Activity的onRestoreInstanceState方法不会被执行。

Service的两种启动方法的区别

  1. 生命周期:

    startService:onCreate — onStartCommand — onDestroy

    bindService:onCreate — onBind — onUnbind — onDestroy

  2. 重复调用:

    startService:重复调用时,onCreate方法只会调用一次,onStartCommand每次都会被调用

    bindService:重复调用时,onCreate与onBind都只会调用一次

  3. 与activity的关系:

    startService:与activity之间没有什么关系,对应的activity被销毁时,不影响service

    bindService:与activity绑定,对应的activity销毁时,对应的service也销毁

  4. 应用场景:

    startService:只指定Service的操作,不需要service返回操作结果的场景

    bindService:需要Service操作完成后,返回操作结果的场景

事件分发机制

事件分发的三个主要对象是:Activity,ViewGroup,View。一个事件产生之后,都是先传给Activity,再传给ViewGroup,最后传给View。

三个重要的方法:dispatchTouchEvent(分发事件),onInterceptTouchEvent(判断是否拦截某个事件,只存在于ViewGroup),onTouchEvent(处理事件)。

Activity和View是没有onInterceptTouchEvent这个方法的,因为Activity是处于分发机制的最顶端,如果一开始就把事件拦截了,那么会导致整个屏幕都无法响应用户的操作,而View处于事件分发的最末端,它不需要拦截,事件分发到View的时候,view能处理就处理,不处理就返回给他的父控件。

手机屏幕我们可以称为一个窗口,也就是一个window,window是一个抽象类,它规定了一些管理窗口的方法,但是具体实现是由它的唯一实现类phonewindow去实现的,这样phonewindow就是整个屏幕的实际掌控者,而phonewindow又是通过它的内部类decorview去对View进行管理。

以点击事件为例:当用户点击了屏幕,事件先传递到Activity中,Activity通过它的dispatchTouchEvent将事件分发到phoneWindow,phonewindow其内部有个内部类DecorView,DecorView会调用dispatchTouchEvent去进行事件分发,如果不拦截事件,就会下传到rootview,rootview在dispatchTouchEvent内部调用onInterceptTouchEvent去判断是否拦截,不拦截就会把事件分发给下一个viewgroup,拦截就在onTouchEvent进行处理并返回true,viewgroup中也是一样,最后事件传递到view,view是最底层控件,不会有onInterceptTouchEvent,它的选择就只有处理和不处理,处理就在onTouchEvent进行处理并返回true,不处理的话事件也不会被销毁,view这时会把事件回传,经过上述流程后回传给activity,如果Activity还不处理,那么这个事件才会被销毁,如下图所示:

图片

Binder原理

Binder IPC是基于内存映射(mmap)来实现的

内存映射就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间,内核空间对这段区域的修改也能直接反应到用户空间。内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。

  • 首先Binder驱动在内核空间创建一个数据接收缓存区;
  • 接着在内核空间开辟一块内核缓存区,建立内核缓存区和数据接收缓存区之间的映射关系,以及数据接收缓存区和接收进程用户空间地址的映射关系;
  • 发送方进程通过系统调用copy_from_user()将数据copy到内核中的内核缓存区,由于内核缓存区和数据接收缓存区,接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。

图片

SurfaceView和View的区别

View主要适用于主动更新的情况,而surfaceView主要适用于被动更新,例如频繁的刷新。

View在主线程中对画面进行刷新,而surfaceView通常会通过一个子线程来进行页面的刷新。

View在绘图时没有使用双缓冲机制,而surfaceView在底层实现了双缓冲机制。

双缓冲技术是把要处理的图片在内存中处理好之后,再将其显示在屏幕上。双缓冲主要是为了解决反复局部刷屏带来的闪烁。把要画的东西先画到一个内存区域里,然后整体的一次性画出来。

HashMap机制

HashMap是一种 “数组+链表” 数据结构,我们是通过put和get方法存取对象的,当我们将键值对传递给put方法时,它调用键对象的hashCode()方法来计算hashcode,然后找到相应的位置来储存值对象。当获取对象时,通过键对象的equals方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中,也就是说,当两个不同的键对象的hashcode相同时,它们会储存在同一个数组位置的链表中。

图片

HashMap在什么情况下会扩容,怎么扩容?


执行put方法时,如果当前的数组里的元素个数大于阈值(阈值=数组长度 x 负荷因子),就会执行resize()方法扩容,扩容时创建一个比原来数组容量大两倍的新数组,遍历原来的数组,把原来数组上的元素重新放到新数组上。

总结:HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。因为红黑树的节点大小是链表节点的两倍,所以只有在节点比较多的时候才使用红黑树。只有链表长度大于8,数组长度大于等于64的时候才会转成红黑树。

ClassLoader双亲委托机制

图片

ClassLoader使用双亲委派机制来加载class文件的:

  1. 当AppClassLoader加载一个class时,首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
  2. 当ExtClassLoader加载一个class时,首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
  3. 如果BootStrapClassLoader加载失败,会使用ExtClassLoader来尝试加载。
  4. 若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。
图片

一些来源的class文件是不可靠的,比如我可以自定义一个Integer类来覆盖jdk中默认的Integer类,然后执行破坏程序正常执行的一些操作,如果使用双亲委派机制的话该Integer类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的Integer类而不会加载自定义的这个。

  • 上一篇: java接口基础教学
  • 下一篇: 疯狂java基础
  • 版权声明


    相关文章:

  • java接口基础教学2025-04-16 10:42:02
  • java基础类总结2025-04-16 10:42:02
  • 黑马java基础笔记2025-04-16 10:42:02
  • java基础课件2025-04-16 10:42:02
  • java基础特殊字段2025-04-16 10:42:02
  • 疯狂java基础2025-04-16 10:42:02
  • java基础选择循环2025-04-16 10:42:02
  • 青岛java基础2025-04-16 10:42:02
  • java基础414讲2025-04-16 10:42:02
  • java基础语法结构2025-04-16 10:42:02