您现在的位置是:首页 > 编程 > 

Android面试高级:内存泄露,OOM,AR ,Devik 进程,Framework原理,Activity 生成一个 view,Android 中的动画,SurfaceView和View的

2025-07-28 10:51:21
Android面试高级:内存泄露,OOM,AR ,Devik 进程,Framework原理,Activity 生成一个 view,Android 中的动画,SurfaceView和View的 什么情况下会导致内存泄露内存泄露是个折腾的问题。根本原因:长生命周期的对象持有短生命周期的对象。短周期对象就无法及时释放。I. 静态集合类引起内存泄露主要是hashmap,Vector等,如果是静态集合 这

Android面试高级:内存泄露,OOM,AR ,Devik 进程,Framework原理,Activity 生成一个 view,Android 中的动画,SurfaceView和View的

什么情况下会导致内存泄露

内存泄露是个折腾的问题。

根本原因:长生命周期的对象持有短生命周期的对象。短周期对象就无法及时释放。

I. 静态集合类引起内存泄露

主要是hashmap,Vector等,如果是静态集合 这些集合没有及时setnull的话,就会一直持有这些对象。

II.remove 方法无法删除set集 Objects.hash(firstame, lastame);

经过测试,hashcode修改后,就没有办法remove了。

III. observer 我们在使用的时候,往往是addxxxlistener,但是当我们不需要的时候,忘记removexxxlistener,就容易内存leak。

广播没有unregisterrecevier

IV.各种数据链接没有关闭,数据库contentprovider,io,sokect等。cursor

V.内部类:

java中的内部类(匿名内部类),会持有宿主类的强引用this。

所以如果是new Thread这种,后台线程的操作,当线程没有执行结束时,activity不会被回收。

Context的引用,当TextView 等等都会持有上下文的引用。如果有static drawable,就会导致该内存无法释放。

VI.单例

单例 是一个全局的静态对象,当持有某个复制的类A是,A无法被释放,内存leak(泄漏)。

如何避免OOM

减少内存对象的占用

I.ArrayMap/SparseArray代替hashmap

II.避免在android里面使用Enum

III.减少bitmap的内存占用

  • inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。
  • decode format:解码格式,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异。
  • ARGB_8888:分别用8位来记录4个值,所以每个像素会占用2位。 ARGB_4444:分别用4位来记录4个值,所以每个像素会占用16位。 RGB_565:分别用5位、6位和5位来记录RGB三值,所以每个像素会占用16位。 ALPHA_8:根据注释应该是不保存颜值,只保存透明度(8位),每个像素会占用8位。

IV.减少资源图片的大小,过大的图片可以考虑分段加载

内存对象的重复利用

大多数对象的复用,都是利用对象池的技术。

I.listview/gridview/recycleview contentview的复用

II.inBitmap 属性对于内存对象的复用ARGB_8888/RBG_565/ARGB_4444/ALPHA_8

这个方法在某些条件下非常有用,比如要加载上千张图片的时候。

III.避免在ondraw方法里面 new对象

IV.StringBuilder 代替+

Android 中如何捕获未捕获的异常

CrashHandler

关键是实现Thread.UncaughtExceptionHandler

然后是在application的oncreate里面注册。

怎么避免AR

AR的关键是:处理超时,所以应该避免在UI线程,BroadcastReceiver 还有service主线程中,处理复杂的逻辑和计算

而交给work thread操作。

1)避免在activity里面做耗时操作,oncreate & onresume

2)避免在onReceiver里面做过多操作

)避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。

4)尽量使用handler来处理UI thread & workthread的交互。

如何解决AR

首先定位AR发生的log:

<pre style="margin: 0px 0px 0px 22px; white-space: pre-wrap; overflow-wrap: break-word; font-size: 12px !important; font-family: "Courier ew" !important;">04-01 1:12:11.572 I/InputDispatcher( 220): Application i****s not responding:Window{2b2610com./com..activity.SplitScreenActivitypaused=false}. 5009.8ms since event, 5009.5ms since waitstarted</pre>

<pre style="margin: 0px 0px 0px 22px; white-space: pre-wrap; overflow-wrap: break-word; font-size: 12px !important; font-family: "Courier ew" !important;">CPUusage from 461ms to 699ms ago ----CPU在AR发生前的使用情况 04-011:12:15.872 E/ActivityManager( 220): 100%TOTAL: 4.8% user + 7.6% kernel + 87% iowait 04-011:12:15.872 E/ActivityManager( 220): CPUusage from 697ms to 422ms later:-- AR后CPU的使用量</pre>

从log可以看出,cpu在做大量的io操作。

所以可以查看io操作的地方。

当然,也有可能cpu占用不高,那就是 主线程被block(块)住了。

Devik 进程,linux 进程,线程的区别

