大厂面试,居然还问这些问题!

2024-06-14 20:32
文章标签 大厂 面试 居然 问题

本文主要是介绍大厂面试,居然还问这些问题!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简单面试整理

又到了金三银四的面试季,自己也不得不参与到这场战役中来,其实是从去年底就开始看,android的好机会确实不太多,但也还好,3年+的android开发经历还是有一些面试机会的,不过确实不像几年前门槛那么低了,总的体会就是小的创业公司比较注重你的项目经历是否和自己的贴合,直接能过来独当一面。大厂除了看中项目经历外,还比较注重你知识面的广度,是广度、深度和解决方案等多方面的考察,平时够工作要好好积累临时刷题只聊点皮毛估计是过不了关的。下面就总结一些遇到的题目,各种风格的都有。这里先列举问题。

1.dp是什么,sp呢,有什么区别

  • 长度宽度的数值要使用dp作为单位放入dimens.xml文件中
  • 字体大小的数值要使用sp作为单位,也放入dimens.xml文件中
  • 使用sp作为字体大小单位,会随着系统的字体大小改变,而dp作为单位则不会.

2.自定义View,ViewGroup注意那些回调?

  • 构造方法
    1.public View(Context context)
    2.public View(Context context, @Nullable AttributeSet attrs)
    3.public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
    4.public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)
  • void onFinishInflate();
    当系统解析XML中声明的View后回调此方法,调用顺序:内层View->外层View,如果是viewgroup,适合在这里获取子View。
  • void onAttachedToWindow(); 当view
    被添加到window中回调,调用顺序:外层View->内层View。在XML中声明或在代码中构造,并调用addview(this
    view)方法都会回调该方法。
  • void onDetachedFromWindow(); 看名字就知道是与void
    onAttachedToWindow();对应的方法,在VIew从Window中移除时回调,如执行removeView()方法。 注意点:
    如果一个View从window中被移除了,那么其内层View(如果有)也会被一起移除,都会回调该方法,且会先回调内层View的onDetachedFromWindow()方法。
  • void onWindowFocusChanged(boolean hasWindowFocus);
    当View所在的Window获得或失去焦点时被回调此方法。
    hasWindowFocus:View所在Window是否获取到焦点,当该Window获得焦点时,hasWindowFocus等于true,否则等于false。
  • onTouchEvent(MotionEvent event);
    当手指触摸View的时候回调该方法,前提是触摸事件没有被拦截或者被子View消费掉。该方法是事件分发流程中最后的消费者。
    event:触摸事件对象,包含了该事件的所有信息,如触摸的类型(down、move、up),触摸位置等。
    返回值:true:事件被消费了,false:没有被消费,事件传递到外层View,super方法:同false。

3.界面卡顿的原因以及解决方法
UI卡顿的根本原因:
Android每个16ms就会绘制一次Activity,通过上述的结论我们知道,如果由于一些原因导致了我们的逻辑、CPU耗时、GPU耗时大于16ms,UI就无法完成一次绘制,那么就会造成卡顿。简单的一句话就是:卡主线程了。

下面总结一些常见的UI卡顿原因:

  • 外部因素引起的(以View为区分)
    内存抖动的问题
    方法太耗时了(CPU占用)
  • View本身的卡顿
    CPU计算时间,CPU的测量、布局时间
    CPU将计算好的Polygons和Texture传递到GPU的时候也需要时间。OpenGL ES
    API允许数据上传到GPU后可以对数据进行保存,缓存到display list。因此,我们平移等操作一个view是几乎不怎么耗时的。

解决办法:

  • 修改方法(算法),使得方法不耗时。
  • 放到子线程中,例如网络访问、大文件操作等,防止ANR。
  • GPU优化建议就是一句话:尽量避免过度绘制(overdraw)

4.android中的存储类型
① 使用SharedPreferences存储数据 
② 文件存储数据
③  SQLite数据库存储数据
④ 使用ContentProvider存储数据
⑤ 网络存储数据

5.service用过么,基本调用方法
在这里插入图片描述
在这里插入图片描述
6.Handler机制
1.Handler中开启线程和分发消息的一些方法:

  • post(Runnable)直接开启Runnable线程
  • postAtTime(Runnable,long)在指定的时间long,开始启动线程
  • postDelayed(Runnable long)在延迟long时间后,启动Runnable线程
  • sendEmptyMessage(int) 发送指定的消息,通过参数int来区分不同的消息
  • sendMessage(Message)发送消息到UI线程中
  • sendMessageAtTime(Message,long) 这个long代表的是系统时间,不推荐用
  • sendMessageDelayed(Message,long) 此方法long代表调用后几秒后执行。

