备战面试旺季:三年开发经验,离开了某创业公司我用这些拿到了6个大厂offer

Activity启动流程总结-生命周期 文章目录前言源码探究startActivitystartActivityAsUserstartActivityMayWaitstartActivityUncheckedresumeFocusedStackTopActivityLockedresumeTopActivityUncheckedLockedresumeTopActivityInnerLocked1.pause当前显示的Activitys... 阅读详情

每天保持好的精神状态和好的行为习惯

周六:星巴克一杯咖啡,看一下午书(最近在看东野圭吾的黎明之街)缓解一下周一到周五紧张的神经。慢慢的品尝美食。晚上看个电影(古仔演反派还是帅)
周日:窝在家里追一天剧,出门散散步

正文开始

更多完整项目下载。未完待续。源码。图文知识后续上传github。
可以点击关于我 联系我获取

一.基础知识

由于面的Android岗位,需要准备一些Java和Android方面的知识,有很多的文章都会去介绍怎么去复习基础的知识或者进阶知识,或者是阅读一些经典的面试数据。大家可以根据网上的文章和一些数据梳理一个自己的知识体系,将一个一个知识点形成点再到面,这样能更加深刻的理解,而且有自己的侧重点,我就列举一下我的准备的方向:

1、Activity生命周期?

onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDetroy()

2、Service生命周期?

service 启动方式有两种

  • 一种是通过startService()方式进行启动
  • 另一种是通过bindService()方式进行启动。

不同的启动方式他们的生命周期是不一样.

通过startService()这种方式启动的service
生命周期是这样:
调用startService() --> onCreate()--> onStartConmon()--> onDestroy()。
这种方式启动的话,需要注意一下几个问题:

  • 第一:当我们通过startService被调用以后,多次在调用startService(),onCreate()方法也只会被调用一次,而onStartConmon()会被多次调用,当我们调用stopService()的时候,onDestroy()就会被调用,从而销毁服务。
  • 第二:当我们通过startService启动时候,通过intent传值,在onStartConmon()方法中获取值的时候,一定要先判断intent是否为null。

通过bindService()方式进行绑定,这种方式绑定service
生命周期:
bindService-->onCreate()-->onBind()-->unBind()-->onDestroy() bindservice 这种方式进行启动service好处是更加便利activity中操作service,如果要在activity中调用,在需要在activity获取ServiceConnection对象,通过ServiceConnection来获取service中内部类的类对象,然后通过这个类对象就可以调用类中的方法,当然这个类需要继承Binder对象

3、Activity的启动过程(不要回答生命周期)

app启动的过程有两种情况

  • 第一种是从桌面launcher上点击相应的应用图标
  • 第二种是在activity中通过调用startActivity来启动一个新的activity。

我们创建一个新的项目,默认的根activity都是MainActivity,而所有的activity都是保存在堆栈中的,我们启动一个新的activity就会放在上一个activity上面,而我们从桌面点击应用图标的时候,由于launcher本身也是一个应用,当我们点击图标的时候,系统就会调用startActivitySately(),一般情况下,我们所启动的activity的相关信息都会保存在intent中,比如action,category等等。我们在安装这个应用的时候,系统也会启动一个PackaManagerService的管理服务,这个管理服务会对AndroidManifest.xml文件进行解析,从而得到应用程序中的相关信息,比如service,activity,Broadcast等等,然后获得相关组件的信息。当我们点击应用图标的时候,就会调用startActivitySately()方法,而这个方法内部则是调用startActivty(),而startActivity()方法最终还是会调用startActivityForResult()这个方法。而在startActivityForResult()这个方法。因为startActivityForResult()方法是有返回结果的,所以系统就直接给一个-1,就表示不需要结果返回了。而startActivityForResult()这个方法实际是通过Instrumentation类中的execStartActivity()方法来启动activity,Instrumentation这个类主要作用就是监控程序和系统之间的交互。而在这个execStartActivity()方法中会获取ActivityManagerService的代理对象,通过这个代理对象进行启动activity。启动会就会调用一个checkStartActivityResult()方法,如果说没有在配置清单中配置有这个组件,就会在这个方法中抛出异常了。当然最后是调用的是Application.scheduleLaunchActivity()进行启动activity,而这个方法中通过获取得到一个ActivityClientRecord对象,而这个ActivityClientRecord通过handler来进行消息的发送,系统内部会将每一个activity组件使用ActivityClientRecord对象来进行描述,而ActivityClientRecord对象中保存有一个LoaderApk对象,通过这个对象调用handleLaunchActivity来启动activity组件,而页面的生命周期方法也就是在这个方法中进行调用。

4、Broadcast注册方式与区别

此处延伸:什么情况下用动态注册

Broadcast广播,注册方式主要有两种.

  • 第一种是静态注册,也可成为常驻型广播,这种广播需要在Androidmanifest.xml中进行注册,这中方式注册的广播,不受页面生命周期的影响,即使退出了页面,也可以收到广播这种广播一般用于想开机自启动啊等等,由于这种注册的方式的广播是常驻型广播,所以会占用CPU的资源。

  • 第二种是动态注册,而动态注册的话,是在代码中注册的,这种注册方式也叫非常驻型广播,受到生命周期的影响,退出页面后,就不会收到广播,我们通常运用在更新UI方面。这种注册方式优先级较高。最后需要解绑,否会会内存泄露

广播是分为有序广播和无序广播。

5、HttpClient与HttpUrlConnection的区别

此处延伸:Volley里用的哪种请求方式

