文档章节

Android面试题及其答案(二)

abcijkxyz
 abcijkxyz
发布于 2016/07/30 17:23
字数 2596
阅读 10
收藏 1
点赞 0
评论 0

内存相关的问题在面试中被问到的概率还是比较大的,而且内存优化对于一个程序的性能而言也是至关重要的,现在就让我们一起来学习吧!

不废话,直接上干货~

一、内存泄漏

内存泄漏就是我们对某一内存空间的使用完成后没有释放。
主要原因:导致内存泄漏最主要的原因就是某些长存对象持有了一些其它应该被回收的对象的引用,导致垃圾回收器无法去回收掉这些对象。
出现的场景:
1.数据库的cursor没有关闭;
2.构造adapter时,没有使用缓存contentview;
3.Bitmap对象不使用时采用recycle()释放内存;
4.activity中的对象的生命周期大于activity;

二、内存溢出
内存溢出通俗理解就是软件(应用)运行需要的内存,超出了它可用的最大内存。
出现的场景:
1、使用大的Bitmap图片;

三、内存优化方法:
1、应该尽量避免static成员变量引用资源耗费过多的实例,比如Context。Context尽量使用Application Context,因为Application的Context的生命周期比较长,引用它不会出现内存泄露的问题。使用WeakReference代替强引用;
2、线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程生命周期的不可控。将线程内部类,改为静态内部类;
3、Bitmap问题:可以说出现OutOfMemory问题的绝大多原因都是因为Bitmap的问题。因为Bitmap占用的内存实在是太多了,它是一个“超级大胖子”,特别是分辨率大的图片,如果要显示多张那问题就更显著了;
如何解决Bitmap带给我们的内存问题?
1)及时的销毁,虽然系统能够确认Bitmap分配的内存最终会被销毁,但是由于它占用的内存过多,所以很可能会超过java堆的限制。因此,在用完Bitmap时,要及时的recycle掉。recycle并不能确定立即就会将Bitmap释放掉,但是会给虚拟机一个暗示:“该图片可以释放了”。
2)设置一定的采样率,有时候,我们要显示的区域很小,没有必要将整个图片都加载出来,而只需要记载一个缩小过的图片,这时候可以设置一定的采样率,那么就可以大大减小占用的内存。如下面的代码: 
BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的四分之一
3)使用LruCache缓存。
4、巧妙的运用软引用(SoftRefrence),有些时候,我们使用Bitmap后没有保留对它的引用,因此就无法调用Recycle函数。这时候巧妙的运用软引用,可以使Bitmap在内存快不足时得到有效的释放;
5、尽量使用9path图片,Adapter要使用convertView复用等等;
6、比较耗资源的对象及时的关闭,例如Cursor,各种传感器,Service 等等;
7、使用IntentService代替service,这种Service的最大特点就是当后台任务执行结束后会自动停止,在极大程度上避免了Service内存泄漏的可能性;
8、使用ProGuard,它除了混淆代码之外,还具有压缩和优化代码的功能。ProGuard会对我们的代码进行检索,删除一些无用的代码,并且会对类、字段、方法等进行重名,重命名之后的类、字段和方法名都会比原来简短很多,这样的话也就对内存的占用变得更少了;