2.流程图:
在这里插入图片描述
3.Handler,Message,looper 和 MessageQueue 构成了安卓的消息机制,handler创建后可以通过 sendMessage 将消息加入消息队列,然后 looper不断的将消息从 MessageQueue 中取出来,回调到 Hander 的 handleMessage方法,从而实现线程的通信。

从两种情况来说,第一在UI线程创建Handler,此时我们不需要手动开启looper,因为在应用启动时,在ActivityThread的main方法中就创建了一个当前主线程的looper,并开启了消息队列,消息队列是一个无限循环,为什么无限循环不会ANR?因为可以说,应用的整个生命周期就是运行在这个消息循环中的,安卓是由事件驱动的,Looper.loop不断的接收处理事件,每一个点击触摸或者Activity每一个生命周期都是在Looper.loop的控制之下的,looper.loop一旦结束,应用程序的生命周期也就结束了。我们可以想想什么情况下会发生ANR,第一,事件没有得到处理,第二,事件正在处理,但是没有及时完成,而对事件进行处理的就是looper,所以只能说事件的处理如果阻塞会导致ANR,而不能说looper的无限循环会ANR

另一种情况就是在子线程创建Handler,此时由于这个线程中没有默认开启的消息队列,所以我们需要手动调用looper.prepare(),并通过looper.loop开启消息

主线程Looper从消息队列读取消息,当读完所有消息时,主线程阻塞。子线程往消息队列发送消息,并且往管道文件写数据,主线程即被唤醒,从管道文件读取数据,主线程被唤醒只是为了读取消息,当消息读取完毕,再次睡眠。因此loop的循环并不会对CPU性能有过多的消耗。

4.Handler为什么会泄漏?
handler发送的消息在当前handler的消息队列中,如果此时activity finish掉了,那么消息队列的消息依旧会由handler进行处理,若此时handler声明为内部类(非静态内部类),我们知道内部类天然持有外部类的实例引用,那么就会导致activity无法回收,进而导致activity泄露。
5.为何handler要定义为static?
因为静态内部类不持有外部类的引用,所以使用静态的handler不会导致activity的泄露
为何handler要定义为static的同时,还要用WeakReference 包裹外部类的对象?
这是因为我们需要使用外部类的成员,可以通过"activity. "获取变量方法等,如果直接使用强引用,显然会导致activity泄露。

6.避免handle内存泄露的办法

  • 1.使用static 修饰的handler,但是一般会弱引用activity对象,因为要使用activity对象中的成员
  • 2.单独定义handler,同样可以弱引用activity
  • 3.使用内部类的handler,在onDestroy方法中removeCallbacksAndMessages

7.LinearLayout、FrameLayout、RelativeLayout性能对比,为什么

  • 1.RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure
  • 2.RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。
  • 3.在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。 最后再思考一下文章开头那个矛盾的问题,为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。
  • 4.能用两层LinearLayout,尽量用一个RelativeLayout,在时间上此时RelativeLayout耗时更小。另外LinearLayout慎用layout_weight,也将会增加一倍耗时操作。由于使用LinearLayout的layout_weight,大多数时间是不一样的,这会降低测量的速度。这只是一个如何合理使用Layout的案例,必要的时候,你要小心考虑是否用layout
    weight。总之减少层级结构,才是王道,让onMeasure做延迟加载,用viewStub,include等一些技巧。

8.Activity的生命周期,finish调用后其他生命周期还会走么?

  • 在onCreate中:onCreate->onDestroy
  • 在onStart中:onCreate->onStart->onStop->onDestroy
  • 在onResume中:onCreate->onStart->onResume->onPause->onStop->onDestroy

9.apk包大小有限制么?怎么减少包大小?
用 Android Studio 提供的 APK Analyser 工具来分析下我们的 apk 文件:
可以看到占空间最多的主要是三个部分:classes.dex, res 和 resources.arsc。

  • classes.dex:包含有 Java 代码的字节码文件。
  • res:包含了资源文件,比如图片、布局文件等。
  • resources.arsc:包含所有的值资源文件,如 strings, dimensions, styles, integers 等。