首先HttpClient和HttpUrlConnection这两种方式都支持Https协议,都是以流的形式进行上传或者下载数据,也可以说是以流的形式进行数据的传输,还有ipv6,以及连接池等功能。HttpClient这个拥有非常多的API,所以如果想要进行扩展的话,并且不破坏它的兼容性的话,很难进行扩展,也就是这个原因,Google在Android6.0的时候,直接就弃用了这个HttpClient.

而HttpUrlConnection相对来说就是比较轻量级了,API比较少,容易扩展,并且能够满足Android大部分的数据传输。比较经典的一个框架volley,在Android 2.3版本以前都是使用Android HttpClient,在Android 2.3以后就使用了HttpUrlConnection。

二.中级→高级知识体系

6、java虚拟机和Dalvik虚拟机的区别

Java虚拟机:

  • java虚拟机基于栈。
    基于栈的机器必须使用指令来载入和操作栈上数据,所需指令更多更多。
  • java虚拟机运行的是java字节码。
    java类会被编译成一个或多个字节码.class文件.

Dalvik虚拟机:

  • dalvik虚拟机是基于寄存器的
  • Dalvik运行的是自定义的.dex字节码格式。
    java类被编译成.class文件后,会通过一个dx工具将所有的.class文件转换成一个.dex文件,然后dalvik虚拟机会从其中读取指令和数据.
  • 常量池已被修改为只使用32位的索引,以 简化解释器。
  • 一个应用,一个虚拟机实例,一个进程
    所有android应用的线程都是对应一个linux线程,都运行在自己的沙盒中,不同的应用在不同的进程中运行。每个android dalvik应用程序都被赋予了一个独立的linux PID(app_*)
7、进程保活(不死进程)

此处延伸:进程的优先级是什么

当前业界的Android进程保活手段主要分为黑、白、灰三种,其大致的实现思路如下:
黑色保活:
不同的app进程,用广播相互唤醒,包括利用系统提供的广播进行唤醒.

  • 白色保活:启动前台Service
  • 灰色保活:利用系统的漏洞启动前台Service

黑色保活
所谓黑色保活,就是利用不同的app进程使用广播来进行相互唤醒。举个3个比较常见的场景:

  • 场景1:开机,网络切换、拍照、拍视频时候,利用系统产生的广播唤醒app
  • 场景2:接入第三方SDK也会唤醒相应的app进程,如微信sdk会唤醒微信,支付宝sdk会唤醒支付宝。由此发散开去,就会直接触发了下面的 场景3
  • 场景3:假如你手机里装了支付宝、淘宝、天猫、UC等阿里系的app,那么你打开任意一个阿里系的app后,有可能就顺便把其他阿里系的app给唤醒了。(只是拿阿里打个比方,其实BAT系都差不多)

白色保活
白色保活手段非常简单,就是调用系统api启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification,用来让用户知道有这样一个app在运行着,哪怕当前的app退到了后台。

灰色保活
灰色保活,这种保活手段是应用范围最广泛。它是利用系统的漏洞来启动一个前台的Service进程,与普通的启动方式区别在于,它不会在系统通知栏处出现一个Notification,看起来就如同运行着一个后台Service进程一样。这样做带来的好处就是,用户无法察觉到你运行着一个前台进程(因为看不到Notification),但你的进程优先级又是高于普通后台进程的。那么如何利用系统的漏洞呢,大致的实现思路和代码如下:

思路一:API < 18,启动前台Service时直接传入new Notification();
思路二:API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理
熟悉Android系统的童鞋都知道,系统出于体验和性能上的考虑,app在退到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来。打开的应用越多,后台缓存的进程也越多。在系统内存不足的情况下,系统开始依据自身的一套进程回收机制来判断要kill掉哪些进程,以腾出内存来供给需要的app。这套杀进程回收内存的机制就叫 Low Memory Killer,它是基于Linux内核的OOM Killer(Out-Of-Memory killer)机制诞生。

进程的重要性,划分5级:

  • 前台进程(Foreground process)
  • 可见进程 (Visible process)
  • 服务进程(Service process)
  • 后台进程(Background process)
  • 空进程 (Empty process)

了解完Low Memory Killer,再科普一下oom_adj。什么是oom_adj?它是 linux内核分配给每个系统进程的一个值,代表进程的优先级,进程回收机制就是根据这个优先级来决定是否进行回收。对于oom_adj的作用,你只需要记住以下几点即可:

进程的oom_adj越大,表示此进程优先级越低,越容易被杀回收;越小,表示进程优先级越高,越不容易被杀回收
普通app进程的oom_adj>=0,系统进程的oom_adj才可能<0

有些手机厂商把这些知名的app放入了自己的白名单中,保证了进程不死来提高用户体验(如微信、QQ、陌陌都在小米的白名单中)。如果从白名单中移除,他们终究还是和普通app一样躲避不了被杀的命运,为了尽量避免被杀,还是老老实实去做好优化工作吧。

所以,进程保活的根本方案终究还是回到了性能优化上,进程永生不死终究是个彻头彻尾的伪命题!

8、讲解一下Context

Context是一个抽象基类。在翻译为上下文,也可以理解为环境,是提供一些程序的运行环境基础信息。Context下有两个子类,ContextWrapper是上下文功能的封装类,而ContextImpl则是上下文功能的实现类。而ContextWrapper又有三个直接的子类, ContextThemeWrapper、Service和Application。其中,ContextThemeWrapper是一个带主题的封装类,而它有一个直接子类就是Activity,所以Activity和Service以及Application的Context是不一样的,只有Activity需要主题,Service不需要主题。

