BAT 大厂Android研发岗必刷真题:Android异常与性能优化相关面试问题

/**

  • 获取缩略图

  • @param imagePath:文件路径

  • @param width:缩略图宽度

  • @param height:缩略图高度

  • @return

*/

public static Bitmap getImageThumbnail(String imagePath, int width, int height) {

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true; //关于inJustDecodeBounds的作用将在下文叙述

Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);

int h = options.outHeight;//获取图片高度

int w = options.outWidth;//获取图片宽度

int scaleWidth = w / width; //计算宽度缩放比

int scaleHeight = h / height; //计算高度缩放比

int scale = 1;//初始缩放比

if (scaleWidth < scaleHeight) {//选择合适的缩放比

scale = scaleWidth;

} else {

scale = scaleHeight;

}

if (scale <= 0) {//判断缩放比是否符合条件

be = 1;

}

options.inSampleSize = scale;

// 重新读入图片,读取缩放后的bitmap,注意这次要把inJustDecodeBounds 设为 false

options.inJustDecodeBounds = false;

bitmap = BitmapFactory.decodeFile(imagePath, options);

// 利用ThumbnailUtils来创建缩略图,这里要指定要缩放哪个Bitmap对象

bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);

return bitmap;

}

e) 三级缓存

网络、本地、内存三级缓存,减少流量的使用

4、 ui卡顿面试问题讲解

a) UI卡顿的原理

  • 60fps -> 16ms

  • overdraw过度绘制

b) UI卡顿的原因分析

1.人为在UI线程中做轻微耗时操作,导致UI线程卡顿

2.布局Layout过于复杂,无法在16ms内完成渲染

3.同一时间动画执行的次数过多,导致CPU、GPU的负载过重

4.View的过度绘制,导致某些像素在同一帧内被绘制多次,从而使CPU、GPU的负载过重

5.View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染

6.内存频繁触发gc过多,导致暂时阻塞渲染操作

7.冗余资源及逻辑等导致加载和执行的缓慢

8.ANR

c) UI卡顿总结

1.布局优化

2.列表及adapter优化

3.背景和图片等内存分配优化

4.避免ANR

4、 内存泄漏

a) java内存泄漏基础知识

1. java内存的分配策略

静态存储区(方法区):主要存放静态数据、全局 static 数据和常量。这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在。

栈区:当方法被执行时,方法体内的局部变量(其中包括基础数据类型、对象的引用)都在栈上创建,并在方法执行结束时这些局部变量所持有的内存将会自动被释放。因为栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

堆区 : 又称动态内存分配,通常就是指在程序运行时直接 new 出来的内存,也就是对象的实例。这部分内存在不使用时将会由 Java 垃圾回收器来负责回收。

2. java是如何管理内存的

3. java中的内存泄漏

内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄漏

b) android内存泄漏

  1. 单例

public class AppManager {

private Context mContext;

private static AppManager instance;

private AppManager(Context context){

//有内存泄漏的问题:传入的是actiivty的context,导致activity没法释放

//this.mContext = context;

//所以这里应该传入Application全局的context

this.mContext = context.getApplicationContext();

}

public static AppManager getInstance(Context context){

if(instance ==null){

instance = new AppManager(context);

}

return instance;

}

}

2.匿名内部类

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

//这样的写法就会造成内存泄漏

//原因是这样写法虽然避免了重复创建,但是非静态内部类持有外部类的引用,

//这时候我们又创建了一个静态实例TAG的话就会和应用的生命周期一样长,所以就会使外部的activity没法释放

class TestResource{

private static final String TAG = “”;

}

//正常的写法,这样的话就不会持有外部类的引用。

static class TestResource1{

private static final String TAG = “”;

}

}

3.handler

public class MainActivity extends AppCompatActivity {

private TextView mTv;

private MyHandler myHandler;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

myHandler = new MyHandler(this);

}

//这样的写法会造成内存泄漏

//mHandler是MainActivity的非静态内部类的实例,它持有外部类的引用,我们知道handler的消息是在一个loop

//中不断的轮询处理消息,那么当MainActivity退出时,消息队列中还有没处理的消息或正在处理的消息,所以会造成内存泄漏

@SuppressLint(“HandlerLeak”)

private Handler mHandler = new Handler(){

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

}

};

//这样写是正确的写法

static class MyHandler extends Handler{

//创建一个软引用

private WeakReference reference;

public MyHandler(Context context){

reference = new WeakReference(context);

}

@Override

public void handleMessage(Message msg) {

MainActivity mainActivity = (MainActivity) reference.get();

if(mainActivity != null){

//TODO------

mainActivity.mTv.setText(“11”);

}

}

}

@Override

protected void onDestroy() {

super.onDestroy();

myHandler.removeCallbacksAndMessages(null);

}

}

4.避免使用static静态变量

如果声明成静态变量,那么它的生命周期就会和app的生命周期一样长,假如你的app是常驻后台的,即使app退到后台,这部分也不会释放

5.资源未关闭造成的内存泄漏

6.AsyncTask造成的内存泄漏

  • 在onDestory调用cancel()方法

  • 添加弱引用实现

5、内存管理面试问题

a)内存管理机制概述

1.分配机制

2.回收机制

b)Android内存管理机制

1.分配机制

弹性的分配机制,当发现内存不够用的时候回分配额外的内存。但是额外的内存也不是无限量的。(让更多的进程存活在系统中)

2.回收机制

前台进程 可见进程 服务进程 后台进程 空进程

c)内存管理机制的特点(目标)

1.更少占用的内存

2.在合适的时候,合理的释放系统资源

3.在系统内存紧张的情况下,能释放掉不部分不重要的资源,来为android系统提供可用的内存

4.能够很合理的在特殊的生命周期中,保存或者还原重要数据,以至于系统能够正确的重新恢复该应用

d)内存优化方法

1.当service完成任务后,尽量停止它

2.在UI不可见的时候,释放掉一些只有UI使用的资源

3.在系统资源紧张的时候,尽可能多的释放掉一些非重要资源

4.避免滥用Bitmap导致的内存浪费

5.使用针对内存优化过的数据容器

6.避免使用依赖注入的框架

7.使用ZIP对齐的APK

8.使用多进程

d)内存溢出VS内存泄漏

6、冷启动优化面试问题讲解

a)什么是冷启动?

1.冷启动的定义

冷启动就是在启动应用前,系统没有该应用的任何进程信息

2.冷启动 / 热启动的区别

热启动:用户使用返回键退出应用,然后马上又重新启动应用

区别:

1). 定义

2). 启动特点

  • 冷启动:Application -> MainActivity ->UI的绘制

  • 热启动:MainActivity ->UI的绘制

3.冷启动时间的计算

这个时间值从应用启动(创建进程)开始计算,到完成视图的第一次绘制(即Activity内容对用户可见)为止

b)冷启动流程

  • Zygote进程中fork创建一个新的进程

最后

在此为大家准备了四节优质的Android高级进阶视频:

架构师项目实战——全球首批Android开发者对Android架构的见解

附相关架构及资料

image.png

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
ity ->UI的绘制

  • 热启动:MainActivity ->UI的绘制

3.冷启动时间的计算

这个时间值从应用启动(创建进程)开始计算,到完成视图的第一次绘制(即Activity内容对用户可见)为止

b)冷启动流程

  • Zygote进程中fork创建一个新的进程

最后

在此为大家准备了四节优质的Android高级进阶视频:

架构师项目实战——全球首批Android开发者对Android架构的见解

附相关架构及资料

[外链图片转存中…(img-oJvAXx3k-1714795820001)]

往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值