解决办法:
一. gradle 中设置
1.1 开启minifyEnabled : 开启混淆,删除没用的java文件
1.2 开启shrinkResources : 去除无用资源
1.3 resConfig “zh”删除无用的语言资源
二.对图片的处理
2.1 使用tinpping 有损压缩,可以对png图片压缩
2.2 对于非透明的大图,png->jpp
2.3 使用webp 格式(根据 Google 的测试,无损压缩后的 WebP 比 PNG 文件少了 45% 的文件大小,即使这些 PNG 文件经过其他压缩工具压缩之后,WebP 还是可以减少 28% 的文件大小)
四. 使用shape文件替换图片
五.使用一套图,能用代码绘制出的图,就不要用图片
六谨慎添加libs,用不到的就删除

10.savedInstanceState onRestoreInstanceState区别

一、onSaveInstanceState(Bundle outState)在什么时机会被调用呢?
答案是当activity有可能被系统回收的情况下,而且是在onStop()之前。注意是有可能,如果是已经确定会被销毁,比如用户按下了返回键,或者调用了finish()方法销毁activity,则onSaveInstanceState不会被调用。
或者也可以说,此方法只有在activity被异常终止的情况下会被调用。

总结下,onSaveInstanceState(Bundle outState)会在以下情况被调用:
1、当用户按下HOME键时。
2、从最近应用中选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从当前activity启动一个新的activity时。
5、屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。
在前4种情况下,当前activity的生命周期为:
onPause -> onSaveInstanceState -> onStop。 onPause和onSaveInstanceState的顺序是不一定的
二、onRestoreInstanceState什么时机被调用?
onRestoreInstanceState(Bundle savedInstanceState)只有在activity确实是被系统回收,重新创建activity的情况下才会被调用。
三、onCreate()里也有Bundle参数,可以用来恢复数据,它和onRestoreInstanceState有什么区别?

因为onSaveInstanceState 不一定会被调用,所以onCreate()里的Bundle参数可能为空,如果使用onCreate()来恢复数据,一定要做非空判断。而onRestoreInstanceState的Bundle参数一定不会是空值,因为它只有在上次activity被回收了才会调用。而且onRestoreInstanceState是在onStart()之后被调用的。有时候我们需要onCreate()中做的一些初始化完成之后再恢复数据,用onRestoreInstanceState会比较方便

11.view的绘制原理
View的绘制流程:OnMeasure()——>OnLayout()——>OnDraw()
各步骤的主要工作:

  1. OnMeasure():测量视图大小。从顶层父View到子View递归调用measure方法,measure方法又回调OnMeasure。
  2. OnLayout():确定View位置,进行页面布局。从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。
  3. OnDraw():绘制视图。ViewRoot创建一个Canvas对象,然后调用OnDraw()。六个步骤:①、绘制视图的背景;②、保存画布的图层(Layer);③、绘制View的内容;④、绘制View子视图,如果没有就不用;⑤、还原图层(Layer);⑥、绘制滚动条。

在这里插入图片描述
measure过程:
1.ViewGroup.LayoutParams :用来指定视图高度和宽度的参数,不包括Padding。
2.MeasureSpec :表示测量规格。32位的Int值,高二位表示模式,后三十位表示测量规格的大小。
(1)UNSPECIFIED:不限定子视图尺寸大小。
(2)EXACTLY:父容器会为子视图确定一个尺寸大小,无论子视图要求多大,都要在父容器的限制内。
(2)AT_MOST:父容器会为子视图指定一个最大的尺寸,子视图所有的大小都必须在这个尺寸范围内。对应wrap_content。此时父容器无法获取子视图的大小,只能子视图自己根据需求设定。
ViewGroup.LayoutParams最终会被封装成MeasureSpec。

measure——重要方法
measure会从父容器遍历子View的measure方法,会根据ViewGroup.MeasureSpec和子View的LayoutParams来决定子视图的测量规格,通过这个测量规格进一步获取到子View的宽高,一层一层向下传递,不断保存整个父容器的测量宽高。
1.measure:该方法会调用onMeasure方法。
2.onMeasure:该方法会调用setMeasuredDimension()方法。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}

3.setMeasuredDimension():该方法完成整个的测量过程。

protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {boolean optical = isLayoutModeOptical(this);if (optical != isLayoutModeOptical(mParent)) {Insets insets = getOpticalInsets();int opticalWidth  = insets.left + insets.right;int opticalHeight = insets.top  + insets.bottom;measuredWidth  += optical ? opticalWidth  : -opticalWidth;measuredHeight += optical ? opticalHeight : -opticalHeight;}setMeasuredDimensionRaw(measuredWidth, measuredHeight);
}