Context一共有三种类型,分别是Application、Activity和Service。这三个类虽然分别各种承担着不同的作用,但它们都属于Context的一种,而它们具体Context的功能则是由ContextImpl类去实现的,因此在绝大多数场景下,Activity、Service和Application这三种类型的Context都是可以通用的。

不过有几种场景比较特殊,比如启动Activity,还有弹出Dialog。出于安全原因的考虑,Android是不允许Activity或Dialog凭空出现的,一个Activity的启动必须要建立在另一个Activity的基础之上,也就是以此形成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog),因此在这种场景下,我们只能使用Activity类型的Context,否则将会出错。

getApplicationContext()和getApplication()方法得到的对象都是同一个application对象,只是对象的类型不一样。

Context数量 = Activity数量 + Service数量 + 1 (1为Application)

9、理解Activity,View,Window三者关系

这个问题真的很不好回答。所以这里先来个算是比较恰当的比喻来形容下它们的关系吧。Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图)LayoutInflater像剪刀,Xml配置像窗花图纸。

1:Activity构造的时候会初始化一个Window,准确的说是PhoneWindow。
2:这个PhoneWindow有一个ViewRoot,这个ViewRoot是一个View或者说ViewGroup,是最初始的根视图。
3:ViewRoot通过addView方法来一个个的添加View。比如TextView,Button等
4:这些View的事件监听,是由WindowManagerService来接受消息,并且回调Activity函数。比如onClickListener,onKeyDown等。

10、四种LaunchMode及其使用场景

此处延伸:栈(First In Last Out)与队列(First In First Out)的区别

栈与队列的区别:

  • 队列先进先出,栈先进后出
  • 对插入和删除操作的"限定"。 栈是限定只能在表的一端进行插入和删除操作的线性表。 队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。
  • 遍历数据速度不同

standard 模式
这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。使用场景:大多数Activity。

singleTop 模式
如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的onNewIntent()),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。使用场景如新闻类或者阅读类App的内容页面。

singleTask 模式
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。使用场景如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。

singleInstance 模式
在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent())。其效果相当于多个应用共享一个应用,不管谁激活该Activity 都会进入同一个应用中。使用场景如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。

11、View的绘制流程

自定义控件:

1、组合控件。这种自定义控件不需要我们自己绘制,而是使用原生控件组合成的新控件。如标题栏。
2、继承原有的控件。这种自定义控件在原生控件提供的方法外,可以自己添加一些方法。如制作圆角,圆形图片。
3、完全自定义控件:这个View上所展现的内容全部都是我们自己绘制出来的。比如说制作水波纹进度条。

View的绘制流程:OnMeasure()——>OnLayout()——>OnDraw()

第一步:OnMeasure():测量视图大小。从顶层父View到子View递归调用measure方法,measure方法又回调OnMeasure。
第二步:OnLayout():确定View位置,进行页面布局。从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。
第三步:OnDraw():绘制视图。
ViewRoot创建一个Canvas对象,然后调用OnDraw()。

六个步骤:

  • 绘制视图的背景;
  • 保存画布的图层(Layer);
  • 绘制View的内容;
  • 绘制View子视图,如果没有就不用;
  • 还原图层(Layer);
  • 绘制滚动条。
12、View,ViewGroup事件分发

1.Touch事件分发中只有两个主角:ViewGroup和View。

ViewGroup
包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent三个相关事件。

View
包含dispatchTouchEvent、onTouchEvent两个相关事件。
其中ViewGroup又继承于View。

2.ViewGroup和View组成了一个树状结构,根节点为Activity内部包含的一个ViewGroup。

3.触摸事件由Action_Down、Action_Move、Aciton_UP组成,其中一次完整的触摸事件中,Down和Up都只有一个,Move有若干个,可以为0个。

4.当Acitivty接收到Touch事件时,将遍历子View进行Down事件的分发。ViewGroup的遍历可以看成是递归的。分发的目的是为了找到真正要处理本次完整触摸事件的View,这个View会在onTouchuEvent结果返回true。

5.当某个子View返回true时,会中止Down事件的分发,同时在ViewGroup中记录该子View。接下去的Move和Up事件将由该子View直接进行处理。由于子View是保存在ViewGroup中的,多层ViewGroup的节点结构时,上级ViewGroup保存的会是真实处理事件的View所在的ViewGroup对象:如ViewGroup0-ViewGroup1-TextView的结构中,TextView返回了true,它将被保存在ViewGroup1中,而ViewGroup1也会返回true,被保存在ViewGroup0中。当Move和UP事件来时,会先从ViewGroup0传递至ViewGroup1,再由ViewGroup1传递至TextView。

6.当ViewGroup中所有子View都不捕获Down事件时,将触发ViewGroup自身的onTouch事件。触发的方式是调用super.dispatchTouchEvent函数,即父类View的dispatchTouchEvent方法。在所有子View都不处理的情况下,触发Acitivity的onTouchEvent方法。

7.onInterceptTouchEvent有两个作用:

  • 拦截Down事件的分发。
  • 中止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。
13、保存Activity状态

onSaveInstanceState(Bundle)会在activity转入后台状态之前被调用,也就是onStop()方法之前,onPause方法之后被调用;

14、Android中的几种动画

帧动画:
指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果,比如想听的律动条。

补间动画:
指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有Alpha、Scale、Translate、Rotate四种效果。
注意:只是在视图层实现了动画效果,并没有真正改变View的属性,比如滑动列表,改变标题栏的透明度。

属性动画:
在Android3.0的时候才支持,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。比如view的旋转,放大,缩小。

15、Android中跨进程通讯的几种方式

Android跨进程通信,像intent,contentProvider.广播,service都可以跨进程通信。