Dalvik进程。

每一个android app都会独立占用一个dvm虚拟机,运行在linux系统中。

所以dalvik进程和linux进程是可以理解为一个概念。

描述一下 android 的系统架构

从小到上就是:

linux kernel,lib dalvik vm ,application framework, app

Framework 工作方式及原理,Activity 是如何生成一个 view 的,机制是什么

Framework是android 系统对 linux kernel,lib库等封装,提供WMS,AMS,bind机制,handler-message机制等方式,供app使用。

简单来说framework就是提供app生存的环境。

1)Activity在attch方法的时候,会创建一个phonewindow(window的子类)

2)onCreate中的setContentView方法,会创建DecorView

)DecorView 的addview方法,会把layout中的布局加载进来。

Activity 创建一个 view 是通过 ondraw 画出来的, 画这个 view 之前呢,还会调用 onmeasure方法来计算显示的大小.

Surfaceview 是直接操作硬件的,因为视频播放对帧数有要求,onDraw 效率太低,不够使,Surfaceview 直接把数据写到显存。

Android FrameWork框架原理之进程是个什么东西

首先在Android中一个进程里只能放一个App。(特殊情况:同一个签名的两个App可以放到一个进程里,这里暂不考虑)。当一个App启动,系统zygote孵化器孵化出一个进程来执行这个App。zygote是个什么东东呢?zygote就是一个鸡,不停的生小鸡。zygote是一个进程,当需要启动一个进程来运行App时,zygote这个进程就把自己复制一份,放在另一个空间,就产生了一个进程给这个App来用。底层就是linux,fork(岔路口,分流)一个新进程。新fork的进程里面都有什么呢?

我们需要考虑的部分就是:里面有一个主线程,一个VM(虚拟机),一个Looper,一个MessageQueue。从这里就可以看出,一个进程里面有一个虚拟机。当然这是在Java层来看的,主线程就是UI线程,用来执行代码的,VM就是虚拟的机器,来执行Java字节码的。Looper和MessageQueue接下来细说。 进程产生主线程开始执行。这个时候先重申下线程是个什么东东。线程是执行一段代码用的,执行完这段代码,线程就死了。就这样。这时候我们想这样一个问题,主线程要执行什么,执行完了,死了,我们程序还运行个卵子。所以进程没死,线程应该永远也执行不完。Android中就是这样的,Android的主线程就是这样的,在一个whlie循环里打转转。怎样打转转的呢?主线程也就是一个普通的线程extends Thread来的嘛,只不过是由FrameWork写好的。启动它的时候调它的start(),由FrameWork在创建它的时候帮我们调了,它的start又调了run(),执行的代码就在run()里面。我们想让主线程不死,就让它在run()里面执行一个 while(true){ },它就一直傻呆在这儿了。这个时候我们已经确保了主线程不会死,但是它要做事啊,不然要它干什么,他怎么做事也就看while循环里的代码怎样写了,这个时候就要看上一篇文章提到的EIT造型了

它只需要在while循环的时候执行一个接口的某个方法,而这个方法是由我们来实现的,我们给他塞进去什么,他就要执行什么,这样不仅解决了要主线程不死,又能一直做事的要求了嘛。就是这么个理,下面看Google是怎么写的。 前面我们讲了进程进程里面不止有主线程,还有一个Looper,一个MessageQueue。其实Looper类里面个loop();主线程要的执行的while循环就写在loop()里。主线程的run()里只要调用Looper.loop(),就一直在这个loop()方法里走不出来了,一直在while循环里。而MessageQueue就是一个信箱,MessageQueue这个对象里有一个队列,队列里放的就是Message对象。(对这个机制不理解的可以看我前面有一篇写的关于Handler的博客),每个Message类里定义的有一个Runnable的属性,用来放代码段的。loop()里的每次循环就是到MessageQueue的Message队列里取一个Message对象,如果这个Message对象的Runnable属性不为null,就执行Runnable.run()里面的代码。就是这样咯。主线程的执行就是在Looper.loop()里面,循环的每一次都是去MessageQueue里面取一个Message,执行Message.Runnable.run()里面的代码。 这个讲完了再说说Message从哪里来的问题。这个Message是由FrameWork放到MessageQueue里面的。再从进程创建开始讲,主线程,MessageQueue和Looper都有了,主线程执行到loop()里一直打转转,MessageQueue还是空的没有消息给它处理,然后根据上一篇说的