layout
onLayout方法是用来设置与父容器的摆放关系的,自定义View需重写该方法。
View中的onLayout是个空方法。

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}

LinearLaout中的onLayout如下:

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {if (mOrientation == VERTICAL) {layoutVertical(l, t, r, b);} else {layoutHorizontal(l, t, r, b);}
}

draw
两个容易混淆的方法:
1.invalidate():请求系统重绘,未发生变化时不会调用。
2.requestLayout():当布局(方向、尺寸等)发生变化时,需手动调用,该方法会触发measure和layout的过程,而不会调用draw方法。

详细见:添加链接描述

12.IntentService生命周期是怎样的,使用场合

要编写耗时操作又不得不交于service管理的话,就需要引入IntentService,IntentService继承service,拥有service的全部生命周期,包含了service的全部特性,与service不同的是IntentService在onCreat被执行时内部会开启一个线程,执行耗时操作

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
IntentService是Service类的子类,用来处理异步请求。客户端可以通过startService(Intent)方法传递请求给IntentService。IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来处理所有Intent请求对象(通过startService的方式发送过来的)所对应的任务,这样以免事务处理阻塞主线程。执行完所一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service;否则执行下一个Intent请求所对应的任务。

IntentService在处理事务时,还是采用的Handler方式,创建一个名叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程。 ServiceHandler把处理一个intent所对应的事务都封装到叫做onHandleIntent的虚函数;因此我们直接实现虚函数onHandleIntent,再在里面根据Intent的不同进行不同的事务处理就可以了。

这篇关于大厂面试,居然还问这些问题!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1061436

相关文章

linux生产者,消费者问题

pthread_cond_wait() :用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

2024.6.24 IDEA中文乱码问题(服务器 控制台 TOMcat)实测已解决

1.问题产生原因: 1.文件编码不一致:如果文件的编码方式与IDEA设置的编码方式不一致,就会产生乱码。确保文件和IDEA使用相同的编码,通常是UTF-8。2.IDEA设置问题:检查IDEA的全局编码设置和项目编码设置是否正确。3.终端或控制台编码问题:如果你在终端或控制台看到乱码,可能是终端的编码设置问题。确保终端使用的是支持你的文件的编码方式。 2.解决方案: 1.File -> S

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

vue同页面多路由懒加载-及可能存在问题的解决方式

先上图,再解释 图一是多路由页面,图二是路由文件。从图一可以看出每个router-view对应的name都不一样。从图二可以看出层路由对应的组件加载方式要跟图一中的name相对应,并且图二的路由层在跟图一对应的页面中要加上components层,多一个s结尾,里面的的方法名就是图一路由的name值,里面还可以照样用懒加载的方式。 页面上其他的路由在路由文件中也跟图二是一样的写法。 附送可能存在

vue+elementui--$message提示框被dialog遮罩层挡住问题解决

最近碰到一个先执行this.$message提示内容,然后接着弹出dialog带遮罩层弹框。那么问题来了,message提示框会默认被dialog遮罩层挡住,现在就是要解决这个问题。 由于都是弹框,问题肯定是出在z-index比重问题。由于用$message方式是写在js中而不是写在html中所以不是很好直接去改样式。 不过好在message组件中提供了customClass 属性,我们可以利用

Visual Studio中,MSBUild版本问题

假如项目规定了MSBUild版本,那么在安装完Visual Studio后,假如带的MSBUild版本与项目要求的版本不符合要求,那么可以把需要的MSBUild添加到系统中,然后即可使用。步骤如下:            假如项目需要使用V12的MSBUild,而安装的Visual Studio带的MSBUild版本为V14。 ①到MSDN下载V12 MSBUild包,把V12包解压到目录(

C++面试八股文:std::deque用过吗?

100编程书屋_孔夫子旧书网 某日二师兄参加XXX科技公司的C++工程师开发岗位第26面: 面试官:deque用过吗? 二师兄:说实话,很少用,基本没用过。 面试官:为什么? 二师兄:因为使用它的场景很少,大部分需要性能、且需要自动扩容的时候使用vector,需要随机插入和删除的时候可以使用list。 面试官:那你知道STL中的stack是如何实现的吗? 二师兄:默认情况下,stack使