intent:
这种跨进程方式并不是访问内存的形式,它需要传递一个uri,比如说打电话。

contentProvider:
这种形式,是使用数据共享的形式进行数据共享。

service:
远程服务,比如aidl

广播:
广播 包含静态广播,动态广播。

三.进阶知识体系

16、AIDL理解

此处延伸:简述Binder

AIDL:
每一个进程都有自己的Dalvik VM实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行着自己的操作,都在自己的那片狭小的空间里过完自己的一生。而aidl就类似与两个进程之间的桥梁,使得两个进程之间可以进行数据的传输,跨进程通信有多种选择,比如BroadcastReceiver , Messenger等,但是 BroadcastReceiver占用的系统资源比较多,如果是频繁的跨进程通信的话显然是不可取的;Messenger进行跨进程通信时请求队列是同步进行的,无法并发执行。

Binder机制简单理解:
在Android系统的Binder机制中,是有Client,Service,ServiceManager,Binder驱动程序组成的,其中Client,service,Service Manager运行在用户空间,Binder驱动程序是运行在内核空间的。而Binder就是把这4种组件粘合在一块的粘合剂,其中核心的组件就是Binder驱动程序,Service Manager提供辅助管理的功能,而Client和Service正是在Binder驱动程序和Service Manager提供的基础设施上实现C/S 之间的通信。其中Binder驱动程序提供设备文件/dev/binder与用户控件进行交互,

Client、Service,Service Manager通过open和ioctl文件操作相应的方法与Binder驱动程序进行通信。而Client和Service之间的进程间通信是通过Binder驱动程序间接实现的。而Binder Manager是一个守护进程,用来管理Service,并向Client提供查询Service接口的能力。

17、Handler的原理

Android中主线程是不能进行耗时操作的,子线程是不能进行更新UI的。所以就有了handler,它的作用就是实现线程之间的通信。

handler整个流程中,主要有四个对象,
handler,Message,MessageQueue,Looper。当应用创建的时候,就会在主线程中创建handler对象,

我们通过要传送的消息保存到Message中,handler通过调用sendMessage方法将Message发送到MessageQueue中,Looper对象就会不断的调用loop()方法

不断的从MessageQueue中取出Message交给handler进行处理。从而实现线程之间的通信。

18、Binder机制原理

在Android系统的Binder机制中,是有Client,Service,ServiceManager,Binder驱动程序组成的,其中Client,service,Service Manager运行在用户空间,Binder驱动程序是运行在内核空间的。而Binder就是把这4种组件粘合在一块的粘合剂,其中核心的组件就是Binder驱动程序,Service Manager提供辅助管理的功能,而Client和Service正是在Binder驱动程序和Service Manager提供的基础设施上实现C/S之间的通信。其中Binder驱动程序提供设备文件/dev/binder与用户控件进行交互,Client、Service,Service Manager通过open和ioctl文件操作相应的方法与Binder驱动程序进行通信。而Client和Service之间的进程间通信是通过Binder驱动程序间接实现的。而Binder Manager是一个守护进程,用来管理Service,并向Client提供查询Service接口的能力。

19、热修复的原理

我们知道Java虚拟机 —— JVM是加载类的class文件的,而Android虚拟机——Dalvik/ART VM是加载类的dex文件,而他们加载类的时候都需要ClassLoader,ClassLoader有一个子BaseDexClassLoader,而BaseDexClassLoader下有一个数组——DexPathList,是用来存放dex文件,当BaseDexClassLoader通过调用findClass方法时,实际上就是遍历数组,找到相应的dex文件,找到,则直接将它return。而热修复的解决方法就是将新的dex添加到该集合中,并且是在旧的dex的前面,所以就会优先被取出来并且return返回。

20、Android内存泄露及管理
  • 内存溢出(OOM)和内存泄露(对象无法被回收)的区别。
  • 引起内存泄露的原因
  • 内存泄露检测工具 ------>LeakCanary

内存溢出out of memory:
是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;
比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存溢出通俗的讲就是内存不够用。

内存泄露memory leak:
是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光

内存泄露原因:
一、Handler 引起的内存泄漏。
解决:将Handler声明为静态内部类,就不会持有外部类SecondActivity的引用,其生命周期就和外部类无关,
如果Handler里面需要context的话,可以通过弱引用方式引用外部类

二、单例模式引起的内存泄漏。
解决:Context是ApplicationContext,由于ApplicationContext的生命周期是和app一致的,不会导致内存泄漏

三、非静态内部类创建静态实例引起的内存泄漏。
解决:把内部类修改为静态的就可以避免内存泄漏了

四、非静态匿名内部类引起的内存泄漏。
解决:将匿名内部类设置为静态的。

五、注册/反注册未成对使用引起的内存泄漏。
注册广播接受器、EventBus等,记得解绑。

六、资源对象没有关闭引起的内存泄漏。
在这些资源不使用的时候,记得调用相应的类似close()、destroy()、recycler()、release()等方法释放。

七、集合对象没有及时清理引起的内存泄漏。
通常会把一些对象装入到集合中,当不使用的时候一定要记得及时清理集合,让相关对象不再被引用。

21、Fragment与Fragment、Activity通信的方式
  • 直接在一个Fragment中调用另外一个Fragment中的方法
  • 使用接口回调
  • 使用广播
  • Fragment直接调用Activity中的public方法
22、Android UI适配

字体使用sp,
dp,多使用match_parent,wrap_content,weight
图片资源,不同图片的的分辨率,放在相应的文件夹下可使用百分比代替。

23、app优化

app优化:

工具:Hierarchy Viewer 分析布局
工具:TraceView测试分析耗时