ListView的优化方案:
1>、复用contentView:就是自定义适配器在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用;在这个方法中尽可能少创建view;
2>、异步加载图片:给contentView设置tag(setTag()),传入一个viewHolder对象,下次可以直接调用getTag()显示缓存中的数据,可以达到图像数据异步加载的效果;
3>.快速滑动列表时不显示图片:
当快速滑动列表时(SCROLL_STATE_FLING),item中的图片获取需要消耗资源的view,可以不显示出来;而处于其他两种状态:空闲(SCROLL_STATE_IDLE)和低俗拖动(SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来。
如果 listview 需要显示的 item 很多,就要考虑分页加载。比如一共要显示100条或者更多的时候,我们可以考虑先加载20条,等用户拉到列表底部的时候,再去加载接下来的20 条。
4>.如果自定义的item中有图片,需要处理图片(减少图片所占内存);
1.对图片进行边界压缩 2.用option类来保存图片大小 3.避免图片的实时缩放,最好预先缩放到视图大小

5>.尽量避免在listview适配器中使用线程,线程是产生内存泄露的主要原因,因为线程的生命周期不可控;


我们用具体的代码来看看,怎么避免OOM
事例一:

Handler mHandler = new Handler() {  
    @Override  
    public void handleMessage(Message msg) {  
        mImageView.setImageBitmap(mBitmap);
    }
}
在一个Activity中有一个Handler的内部类,Handler对象会隐式地持有该Activity的引用,而Handler通常会伴随着一个耗时的后台线程(例如网络下载图片)一起出现,这个后台线程在任务执行完毕之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用,这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束。
要解决这个问题有两种办法:
方法一:通过程序逻辑来进行保护。 
1).在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。 
2).如果你的Handler是被delay的Message持有了引用(调用了postDelayed,那么使用Handler的removeCallbacks()或removeCallbacksAndMessages(null)方法把消息对象从消息队列移除就行了。 
方法二:将Handler声明为静态类,并且加上Activity的弱引用。
静态类不持有外部类的对象,所以你的Activity就可以被回收了。代码如下:
static class MyHandler extends Handler {  
    WeakReference<Activity > mActivityReference;  
    MyHandler(Activity activity) {  
        mActivityReference= new WeakReference<Activity>(activity);
    }  
    @Override  
    public void handleMessage(Message msg) {  
        final Activity activity = mActivityReference.get();
        ImageView imageView= (ImageView)activity.findViewById(R.id.imageview);
        if (activity != null) {  
            mImageView.setImageBitmap(mBitmap);
        }
    }  
}
事例二、
new Thread(new Runnable() {  
    @Override  
    public void run() {  
        SystemClock.sleep(10000);  
    }  
}).start();
在Activity里声明了一个匿名内部类,如果Activity在销毁之前,线程的任务还未完成, 那么将导致Activity的内存资源无法回收,造成内存泄漏。
解决办法就是使用静态内部类,并且及时关闭线程,如下:
private static class MyThread extends Thread {  
    private boolean mRunning = false; 
    @Override  
    public void run() {  
        mRunning = true;  
        while (mRunning) {  
            SystemClock.sleep(1000);  
        }  
    }
    public void close() {  
        mRunning = false;  
    }  
}
我们在Activity退出时,可以在onDestroy()方法中显示的调用mThread.close();以此来结束该线程,这样在避免Activity OOM的同时也避免了线程的内存泄漏问题。

       每一个非静态内部类实例都会持有一个外部类的引用,若该引用是Activity的引用,那么该Activity在被销毁时将无法被回收。如果你的静态内部类需要一个相关Activity的引用以确保功能能够正常运行,那么你得确保你在对象中使用的是一个Activity的弱引用。
       这样看来static好像是解决OOM问题的重要武器,那是不是每个内部类都使用static来修改就好了呢,其实不然,只有当此类在全局多处用到时才这样做,因为static声明变量的生命周期其实是和APP的生命周期一样的,有点类似于Application。如果大量的使用的话,就会占据内存空间不释放,积少成多也会造成内存的不断开销,直至挂掉。static一般用来修饰基本数据类型或者轻量级对象,尽量避免修饰集合或者大对象,常用作修饰全局配置项、工具类方法、内部类。 


最后再来个扩展阅读...
GC回收的对象?
        如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收。也就是说,一个对象不被任何引用所指向,则该对象会在被GC发现的时候被回收;另外,如果一组对象中只包含互相的引用,而没有来自它们外部的引用(例如有两个对象A和B互相持有引用,但没有任何外部对象持有指向A或B的引用),这仍然属于不可到达,同样会被GC回收。 
什么是WeakReference? OOM问题解决方法?
        WeakReference弱引用,与强引用(即我们常说的引用)相对,它的特点是,GC在回收时会忽略掉弱引用,即就算有弱引用指向某对象,但只要该对象没有被强引用指向(实际上多数时候还要求没有软引用),该对象就会在被GC检查到时回收掉。如果对内存的开销比较关注的APP,可以考虑使用WeakReference,当GC回收扫过这块内存区域时就会回收;如果不是那么关注的话,可以使用SoftReference,它会在内存申请不足的情况下自动释放,同样也能解决OOM问题。同时Android自3.0以后也推出了LruCache类,使用LRU算法就释放内存,一样的能解决OOM,如果要兼容3.0以下的版本,需要导入v4包。

本文转载自:http://blog.csdn.net/wdong_love_cl/article/details/51588841

共有 人打赏支持
abcijkxyz
粉丝 60
博文 6195
码字总数 1876
作品 0
深圳
项目经理
Android开发工程师面试指南(面试题集附答案、简历模板)

给Android开发工程师的一份面试指南,包含面试题集与简历模板。 面试题集 面试题集里的答案大部分来源于我的博客,因此这个题集也相当于是我的博客的精华版,希望对需要面试的Android同学有所...

郭孝星 ⋅ 04/08 ⋅ 0

2018Android面试经历

面试中遇到的一些问题 Q1:ListView和RecyclerView的使用,就问我它们有什么区别? Q2:既然RecyclerView在很多方面能取代ListView,Google为什么没把ListView划上一条过时的横线? Q3:你用...

codeGoogle ⋅ 05/16 ⋅ 0

阿里腾讯百度头条美团iOS面试总结

阿里腾讯百度头条美团iOS面试总结 2018-05-30 15:24编辑: garace分类:程序人生来源:代码湾 互联网面试iOS 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发工程师 京东招聘iOS开发工...

garace ⋅ 05/30 ⋅ 0

如何理解并掌握 Java 数据结构

一说起“数据结构”可能很多同学都又交给老师了。但是实际工作中如果做得深入一些,特别是越往上发展,越大公司越离不开数据结构。本场 Chat 作者将带领大家重温《Java 数据结构》,讲解的内...

valada ⋅ 04/12 ⋅ 0

android仿IT之家、炫酷水波纹、Kotlin MVP项目、后台模拟点击、蜂巢迷宫小游戏等源码

Android精选源码 Android 炫酷的多重水波纹源码(http://www.apkbus.com/thread-598586-1-1.html) Android开发一款基于行为识别和个性化推荐的智能推荐APP(http://www.apkbus.com/thread-5985...

逆鳞龙 ⋅ 05/02 ⋅ 0

互联网三线城市春招Android面试笔记

概述: 坐标:福建福州 学历:专科(软件工程专业) 历时:2个月(2018.3.20~2018.5.17) 平台:前程无忧(51job.com)、智联招聘(zhaopin.com) 投递简历:62份(前程49+智联13) 面试:2...

E_Sun伊森 ⋅ 05/18 ⋅ 0

Android技能树 — 树基础知识小结(一)

前言: 现在安卓面试,对于数据结构的问题也越来越多了,也经常看到别人发的面试题都是问什么红黑树,二叉树查找等,所以我们虽然不会马上就会各种难的面试题,但起码树的基础知识还是要会的...

青蛙要fly ⋅ 05/04 ⋅ 0

我所经历的Android面试|掘金技术征文

概述 时隔一个多月,我又回来了。这段时间有不少人问我最近在干嘛,面经什么时候写,怎么这么久没更文了等等等等。当然了,最近我一直在执行了一次我计划了近半年的跳槽。总得而言还不错。说...

我就是马云飞 ⋅ 04/21 ⋅ 0

2018届android校招面试总结:百度,大疆,乐视,知乎

写在前面 四月面临了人生第一次比较重大的变化:现在的公司因为融资不利,收回了我的正式offer。这一波很伤... 所以在得知消息之后,接下来差不多一个月的时间里,自己开始了的频繁的面试之旅...

MDove ⋅ 04/29 ⋅ 0

android沉浸状态栏实现、地图多线路规划、Retrofit+RxJava+Jsoup+Mvp模式资讯类App等源码

Android精选源码 Android各种沉浸式状态栏实现源码(http://www.apkbus.com/thread-598927-1-1.html) Android自定义View实现炫酷的星期日期选择控件源码(http://www.apkbus.com/thread-59893...

逆鳞龙 ⋅ 05/08 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

如何将S/4HANA系统存储的图片文件用Java程序保存到本地

我在S/4HANA的事务码MM02里为Material维护图片文件作为附件: 通过如下简单的ABAP代码即可将图片文件的二进制内容读取出来: REPORT zgos_api.DATA ls_appl_object TYPE gos_s_obj.DA...

JerryWang_SAP ⋅ 32分钟前 ⋅ 0

Cube的构建过程

Cube 的构建方式有两种:全量构建和增量构建。两者的构建过程完全一样,区别在于构建时读取的数据源是全集还是子集。 Cube的构建步骤: 1.创建临时的 Hive 平表(从 Hive 读取数据)。 2.计算...

无精疯 ⋅ 37分钟前 ⋅ 0

云计算的选择悖论如何对待?

导读 人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云...

问题终结者 ⋅ 40分钟前 ⋅ 0

637. Average of Levels in Binary Tree - LeetCode

Question 637. Average of Levels in Binary Tree Solution 思路:定义一个map,层数作为key,value保存每层的元素个数和所有元素的和,遍历这个树,把map里面填值,遍历结束后,再遍历这个map,把每...

yysue ⋅ 54分钟前 ⋅ 0

IDEA配置和使用

版本控制 svn IDEA版本控制工具不能使用 VCS-->Enable Version Control Integration File-->Settings-->Plugins 搜索Subversion,勾选SVN和Git插件 删除.idea文件夹重新生成项目 安装SVN客户......

bithup ⋅ 今天 ⋅ 0

Hive函数

1.函数explode (一转多) create table hive_wc(sentence string); load data local inpath '/home/hadoop/data/hive-wc.txt' into table hive_wc; 结果: hive > select * from hive_wc; ......

GordonNemo ⋅ 今天 ⋅ 0

PE格式第三讲扩展,VA,RVA,FA的概念

作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶VA概念 VA (virtual Address) 虚拟地址的意思 ,比如随便打开一个PE,找下它的虚拟地址 这边...

simpower ⋅ 今天 ⋅ 0

180623-SpringBoot之logback配置文件

SpringBoot配置logback 项目的日志配置属于比较常见的case了,之前接触和使用的都是Spring结合xml的方式,引入几个依赖,然后写个 logback.xml 配置文件即可,那么在SpringBoot中可以怎么做?...

小灰灰Blog ⋅ 今天 ⋅ 0

冒泡排序

原理:比较两个相邻的元素,将值大的元素交换至右端。 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第...

人觉非常君 ⋅ 今天 ⋅ 0

Vagrant setup

安装软件 brew cask install virtualboxbrew cask install vagrant 创建project mkdir -p mst/vmcd mst/vmvagrant init hashicorp/precise64vagrant up hashicorp/precise64是一个box......

遥借东风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部