由FrameWork框架的AMS(ActivityManagerService)来new出Activity对象,具体new出的是哪个Activity的实例,是根据Manifest文件里标明的那个启动的Activity。然后FrameWork给这个App的进程发出一个Message,放到MessageQueue里面,这个Message.runnable.run()里面的代码就是();这个Activity的引用是刚new出来的那个作为启动的myActivity(假设在Manifest里面写明的第一个启动的Activity是myActivity)。它的onCreate()方法是我们已经重写了,主线程这个时候就执行到我们写在myActivity的onCreate()中的代码咯。 上面已经解释了怎么从App启动执行到我们写在my()中代码。现在再申明一个事情,myActivity的生命周期都不是由它自己控制的,而是由框架控制的。执行顺序并不是简单的执行完onCreate()直接去执行onResume()的。onResume也是框架来通过传Message来让主线程执行的。一般情况下一on开头的函数都是主线程来执行的。比如onCreate(),onResume()。。。再简单说下从onCreate()怎样执行到onResume()的。 我们在my()里面有一行,setContentView(View),这行是要我们把自己写的布局传进去。无论是布局id还是直接一个view都是一样的,不做过多解释。(setContentView时究竟做了什么事,可以参见我的Activity的UI结构的那篇博客)我们知道有个View叫ContentView,我们把自己写的布局交给它,让他去显示。

由setContentView这个方法我们可以明显看出这里我们是调用基类的Activity的setContentView(),而Activity这个基类是框架定义的(参见上篇Acticity是EIT中的E&I由框架定义)。也就是说my()告诉框架我要setContentView(),然后框架把我们写的布局投射到屏幕上。这个调框架把布局投射到屏幕的动作,交由框架执行,框架中执行这些动作,到一个合适的时间,框架再发出Message,告诉主线程,现在是显示界面的时候了。然后主线程循环走到取Message,取出来发现框架让他执行(),他再去执行(),就这样框架决定了什么时候发出执行onResume的动作,主线程才去执行。这就保证了框架的主导权和控制权。由此我们也可以看出App执行的过程中,框架是全程参与的,而且处于主导地位,所以我在上篇说我们写的App只是一个套件组。至于怎么从onResume()再执行到其他的方法,和这个基本一样,不过多叙述。 由上面的分析我们可以看出,其实myActicity中的onCreate()和onResume等并不是真正的myActivity在这个时候创建和显示,这只是框架给App开发者留的接口,让App开发者去处理一些时机要做什么样的处理。其实像点击事件的响应也大致是这么一个流程,后面讲UI的时候再详细描述(其实点击事件就是一个订阅者模式,点击事件是由框架捕获交由主线程去处理的)。到此应该对Android整个App的启动有个基本的认知了吧。

Android 中的动画有哪几类,它们的特点和区别是什么

视图动画,或者说补间动画。只是视觉上的一个效果,实际view属性没有变化,性能好,但是支持方式少。

属性动画,通过变化属性来达到动画的效果,性能略差,支持点击等事件。android .0

帧动画,通过drawable一帧帧画出来。

Gif动画,原理同上,canvas画出来。

如何修改 Activity 进入和退出动画

overridePendingTransition

SurfaceView和View的区别

View在UI线程去更新自己; SurfaceView则在一个子线程中去更新自己 SurfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面在UI的主线程中更新动画,时间一旦太长就会出现问题 SurfaceView在新的线程中更新画面所以不会阻塞你的UI主线程,但是涉及到线程同步,需要SurfaceView中 thread处理.

SurfaceView(表面)优点: 可以在另一个线程中更新界面

不会阻碍界面的交互

View和SurfaceView的区别

基于View的绘图效率不高,主要用于动画变化较少的程序

SurfaceView 绘图效率较高,用于界面更新频繁的程序,如相机预览。

SurfaceView 可以在另一个线程中更新界面。

四、SurfaceView 使用方式: 1.布局中放入SurfaceView

2.实现SurfaceHolder.Callback

.绘制画布更新画布到SurfaceView(本例是在主线程中更新,可以另起一个线程更新)

通过lockCanvas()将返回绘制的canvas

绘制的过程中,对canvas的绘制不会立刻反应在界面上,直到执行unlockCanvasAndPost()提交刚才修改的界面

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-12-16,如有侵权请联系 cloudcommunity@tencent 删除进程面试内存原理动画

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1259700.html

相关标签:无
上传时间: 2025-07-28 06:30:20
留言与评论(共有 8 条评论)
本站网友 小儿湿疹膏
1分钟前 发表
bind机制
本站网友 西永二手房
9分钟前 发表
然后框架把我们写的布局投射到屏幕上
本站网友 俺去也防屏蔽
26分钟前 发表
执行完这段代码
本站网友 包装箱
12分钟前 发表
当然
本站网友 黑色素瘤早期症状图片
28分钟前 发表
OOM
本站网友 痣长在哪里好
14分钟前 发表
onResume也是框架来通过传Message来让主线程执行的
本站网友 长沙163医院
5分钟前 发表
所以如果是new Thread这种