App启动优化

布局优化
响应优化
内存优化
电池使用优化
网络优化

App启动的方式有三种:
冷启动:
App没有启动过或App进程被killed, 系统中不存在该App进程, 此时启动App即为冷启动。

热启动:
热启动意味着你的App进程只是处于后台, 系统只是将其从后台带到前台, 展示给用户。

介于冷启动和热启动之间,
一般来说在以下两种情况下发生:

(1)用户back退出了App, 然后又启动.
App进程可能还在运行, 但是activity需要重建。
(2)用户退出App后, 系统可能由于内存原因将App杀死, 进程和activity都需要重启, 但是可以在onCreate中将被动杀死锁保存的状态(saved instance state)恢复。

启动优化:
Application的onCreate(特别是第三方SDK初始化),首屏Activity的渲染都不要进行耗时操作,如果有,就可以放到子线程或者IntentService中。

布局优化
尽量不要过于复杂的嵌套。可以使用<include>,<merge>,<ViewStub>

响应优化
Android系统每隔16ms会发出VSYNC信号重绘我们的界面(Activity)。

页面卡顿的原因:
(1)过于复杂的布局.
(2)UI线程的复杂运算
(3)频繁的GC
导致频繁GC有两个原因:
1、内存抖动, 即大量的对象被创建又在短时间内马上被释放.
2、瞬间产生大量的对象会严重占用内存区域。

电池使用优化
工具:Batterystats & bugreport

(1)优化网络请求
(2)定位中使用GPS, 请记得及时关闭

网络优化
网络连接对用户的影响:流量,电量,用户等待,可在Android studio下方logcat旁边那个工具Network Monitor检测

API设计:
App与Server之间的API设计要考虑网络请求的频次, 资源的状态等. 以便App可以以较少的请求来完成业务需求和界面的展示.

Gzip压缩:
使用Gzip来压缩request和response, 减少传输数据量, 从而减少流量消耗.

图片的Size:
可以在获取图片时告知服务器需要的图片的宽高, 以便服务器给出合适的图片, 避免浪费.

网络缓存:
适当的缓存, 既可以让我们的应用看起来更快, 也能避免一些不必要的流量消耗.

24、图片优化

(1)对图片本身进行操作。
尽量不要使用setImageBitmap、setImageResource、BitmapFactory.decodeResource来设置一张大图,因为这些方法在完成decode后,最终都是通过 java 层的 createBitmap来完成的,需要消耗更多内存.
(2)图片进行缩放的比例,SDK中建议其值是2的指数值,值越大会导致图片不清晰。
(3)不用的图片记得调用图片的recycle()方法

25、HybridApp WebView和JS交互

Android与JS通过WebView互相调用方法,实际上是:
Android去调用JS的代码

通过WebView的loadUrl(),使用该方法比较简洁,方便。但是效率比较低,获取返回值比较困难。
通过WebView的evaluateJavascript(),该方法效率高,但是4.4以上的版本才支持,4.4以下版本不支持。所以建议两者混合使用。

JS去调用Android的代码

  • 通过WebView的addJavascriptInterface()进行对象映射 ,该方法使用简单,仅将Android对象和JS对象映射即可,但是存在比较大的漏洞。
    漏洞产生原因是:当JS拿到Android这个对象后,就可以调用这个Android对象中所有的方法,包括系统类(java.lang.Runtime 类),从而进行任意代码执行。

解决方法:

(1)Google 在Android 4.2版本中规定对被调用的函数以 @JavascriptInterface进行注解从而避免漏洞攻击。
(2)在Android 4.2版本之前采用拦截prompt()进行漏洞修复。

  • 通过 WebViewClient的shouldOverrideUrlLoading ()方法回调拦截url 。
    这种方式的优点:
    不存在方式1的漏洞;
    缺点:JS获取Android方法的返回值复杂。(ios主要用的是这个方式)

(1)Android通过 WebViewClient 的回调方法shouldOverrideUrlLoading ()拦截 url
(2)解析该url的协议
(3)如果检测到是预先约定好的协议,就调用相应方法

  • 通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息
    这种方式的优点:不存在方式1的漏洞;缺点:JS获取Android方法的返回值复杂。
26、JAVA GC原理

垃圾收集算法的核心思想是:
对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能。

27、ANR

ANR全名Application Not Responding, 也就是"应用无响应". 当操作在一段时间内系统无法处理时, 系统层面会弹出上图那样的ANR对话框.

产生原因:

(1)5s内无法响应用户输入事件(例如键盘输入, 触摸屏幕等).
(2)BroadcastReceiver在10s内无法结束
(3)Service 20s内无法结束(低概率)

解决方式:

(1)不要在主线程中做耗时的操作,而应放在子线程中来实现。如onCreate()和onResume()里尽可能少的去做创建操作。
(2)应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。
(3)避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
(4)service是运行在主线程的,所以在service中做耗时操作,必须要放在子线程中。

28、设计模式

此处延伸:Double Check的写法被要求写出来。
单例模式:分为恶汉式和懒汉式
恶汉式:

public class Singleton 
{ 
    private static Singleton instance = new Singleton(); 
    public static Singleton getInstance() 
    { 
        return instance ; 
    } 
}

懒汉式:

public class Singleton02 
{ 
   private static Singleton02 instance; 
   public static Singleton02 getInstance() 
   { 
       if (instance == null) 
       { 
           synchronized (Singleton02.class) 
           { 
               if (instance == null) 
               { 
                   instance = new Singleton02(); 
               } 
           } 
       } 
       return instance; 
   } 
}
29、MVP,MVC,MVVM

此处延伸:手写mvp例子,与mvc之间的区别,mvp的优势

MVP模式
对应着
Model:业务逻辑和实体模型,
view:对应着activity,负责View的绘制以及与用户交互,
Presenter:负责View和Model之间的交互,

MVP模式是在MVC模式的基础上,将Model与View彻底分离使得项目的耦合性更低,在Mvc中项目中的activity对应着mvc中的C–Controllor,而项目中的逻辑处理都是在这个C中处理,同时View与Model之间的交互,也是也就是说,mvc中所有的逻辑交互和用户交互,都是放在Controllor中,也就是activity中。View和model是可以直接通信的。而MVP模式则是分离的更加彻底,分工更加明确Model业务逻辑和实体模型,view负责与用户交互,Presenter 负责完成View于Model间的交互,MVP和MVC最大的区别是MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。还有一点就是Presenter与View之间的交互是通过接口的

30、JNI

(1)安装和下载Cygwin,下载 Android NDK
(2)在ndk项目中JNI接口的设计
(3)使用C/C++实现本地方法
(4)JNI生成动态链接库.so文件
(5)将动态链接库复制到java工程,在java工程中调用,运行java工程即可

31、RecyclerView和ListView的区别

RecyclerView可以完成ListView,GridView的效果,还可以完成瀑布流的效果。同时还可以设置列表的滚动方向(垂直或者水平);
RecyclerView中view的复用不需要开发者自己写代码,系统已经帮封装完成了。
RecyclerView可以进行局部刷新。
RecyclerView提供了API来实现item的动画效果。

在性能上:
如果需要频繁的刷新数据,需要添加动画,则RecyclerView有较大的优势。
如果只是作为列表展示,则两者区别并不是很大。

四.NDK

更多完整项目下载。未完待续。源码。图文知识后续上传github。
可以点击关于我 联系我获取

前端面试备战:从牛客面经到高频考点与手写题全解析 前端面试准备不仅关乎知识记忆,更在于构建系统化的技术认知。从JavaScript核心原理到浏览器缓存与事件循环,深入理解底层机制是应对复杂问题的关键。手写代码能力如防抖节流、Promise实现,则体现了工程实践的真功夫。在当前竞争激烈的技术招聘环境下,掌握这些基础概念能显著提升面试表现。无论是面对框架原理追问还是性能优化场景题,系统化的知识体系与场景迁移能力都至关重要。本文基于牛客面经整理,涵盖高频考点、手写题解析与备战策略,助你从‘背题’走向‘搭体系’。 阅读详情

相关推荐

Cadence Virtuoso Layout 版图绘制

画好原理图,打好pin脚(pin最好以全大写的形式书写,以防后续操作中可能出现Bug) 查看所使用工艺库的design rule文件,确定栅格单位设置大小 在准备绘制的原理图界面启动layout XL/GXL 在layout界面按e,设置网格大小与design rule匹配 直接根据原理图生成版图 根据原理图连接关系显示版图中未连接的飞线 查看和更改原理图与版图中器件对应的链接关系 shift + f:显示器件版图细节 版图的构成:元器件(工艺厂商提供)、器件连接、阱连接、IO和PAD模拟电路

bobo_supper的博客 2万+

Android 面试题中高级

1、Activity生命周期?onCreate() -&gt; onStart() -&gt; onResume() -&gt; onPause() -&gt; onStop() -&gt; onDetroy()    onReast() 2、Service生命周期?service 启动方式有两种,一种是通过startService()方式进行启动,另一种是通过bindService()方式进行启...

weixin_41205419的博客 2661

VCS 2018 环境下,手把手教你用 UVMC 搞定 SystemC 和 SystemVerilog 混合仿真(附完整代码)

本文详细介绍了在VCS 2018环境下使用UVMC实现SystemC和SystemVerilog混合仿真的完整指南。从环境配置、工具链设置到UVMC通信机制解析,提供了实战案例和高级调试技巧,帮助开发者高效搭建复杂验证环境。特别适合需要处理跨语言仿真的芯片验证工程师。

weixin_30952535的博客 285

Android2017-2018最新面试题(3-5年经验个人面试经历)

2017-2018最新Android面试题 版权声明:本文为博主原创文章,未经博主允许不得转载。 原文链接:http://blog.youkuaiyun.com/huangqili1314/article/details/72792682 大家好,在跟大家讲述自己的面试经历,以及遇到的面试题前,先说说几句题外话。 接触Android已经3年,在工作中遇到疑难问题总是在网上(csdn大牛博客,stack...

启立豆 28万+

Supermind量化实战:我如何给双均线策略加上“止损”和“仓位管理”,让回测收益更稳健

本文详细介绍了如何在Supermind平台上为双均线策略添加止损和仓位管理模块,以提升量化交易的稳健性。通过Python实现动态止损和智能仓位管理,策略的年化收益率从12.3%提升至15.8%,最大回撤从58.7%降至22.4%,Sharpe比率显著提高。这些实战技巧适用于量化交易爱好者,帮助他们在黑天鹅行情中保持收益稳定。

weixin_42567752的博客 362

利用腾讯云轻量服务器快速搭建网站CDN

腾讯云的轻量最近在主机和站长中间可谓是占尽来风头,优秀的线路,低廉的价格使得越来越多的人开始使用腾讯云的轻量级服务器来部署应用。由于腾讯云轻量服务器的海外服务器电信走的是CN2GIA线路带宽30m挺适合做CDN的,我就记录一下如何利用腾讯云香港的轻量服务器搭建一个CDN。 购买服务器 首先选购服务器,最近腾讯云在做活动,力度很大国内备案用户可以选用国内的服务器最低128元/年,未备案的可以选用香港或者新加坡的服务器。 购买链接 服务器系统选Debian、Ubuntu、centos都可以 一键脚

demo_top的博客 2563

Android 面试会问到的面试题(持续更新中)

Java基础 1.内存泄露的原因 资源对象没关闭。如Cursor、File等资源。他们会在finalize中关闭,但这样效率太低。容易造成内存泄露。SQLiteCursor,当数据量大的时候容易泄露 使用Adapter时,没有使用系统缓存的converView。 即时调用recycle()释放不再使用的Bitmap。适当降低Bitmap的采样率,如: BitmapFact...

zkbilian的博客 4628

Altium Designer操作技巧(12)——如何进行邮票孔拼版?

【摘要】本文详细介绍了PCB设计中邮票孔拼板的全流程操作方法。首先解释了邮票孔拼板的定义、核心目的(提高贴片效率、方便生产)和适用场景(异形板、V-CUT无法实现的情况)。重点阐述了关键设计参数,包括孔径、数量、间隙等规范要求,并提供了两种具体操作方案:传统复制粘贴法和新版阵列放置法。文章通过图文详细演示了从PCB复制、邮票孔添加、板框定义到定位孔和Mark点设置的完整步骤,最后强调了对称性、非金属化孔等设计要点,以及需要与板厂确认工艺参数等注意事项。

u012526819的博客 1672

深入探索Activity生命周期以及启动过程

1.各个生命周期的作用 1.onCreate() 可以进行初始化操作,初始化组件以及布局资源。此时Activity处于不可见状态。 2.onStart() 表示Activity在启动,前台还没有显示。 3.onResume() 表示Activity已经在屏幕上显示UI。 4.onPause() 此方法回调时,Activity正在停止(Paused形态),通常接下来 onStop() 会被回调 ...

callmeL的博客 716

Windows 11 安装 OpenClaw(龙虾):不用WSL、不用虚拟机、启动、使用、停止、卸载

本文详解 Windows 11 原生安装 OpenClaw(龙虾)全流程,无需 WSL 或虚拟机。涵盖环境配置、安全警示、模型接入(如通义千问)及技能初始化。提供启动、文件自动化操作、停止与卸载的完整指南,并附常见认证过期解决方案。助您快速部署本地 AI 智能体,实现电脑操作自动化,提升工作效率。

寒水馨 · 轻量级技术文档 · hanshuixin.org 897

opencv 双目摄像头拍照(分别左右镜头拍照)

准备一个usb线的双目同步摄像头: 运行环境是vc2015,opencv3.1。 将左右两个摄像头拍到的图片分别保存起来。 1)适用条件 双目同步摄像头(两个镜头,共用一个设备ID) 使用语言:C++ 、opencv库 摄像头 分辨率2560*960 或以上。 源程序: #include"stdafx.h" #include<iostream&g...

黎国溥 1万+

精准突击2026金三银四Java面试题及学习储备计划,稳拿大厂offer

刷题平台的选择与使用如今有许多知名的算法刷题平台,如 LeetCode、牛客网、HackerRank 等。LeetCode 上收集了大量的面试算法题,涵盖了各种难度级别和类型,并且有很多用户分享的解题思路和代码,比较适合准备大厂面试的开发者。我们可以根据自己的水平选择合适难度的题目开始练习,从简单题入手,逐步提高解题能力和信心。牛客网则有很多针对国内大厂的真题和模拟题,并且提供了在线测试和交流社区,方便我们了解大厂的面试风格和考察重点。

IT_1024的博客 837

uniapp:实现APP获取陀螺仪数据、加速传感器、线性加速传感器,uniApp实时监听陀螺仪【XYZ】数据及停止监听与资源释放等功能示例源码,根据需求做功能(完美兼容Android安卓、苹果ios)

uniapp陀螺仪,uniapp加速传感器,uniapp线性加速传感器,APP陀螺仪数据,uniapp app 端获取陀螺仪数据示例代码,手机中获取陀螺仪的数据,uniApp实时获取陀螺仪xyz数据,android陀螺仪方向,获得陀螺仪传感器,处理传感器数据,停止监听与资源释放,Android使用陀螺仪,uniapp苹果ios陀螺仪,uni-app设备之(加速计,罗盘,陀螺仪)插件安卓/IOS APP提供了获取陀螺仪数据的能力,手机陀螺仪传感器获得手机自身旋转的角度,陀螺仪获取旋转角度,陀螺仪、加速度传感器

✅ 精选推荐文章 4265

拼多多终面竟被“Out”了?春节宅家复习,备战金三银四拿offer

前言 随着互联网的发展,近两年来也涌现了越来越多的新兴互联网企业,除了BAT三巨头以外,其他互联网公司的表现力和实力也不容小觑,拼多多就是其一,如果要说拼多多是发展最快的新兴互联网公司之一,应该是没有多大争议的。那么,拼多多的面试又究竟是什么样呢?前段时间,去拼多多面试了Java岗,结果终面竟然被“out”掉了,不过好在已经定好计划,备战金三银四,相信一定能够拿下offer。 对了,以下会整理不少面试题、复习资料以及学习笔记的文档,可以免费提供,需要的直接(点击我)即可~ 拼多多面试过程全还原(Java

weixin_47083537的博客 648

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

【校招VIP】大厂暑假实习简历投递基本结束,没结果?其实大厂校招OFFER,很好拿

我们校招的大厂,会有自己的一个大纲,考察点非常的明确,所以准备起来很快很容易。第二点,市面上也没有这么多,由顶级的国内外的学校,参与的大厂就业计划。最后,还是介绍我们的稳拿计划,为了迎接5月份会到来的旺季,从本周开始,我们开始打折的优惠,而且越早报名,越是打骨折。我们稳拿计划的特点是,必须是一本以上,才能报名的就业计划。另一方面,只要就公司有一个比较合格的HR,那基本上想找到一个正式的实习生,是很难的。所以说没有面试的原因,要么是机试成绩太差,要么就是简历上的主项目不够出色,跟别人写的是一样的。

shuize123的博客 1415

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

热榜首推!阿里内部都在用的Java后端面试笔记,主流技术全在里面了!备战2023Java面试,拿理想offer

不少人准备技术面试,都会借助网上的“Java面试笔试题”,但这些资料大多专注于具体问题,解答也是点到即止,更有甚者连准确性都值得商榷,更不要说举一反三的讲解了。学习还是要脚踏实地,逐—梳理Java 相关技术的核心与要点,并找到高效归纳自己知识体系的方法。**备战2023Java面试,拿到理想offer,从任何时候开始,都不算晚。

chenxuyuana的博客 623

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

拼多多终面竟被“Out”了?春节宅家复习,备战金三银四拿offer,美的研发面试难不难

关于这次拼多多的三面,我也是一脸懵逼的,原以为顺顺利利,但却没有了下文,关键是自己也不自己自己挂在了哪里,问题都还答得算是顺利,对自己的表现也挺满意,可能我个人唯一的不足就是主观性比较强,所以交流过程中会给面试官不适感吧。实际上,根据我们的面经来看,是能够发现大厂的面试特点的,能够整理出一些核心技术知识点,面试时,面试官会有针对性的来提问。今年春节提前,相信2月就会提前进入招聘旺季,时间较短,比较紧促,所以最快的复习方式就是刷题,前端时间自己也整理了非常多的面试题,包括核心知识点、大厂面试集锦等等。

2401_87555412的博客 586

浏览器能开启几个ajax线程并发_面试美团被问到了Redis,搞懂这几个问题,让你轻松吊打面试官...

每一个程序员都拥有一座大厂梦,很多Java开发者面试之前,可能没有较长的工作时间或者较为丰富的工作经验,所以不知道互联网公司或者一线互联网公司技术面试都会问哪些问题? 再加上可能自己准备也不充分,去面试没几个回合就被面试官几个问题打蒙了,最后以惨败收场。今天针对这类的Java工程师们总结一下关于互联网企业以及一些大厂必问的面试题—Redis做一个面试分享,让即将面试或是有想法跳槽的读者朋友们对面试...

weixin_39843093的博客 97

程序员必看!拿下我人生中第7个Offer,真香

前言 每年的3、4月份是各大企业为明年拓展业务大量吸纳人才的关键时期,招聘需求集中、空缺岗位多,用人单位也习惯在初秋进行大规模招聘。 金九银十,招聘旺季,也是一个求职旺季。 不打无准备的仗,在这种关键时期,各大公司的薪资待遇等信息就变得相当重要,特别是对那些刚出校门或者是第一次跳槽的朋友们,知己知彼方能百战不殆。 在国内就业环境中,以腾讯、阿里等大厂为代表的互联网公司一直都是求职者眼中的香饽饽,“大厂工作经历”相当于一块金字招牌。 今天我帮大家搜集整理了一份薪资、职级、考核、晋升条件资料,都是互联网大厂。我

m0_56037919的博客 191

最新校招备战攻略,AI知识要点+面试笔记,GitHub超2万星

转载于新智元 来源:Github编辑:元子【新智元导读】正值春招旺季,同时又面对即将到来的秋招,同学们要如何进行备战呢?这里介绍一个GitHub超过2万星的项目,搜集了机器学习...

计算机与软件考研 213

2026求职趋势:微证书化与人机协同面试解析

在数字化转型浪潮下,求职市场正经历结构性变革。微证书认证体系通过模块化技能验证重塑人才评价标准,其核心价值在于实现技能组合的可验证与可移植性。与此同时,人机协同面试成为技术评估新范式,考察候选人调试AI输出与解释技术决策的复合能力。这些变化源于企业用人需求向精准匹配的转变,以及AI招聘工具带来的流程革新。对于开发者而言,掌握GitHub实战项目展示、API对接能力等工程实践技能,结合持续更新的纳米学位认证,将成为斩获优质offer的关键竞争力。当前头部企业已普遍采用动态岗位匹配机制,理解这些趋势对把握新兴数

weixin_30709061的博客 279

从入门到精通!拿下我人生中第7个Offer,真香

前言 每年的3、4月份是各大企业为明年拓展业务大量吸纳人才的关键时期,招聘需求集中、空缺岗位多,用人单位也习惯在初秋进行大规模招聘。 金九银十,招聘旺季,也是一个求职旺季。 不打无准备的仗,在这种关键时期,各大公司的薪资待遇等信息就变得相当重要,特别是对那些刚出校门或者是第一次跳槽的朋友们,知己知彼方能百战不殆。 在国内就业环境中,以腾讯、阿里等大厂为代表的互联网公司一直都是求职者眼中的香饽饽,“大厂工作经历”相当于一块金字招牌。 今天我帮大家搜集整理了一份薪资、职级、考核、晋升条件资料,都是互联网大厂。我

CHAMPION8888的博客 203
上一篇: 灵魂一问,如何彻底防止反编译?
下一篇: 架构师基础技能:序列化与反序列化,Android的Parcelable与Serializable区别是什么
初壹十五a
博客等级 码龄8年 146粉丝 257原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值