-
2019-01-25 20:40:33
常见Android面试题及答案(详细整理)
2016年03月16日 10:10:15 Ericpengjun 阅读数:64035
以下是一些常用的Android面试题及答案,有需要没需要都可以备着,希望能帮到大家。
1. 请描述一下Activity 生命周期。
答: 如下图所示。共有七个周期函数,按顺序分别是: onCreate(), onStart(), onRestart(), onResume(), onPause(),onStop(), onDestroy()。
onCreate(): 创建Activity时调用,设置在该方法中,还以Bundle的形式提供对以前存储的任何状态的访问。
onStart(): Activity变为在屏幕上对用户可见时调用。
onResume(): Activity开始与用户交互时调用(无论是启动还是重新启动一个活动,该方法总是被调用。
onPause(): Activity被暂停或收回cpu和其他资源时调用,该方法用户保护活动状态的,也是保护现场。
onStop(): Activity被停止并转为不可见阶段及后续的生命周期事件时调用。
onRestart(): Activity被重新启动时调用。该活动仍然在栈中,而不是启动新的Activity。
1、完整生命周期: 即从一个Activity从出现到消失,对应的周期方法是从onCreate()到onDestroy()。
2、可见生命周期: 当Activity处于可以用户看见的状态,但不一定能与用户交互时,将多次执行从onStart()到onStop()。
3、前景生命周期: 当Activity处于Activity栈最顶端,能够与其他用户进行交互时,将多次执行从onResume()到onPause()。
2. 两个Activity之间跳转时必然会执行的是哪几个方法。
答: 两个Activity之间跳转必然会执行的是下面几个方法。
onCreate()//在Activity生命周期开始时调用。
onRestoreInstanceState()//用来恢复UI状态。
onRestart()//当Activity重新启动时调用。
onStart()//当Activity对用户即将可见时调用。
onResume()//当Activity与用户交互时,绘制界面。
onSaveInstanceState()//即将移出栈顶保留UI状态时调用。
onPause()//暂停当前活动Activity,提交持久数据的改变,停止动画或其他占用GPU资源的东西,由于下一个Activity在这个方法返回之前不会resume,所以这个方法的代码执行要快。
onStop()//Activity不再可见时调用。
onDestroy()//Activity销毁栈时被调用的最后一个方法。
3. 横竖屏切换时候Activity的生命周期。
答:
1、不设置Activity的android: configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
2、设置Activity的android: configChanges=“orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次。
3、设置Activity的android: configChanges=“orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfiguration方法
4. 如何将一个Activity设置成窗口的样式。
答: 第一种方法,在styles.xml文件中,可以新建如下的类似Dialog的style。
<style name=“Theme.FloatActivity” parent=“android:style/Theme.Dialog”> </style>。
第二种方法,在AndroidManifest.xml中在需要显示为窗口的Activity中添加如下属性: android: theme=“@style/Theme.FloatActivity”即可。也可以直接添加对应需要展示为Dialog style的Activity的android: theme属性为android: theme=“@ android: style/Theme.Dialog”。
5. 两个Activity之间怎么传递数据?
答: 可以在Intent对象中利用Extra来传递存储数据。
在Intent的对象请求中,使用putExtra(“键值对的名字”,”键值对的值”);在另外一个Activity中将Intent中的请求数据取出来:
Intent intent = getIntent();
String value = intent.getStringExtra(“testIntent”);
6. 怎么让在启动一个Activity是就启动一个service?
答: 首先定义好一个service,然后在Activity的onCreate里面进行连接并bindservice或者直接startService。
7. Activity怎么和service绑定,怎么在activity中启动自己对应的service?
答:
1、activity能进行绑定得益于Serviece的接口。为了支持Service的绑定,实现onBind方法。
2、Service和Activity的连接可以用ServiceConnection来实现。需要实现一个新的ServiceConnection,重现onServiceConnected和OnServiceDisconnected方法,一旦连接建立,就能得到Service实例的引用。
3、执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显示或隐式)和一个你实现了的ServiceConnection的实例
8.什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service?
答: Android Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序进程的上下文里。需要通过某一个Activity或者Context对象来调用。Service有两个启动方法,分别是Context.startService()和Context.bindService()。如果在Service执行耗时的操作需要启动一个新线程来执行。
Android Service只继承了onCreate(), onStart(),onDestroy()三个方法,当我们第一次启动Service时,先后调用onCreate(), onStart()这两个方法,当停止Service时,则执行onDestroy()方法时。如果Service已经启动了,当我们再次启动Service时,不会再执行onCreate()方法,而是直接执行onStart()方法。
9. 什么时候使用Service?
答: 比如播放多媒体的时候,用户启动了其他Activity,这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你的地理信息位置的改变等等。
10. 请描述一下Intent 和 Intent Filter。
答: Intent在Android中被翻译为”意图”,他是三种应用程序基本组件-Activity,Service和broadcast receiver之间相互激活的手段。在调用Intent名称时使用ComponentName也就是类的全名时为显示调用。这种方式一般用于应用程序的内部调用,因为你不一定会知道别人写的类的全名。而Intent Filter是指意图过滤,不出现在代码中,而是出现在android Manifest文件中,以<intent-filter>的形式。(有一个例外是broadcast receiver的intent
filter是使用Context.registerReceiver()来动态设定的,其中intent filter也是在代码中创建的)一个intent有action,data,category等字段。一个隐式intent为了能够被某个intent filter接收,必须通过3个测试,一个intent为了被某个组件接收,则必须通过它所有的intent filter中的一个。
11. Intent传递数据时,可以传递哪些类型数据?
答: intent间传送数据一般有两种常用的方法: 1、extra 2、data。
extra可以用Intent.putExtra放入数据。新启动的Activity可用Intent.getExtras取出Bundle,然后用Bundles.getLong,getInt,getBoolean,getString等函数来取放进去的值。
Data则是传输url。url可以是指我们熟悉的http,ftp等网络地址,也可以指content来指向ContentProvider提供的资源。Intent.setData可以放入数据,Intent.getData可以取出数据。
12. 说说Activity,Intent,Service是什么关系 ?
答: 一个Activity通常是一个单独的屏幕,每一个Activity都被实现为一个单独的类,这些类都是从Activity基类中继承而来的。Activity类会显示由视图控件组成的用户接口,并对视图控件的事件做出响应。
Intent的调用是用来进行屏幕之间的切换。Intent描述应用想要做什么。Intent数据结构中两个最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。
Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程里,也可以运行在其他应用程序进程的上下文里。需要一个Activity或者其他Context对象来调用。
Activity跳转Activity,Activity启动Service,Service打开Activity都需要Intent表明意图,以及传递参数,Intent是这些组件间信号传递的承载着。
13. 请描述一下BroadcastReceiver。
答: Broadcast Receiver用于接收并处理广播通知(broadcast announcements)。多数的广播是系统发起的,如地域变换、电量不足、来电短信等。程序也可以播放一个广播。程序可以有任意数量的broadcast receivers来响应它觉得重要的通知。Broadcast receiver可以通过多种方式通知用户: 启动activity、使用NotificationManager、开启背景灯、振动设备、播放声音等,最典型的是在状态栏显示一个图标,这样用户就可以点它打开看通知内容。通常我们的某个应用或系统本身在某些事件(电池电量不足、来电短信)来临时会广播一个Intent出去,我们利用注册一个broadcast
receiver来监听这些Intent并获取Intent中的数据。14. 在manifest和代码中如何注册和使用 broadcast receiver 。
答: 在android的manifest中注册
<receiver android: name =“Receiver1”>
<intent-filter>
<!----和Intent中的action对应--->
<actionandroid: name=“com.forrest.action.mybroadcast”/>
</intent-filter>
</receiver>
在代码中注册
1、 IntentFilter filter = new IntentFilter(“com.forrest.action.mybroadcast”);//和广播中Intent的action对应;
2、 MyBroadcastReceiver br= new MyBroadcastReceiver();
3、 registerReceiver(br, filter);
15. 请介绍下ContentProvider是如何实现数据共享的。
答: 一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content provider是以类似数据库中的表的方式将自己的数据暴露。Content provider存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:创建一个数据自己的Content Provider或者将你的数据添加到一个已经存在的Content Provider中,前提是有相同数据类型并且有写入Content Provider的权限,Android提供了Content Resolverr,外界的程序可以通过Content Resolver接口访问Content Provider提供的数据。
16. 请介绍下Android的数据存储方式。
答: Android提供了5中存储数据的方式,分别是以下几种
1、使用Shared Preferences存储数据,用来存储key-value,pairs格式的数据,它是一个轻量级的键值存储机制,只可以存储基本数据类型。
2、使用文件存储数据,通过FileInputStream和FileOutputStream对文件进行操作。在Android中,文件是一个应用程序私有的,一个应用程序无法读写其他应用程序的文件。
3、使用SQLite数据库存储数据,Android提供的一个标准数据库,支持SQL语句。
4、使用Content Provider存储数据,是所有应用程序之间数据存储和检索的一个桥梁,它的作用就是使得各个应用程序之间实现数据共享。它是一个特殊的存储数据的类型,它提供了一套标准的接口用来获取数据,操作数据。系统也提供了音频、视频、图像和个人信息等几个常用的Content Provider。如果你想公开自己的私有数据,可以创建自己的Content Provider类,或者当你对这些数据拥有控制写入的权限时,将这些数据添加到Content Provider中实现共享。外部访问通过Content Resolver去访问并操作这些被暴露的数据。
5、使用网络存储数据
17. 请介绍下Android中常用的五种布局。
答: 最常用的布局方式为Absolute Layout、Relative Layout、Linear Layout、FrameLayout、TableLayout。其中Linear Layout和Relative Layout是最常用的方式,他们可以通过在xml配置文件或者代码中进行布局。
1、Frame Layout是最简单的布局方式,放置的控件都只能罗列到左上角,控件会有重叠,不能进行复杂的布局。
2、Linear Layout可以通过orientation属性设置线性排列的方向是垂直还是纵向的,每行或每列只有一个元素,可以进行复杂的布局。
3、Absolute Layout可以让子元素指定准确的x、y坐标值,并显示在屏幕上。Absolute Layout没有页边框,允许元素之间相互重叠。它是绝对坐标,所以在实际中不提倡使用。
4、Relative Layout允许子元素制定他们相对于其他元素或父元素的位置(通过ID制定)。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列,因此如果第一个元素在屏幕的中央,那么相对于这个元素的其他元素将以屏幕中央的相对位置来排列。这个是相对于Absolute Layout的,采用相对坐标,所以在实际中比较常用。
5、Table Layout将以子元素的位置分配到行或列。一个Table Layout由许多的Table Row组成,每个Table Row都会定义一个row。Table Layout容器不会显示row、column或者cell的边线框。每个row拥有0个或多个的cell; 和html中的table差不多。在实际中也经常使用。
18. 谈谈UI中, Padding和Margin有什么区别?
答: Padding是控件的内容相对控件的边缘的边距,而Margin是控件边缘相对于其他控件的边距。如下图所示:
19. android本身的一些限制,比如apk包大小限制,读取大文件时的时间限。
答:apk包大小限制不好说,有的apk为100M,还是能装到手机上。一般的apk大小为5~10M左右。读取大文件的时间应该是在main线程里面,时间限制为5秒左右。
20. ListView如何提高其效率?
答:1、使用分页加载,不要一次性加载所有数据。
2、复用convertView。在getItemView中,判断converView是否为空,如果不为空,可复用。
3、异步加载图片。Item中如果包含有webimage,那么最好异步加载。
4、快速滑动时,不显示图片。当快速滑动列表(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来
21. Android程序与Java程序的区别?
区别
Java程序
Android程序
执行入口点
Main
Android Mainfest.xml配置文件中的intent-filter
UI
Frame·
Activity
是否基于配置文件
否
是
是否基于组件
否
是Activity,Service,Broadcast Receiver,Content Provider
22. 谈谈对Android NDK的理解。
答: android NDK是一套工具,允许Android应用开发者嵌入从C、C++源代码编译来的本地机器代码到各自的应用软件包中。
1、 NDK是一系列工具的集合。
NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者帮助时巨大的。
NDK集成了交叉编辑器,并提供了相应的mk文件隔离CPU、平台、API等差异,开发人员只需要简单修改mk文件(指出“那些文件需要编译”、“编译特性要求”等),就可以创建出so。NDK可以自动将so和Java应用一起打包,极大的减轻了开发人员的打包工作。
2、NDK提供了一份稳定、功能有限的API头文件声明。这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、log库(liblog)。
23. 谈谈Android的优点和不足之处。
答: 优点如下所示:
1、android是开源、市场占有率大。
2、android能够有丰富的硬件选择。
3、android是一款基于Linux平台的开源操作系统,从而避免了专利壁垒,是一款完全免费的只能手机平台。
4、由于android是google开发的,因此能够无缝结合Google应用。
缺点如下所示:
1、安全与隐私。手机与互联网紧密联系,个人隐私很难得到保守。
24. Android系统中GC什么情况下会出现内存泄露呢?
答: 导致内存泄露主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为“有效的活动”,同时不会被释放。要确定对象所占内存将被回收,我们就要确认该对象不会再被使用。典型的做法是把对象数据成员设为null或者从集合中移除该对象。当出现以下情况时,会造成内存泄露:
1、 数据库的cursor没有关闭。
2、 构造adapter时,没有使用缓存contentview。
3、 Bitmap对象不使用时,采用recycle()释放内存。
4、 Activity中的对象的生命周期大于activity。
调试方法: DDMS==>HEAPSIZE==>dataobject==>[TotalSize]
25. Android UI中的View如何刷新。
答: Android中对View的更新方式有很多种,使用时要区分不同的应用场合。要分清的是:多线程和双缓冲。
1、不使用多线程和双缓冲
这种情况最简单,一般只希望View在发生改变时对UI进行重绘。你只需要Activity中显式调用View对象中的invalidate()方法即可。系统会自动调用View的onDraw()方法。
2、使用多线程和不使用双缓冲
这种情况下需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报错:android.view.ViewRoot$ CalledFromWrongThreadException: only theoriginal thread that created a view hierarchy can touch its views。
这时候你需要创建一个继承了android.os.handler的子类,并重写handleMessage方法。Android.os.Handle是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量,你可以直接调用View对象中的invalidate()方法。也就是说:在新线程中创建并发送一个Message,然后在主线程中捕获、处理该消息。
3、使用多线程和双缓冲
Android的SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现Surfaceholder.Callback接口。由于SurfaceHolder.Callback接口,新线程就不要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制完新的图像后调用unlockCanvasand Post解锁。
(来自威哥干Java的微信文章)
更多相关内容 -
Android 高级开发面试题以及答案整理
2021-01-06 10:21:02Android 高级开发面试题以及答案整理 -
71道经典Android面试题和答案.doc
2021-09-15 15:52:1571道经典Android面试题和答案 -
2021年Android面试题集大合集(含答案解析)-2109页.pdf
2021-10-21 17:01:462021年Android面试题集大合集(含答案解析),内容太多,共2109页。 -
android面试题及答案.doc
2022-03-26 07:27:38android面试题及答案.doc -
Android+高级开发面试题以及答案整理.pdf
2020-10-29 15:41:55Android知识点的总结,可以以此为参考复习知识! -
2022年Android面试题及答案汇总,每天20题【一】持续更新中...(从面试官角度帮你审视问题)
2022-04-18 16:59:06这是我既前两次做Android面试题合集之后重新整理和完善的一份新的面试题。 写在前面,之前面试题带入的都是咱们求职者的视角,这次我联络的是部分招聘人员,当然具体名字和公司不方便透露,总之,该部分面试是从招聘...前言
本文乃找工作、招人必备之良品。后期不断完善中……
对于面试仍然充满畏惧?多次面试后信心被搓,被恶心的面试官打击?这里有一份宝典合集:包括有《1599页Android面试宝典》+《Android Framework 开发揭秘》+《Android项目合集》等等,一切你需要的面试资料,我们都有合集大礼包等着你,需要的朋友可以添加下面VX回复JJ即可领取,100%免费!!!
这是我既前两次做Android面试题合集之后重新整理和完善的一份新的面试题。
写在前面,之前面试题带入的都是咱们求职者的视角,这次我联络的是部分招聘人员,当然具体名字和公司不方便透露,总之,该部分面试是从招聘角度出发,当然作为求职者我觉得只会收获更加丰富。
如何招聘人,搜集了一些知识点。如何做好应聘准备,也收集了一些主要知识点,供你参考。
- Android基础知识:基本涵盖Android所有知识体系,四大组件,Fragment,WebView,事件分发,View绘制…
- Java基础知识&高阶知识点:基础部分不谈了,高阶部分:泛型,反射,Java虚拟机…
- 算法与数据结构:链表,堆,栈,树…
- Android常用框架:异步,网络,图片加载,内存优化,依赖注入,数据库等框架
- Android前沿技术:Android组件化,热更新,插件化,消息推送,AOP面向切面编程,Flutter(谷歌的移动UI框架)…
- 源码分析:Android源码分析,启动一个app的源码分析,常用框架源码分析,Java源码分析,集合源码分析…
- 网络基础:五层网络模型,三次握手&四次挥手,请求头&响应头,Socket&WebSocket…
1.Java中的==、equals和hashCode的区别
(1)“==”运算符用来比较两个变量的值是否相等,即该运算符用于比较变量之间对应的内存中的地址是否相同,
要比较两个基本类型的数据或两个引用变量是否相等,只能使用“=.=“(注:编译器格式显示问题,是双等号)运算符(2)equals是Object类提供的方法之一,每个java类都集成自Object类,即每个对象都有equals方法,equals与“==”一样,比较的都是引用,相比运 算符,equals(Object)方法的特殊之处在于其可以被覆盖,所以可以通过覆盖的方法让他比较的不是引用而是数据内容,即堆中的内容是否相等。
(3)hashCode()方法是从Object类继承过来的,他也是用来比较两个对象是否相等,Object类中的hashCode方法,返回对象在内存中地址转换成的一个Int值,所以如果未重写hashCode方法,任何对象的hashCode方法返回的值都是不相等的。
综上而言,==和equals判断的是(基本类型数据)引用是否相等,但equals可以通过覆盖方法使其比较的是数据内容,事实上,Java中很多类库中的类已经覆盖了此方法,而hashCode判断的是对象在内存中地址是否相等。
2.int和integer的区别
Integer是int提供的封装类,而int是java的基本数据类型,Integer的默认值是null,而int的默认值是0,声明Integer的变量需要实例化,而int不需要,Integer是对象,是一个引用指向这个对象,而int是基本数据类型,直接存储数据。
3.String、StringBuffer和StringBuilder的区别
他们的主要区别在于运行速度和线程安全两个方面,运行速度:StringBuilder>StringBuffer>String,String最慢的原因在于String是字符串常量,一旦创建是不可以再更改的,但后两者的对象是变量,是可以更改的,Java中对String对象的操作实际上是一个不断创建新的对象而将旧的对象回收的过程,而后两者因为是变量,所以可以直接进行更改,在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的,因为在StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,而StringBuilder不存在该关键字,所以在线程中并不安全。
4.什么是内部类?内部类的作用是什么?
内部类是定义在另一个类里面的类,与之相对应,包含内部类的类被称为外部类,
内部类的作用有:(1)内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一包中的其他类访问,(2)内部类的方法可以直接访问外部类的所有数据,包括私有的数据,(3)内部类的种类:成员内部类、静态内部类、方法内部类、匿名内部类
5.进程与线程的区别
进程是CPU资源分配的最小单位,而线程是CPU调度的最小单位,进程之间不能共享资源,而线程共享所在进程的地址空间和其他资源,一个进程内可以拥有多个线程,进程可以开启进程、也可以开启线程,一个线程只能属于一个进程,线程可直接使用同进程的资源,线程依赖于进程而存在。
6.final、finally、finalize的区别
final是用于修饰类、成员变量和成员方法,类不可被继承,成员变量不可变,成员方法不可被重写;finally与try…catch…共同使用,确保无论是否出现异常都能被调用到;finalize是类的方法,垃圾回收前会调用此方法,子类可以重写finalize方法实现对资源的回收。
7.Serializable和Parcelable的区别
Serlizable是java序列化接口,在硬盘上读写,读写的过程中有大量临时变量产生,内部执行大量的I/O操作,效率很低;Parcelable是Android序列化接口,效率高,在内存中读写,但使用麻烦,对象不能保存到磁盘中。
8.静态属性和静态方法是否可以被继承?是否可以被重写?
可以继承,但不可以被重写,而是被隐藏,如果子类里面定义了静态方法或属性,那么这时候父类的静态方法或属性称之为隐藏。
9.成员内部类、静态内部类、局部内部类、和匿名内部类的理解
Java中内部类主要分为成员内部类、局部内部类(嵌套在方法和作用域中)、匿名内部类(无构造方法)、静态内部类(由static修饰的类、不能使用任何外围类的非static成员变量和方法、不依赖外围类),每个内部类都能独立的继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类均无影响,因为Java支持实现多个接口,而不支持多继承,我们可以使用内部类提供的、可以继承多个具体的或抽象的类的能力来解决使用接口难以解决的问题,接口只是解决了部分问题,而内部类使得多继承的解决方案变得更加完整。
10.Java的垃圾回收机制及其在何时会被触发
内存回收机制:就是释放掉在内存中已经没有用的对象,要判断怎样的对象是没用的,有两种方法:(1)采用标记数的方法,在给内存中的对象打上标记,对象被引用一次,计数加一,引用被释放,计数就减一,当这个计数为零时,这个对象就可以被回收,但是,此种方法,对于循环引用的对象是无法识别出来并加以回收的,(2)采用根搜索的方法,从一个根出发,搜索所有的可达对象,则剩下的对象就是可被回收的,垃圾回收是在虚拟机空闲的时候或者内存紧张的时候执行的,什么时候回收并不是由程序员控制的,可达与不可达的概念:分配对象使用new关键字,释放对象时,只需将对象的引用赋值为null,让程序不能够在访问到这个对象,则称该对象不可达。
在以下情况中垃圾回收机制会被触发:
(1)所有实例都没有活动线程访问 ;(2)没有其他任何实例访问的循环引用实例;(3)Java中有不同的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。
11.Java中的代理是什么?静态代理和动态代理的区别是什么?
代理模式:在某些情况下,一个用户不想或不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用,代理对象可以在客户端和目标对象之间起中介的作用,并且可以通过中介对象去掉用户不能看到的内容和服务,或者添加用户需要的额外服务。
静态代理:即在程序运行前代理类就已经存在,也就是编写代码的时候已经将代理类的代码写好。
动态代理:在程序运行时,通过反射机制动态创建代理类。
12.Java中实现多态的机制是什么?
方法的重写Overriding和重载Overloading是Java多态性的不同表现
重写Overriding 是父类与子类之间多态的一种表现;
重载Overloading是同一个类中多态性的一种表现;
13.Java中反射的相关理解
Java的反射机制是在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,能够调用它的任意一个方法和属性,包括私有的方法和属性,这种动态地获取信息以及动态的调用对象的方法的功能就称之为Java的反射机制。
从对象出发,通过反射(.class类)可以获取到类的完整信息,(类名、class类型、所在包、具有的所有方法Method[]类型、某个方法的完整信息,包括修饰符、返回值类型、异常、参数类型、所有属性Field[ ]、某个属性的完整信息,构造器Constructors,调用类的属性或方法。
14.Java中注解的相关理解
Java注解,英文名为Annotation,一种代码级别的说明,是JDK1.5及以后版本引入的一个特性,与类、接口、枚举在同一个层次,他可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释、作用分类;注解是Java提供的一种元程序中元素关联任何信息和任何元数据(metadata)的途径和方法,Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据
注解的一般格式为:[修饰符]@interface[名称]{元素},元素是无方法体的方法声明,可以有默认值。
注解的作用:
编写文档:通过代码里标识的元数据生成文档[生成文档doc]
代码分析:通过代码里的元数据对代码进行分析[使用反射]
编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查[Override]
15.对Java中String类的理解
通过对String类的源代码分析可知,(1)String类是final类,即意味着String类不能被继承,并且他的成员方法都默认为final方法;(2)String类在源代码中实际上是通过char[ ]数组来保存字符串的;(3)String对象一旦创建就是固定不便的,对String对象的任何change操作都会生成新的对象。
16.对Java中字符串常量池的理解
字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间成本的,而且字符串在程序中使用得非常多,JVM为了提高性能和减少内存的开销,在实例化字符串的时候会进行一些优化;每当我们创建字符串常量时,JVM首先会检查字符串常量池,如果该字符床已经存在于常量池中,那么就直接返回常量池中的实例引用,如果该字符串不存在,就会实例化该字符串,并将其放在常量池中,由于字符串的不可变性,我们可以十分肯定常量池中一定不存在两个相同的字符串,Java中的常量池实际上分为两种形态:静态常量池和运行时常量池
静态常量池:即*.class文件的常量池,.class文件的常量池不仅仅包括字符串(数字)字面量,还包含类、方法的信息,占用class文件的绝大部分空间。
运行时常量池:常量存入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。
17.Java中为什么String类要设计成不可变的
在java中将String类设计成不可变的是综合考虑到各种因素的结果,需要综合内存、同步、数据结构、以及安全等方面的考虑。
字符串常量池的需要:字符串常量池是Java堆内存中一个特殊的存储区域,当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象,假若字符串对象允许改变,那么将会导致各种逻辑的错误,比如改变一个引用的字符串将会导致另一个引用出现脏数据。
允许String对象缓存HashCode:Java中String对象的哈希码被频繁的使用,比如在HashMap等容器中,字符串不变性保证了哈希码的唯一性,因此可以放心地进行缓存,这也是一种性能优化的手段,意味着不必每次都去计算新的哈希码。
安全性:String被许多Java类库用来当作参数,如:网络连接(network connection)、打开文件(opening files)等等,如果String不是不可变的,网络连接、打开文件将会被改变——这将导致一系列的安全威胁,操作的方法本以为连接上一台机器,其实不是,优于反射的参数都是字符串,同样也会引起一系列的安全问题。
18.Java中Hash码(哈希码)的理解
在Java中,哈希码代表了对象的一种特征,例如我们判断某两个字符串是否==,如果其哈希码相等,则这两个字符串是相等的,其次,哈希码是一种数据结构的算法,常见的哈希码的算法有:
Object类的HashCode,返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以哈希码也不一样。
String类的HashCode,根据String类包含的字符串的内容,根据一种特殊的算法返回哈希码,只要字符串的内容相同,返回的哈希码也相同。
Integer类:返回的哈希码就是integer对象里所包含的那个整数的数值。例如
Integer i1=new Integer(100) i1.hashCode的值就是100,由此可见两个一样大小的Integer对象返回的哈希码也一样。
19.Object类的equal方法和hashcode方法的重写
equal和hashCode的关系是这样的:(1)如果两个对象相同(即用equal比较返回true),那么他们的hashcode值一定要相同;(2)如果两个对象的hashcode相同,他们并不一定相同(即用equal比较返回false),因为hashcode的方法是可以重载的,如果不重载,会用Java.long.Object的hashcode方法,只要是不同的对象,hashcode必然不同。
由于为了提高程序的效率才实现了hashcode方法,先进行hashcode的比较,如果不同,就没有必要再进行equal的比较了,这样就大大减少了equals比较的次数,这对需要比较数量很大的运算效率特稿是很多的。
附加:一旦new对象就会在内存中开辟空间,==比较的是对象的地址值,返回的是boolean型,equal方法默认比较的对象的地址值,但是Integer等基本类型包装类以及String类中已经重写了equal()方法,比较的是对象内存中的内容,返回值是boolean型。
20.Java常用集合List与Set,以及Map的区别
Java中的集合主要分为三种类型:Set(集)、List(列表)、Map(映射);
数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型),而Java集合是可以存储和操作数目不固定的一组数据,所有的Java集合都位于java.util包中,Java集合只能存放引用类型的数据,不能存放基本数据类型。
Collection是最基本的集合接口,声明了适用于Java集合(只包括Set和List)的通用方法,Set和List都继承了Collection接口。
Set是最简单的一种集合,集合中的对象不按特定的方式排序,并且没有重复对象,Set接口主要实现了两种实现类
TreeSet:TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序;
HashSet:HashSet类按照哈希算法来存取集合中的对象,存取速度比较快;
Set具有与Collection完全一样的接口,因此没有任何额外的功能,实际上Set就是Collection,只是行为不同(这是继承与多态思想的典型应用,表现不同的行为),Set不保存重复的元素,Set接口不保证维护元素的次序。
(2) List列表的特征是其他元素以线性表的方式存储,集合中可以存放重复的对象,其接口主要实现类:
ArrayList( ):代表长度可以改变的数组,可以对元素进行随机的访问,向ArrayList( )中插入与删除元素的速度慢。
LinkedList( ):在实现类中采用链表数据结构,插入和删除的速度快,但访问的速度慢。
对于List的随机访问来说,就是只是随机来检索位于特定位置的元素,List的get(int index)方法返回集合中由参数index指定的索引位置的对象,索引下标从0开始。
Map映射是一种把关键字对象映射的集合,他的每一个元素都包括一堆键对象和值对象,Map没有继承Collection接口,从Map集合中检索元素时只要给出键对象,就会返回对应的值对象。
HashMap:Map基于散列表的实现,插入和查询“键值对”的开销是固定的,可以通过构造器设置容量capacity和负载因子load factor ,以调整容器的性能;
LinkedHashMap:类似于HashMap,但在迭代遍历时,取得“键值对”的顺序是其插入次序,只比HashMap慢一点,而在迭代访问时反而更快,因为它使用链表维护内部次序。
TreeMap:基于红黑树数据结构的实现,查看“键”或“键值对”时,他们会对其排序(次序由Comparabel和Comparator决定)
最后
按照国际惯例,给大家分享一套十分好用的Android进阶资料:《全网最全Android开发笔记》。
整个笔记一共8大模块、729个知识点,3382页,66万字,可以说覆盖了当下Android开发最前沿的技术点,和阿里、腾讯、字节等等大厂面试看重的技术。
好啦,这份资料就给大家介绍到这了,有需要详细文档的小伙伴,可以微信扫下方二维码回复JJ免费领取哈~
因为所包含的内容足够多,所以,这份笔记不仅仅可以用来当学习资料,还可以当工具书用。
如果你需要了解某个知识点,不管是Shift+F 搜索,还是按目录进行检索,都能用最快的速度找到你要的内容。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照整个知识体系编排的。
(一)架构师必备Java基础
1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……
(二)设计思想解读开源框架
1、热修复设计
2、插件化框架设计
3、组件化框架设计
4、图片加载框架
5、网络访问框架设计
6、RXJava响应式编程框架设计
……
(三)360°全方位性能优化
1、设计思想与代码质量优化
2、程序性能优化
- 启动速度与执行效率优化
- 布局检测与优化
- 内存优化
- 耗电优化
- 网络传输与数据储存优化
- APK大小优化
3、开发效率优化
- 分布式版本控制系统Git
- 自动化构建系统Gradle
……
(四)Android框架体系架构
1、高级UI晋升
2、Android内核组件
3、大型项目必备IPC
4、数据持久与序列化
5、Framework内核解析
……
(五)NDK模块开发
1、NDK开发之C/C++入门
2、JNI模块开发
3、Linux编程
4、底层图片处理
5、音视频开发
6、机器学习
……
(六)Flutter学习进阶
1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter Dart语言系统入门
……
(七)微信小程序开发
1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战
……
(八)kotlin从入门到精通
1、准备开始
2、基础
3、类和对象
4、函数和lambda表达式
5、其他
……
好啦,这份资料就给大家介绍到这了,有需要详细文档的小伙伴,可以微信扫下方二维码回复JJ免费领取哈~
-
Android面试试题及答案
2014-08-12 10:32:57Android面试试题及答案,讲叙了常见Android移动开发应用中面试题目及答案,面试前看看能收到意想不到的效果 -
Android 面试题及答案.doc
2020-08-29 09:46:01Android 面试题及答案 1 Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念 DVM指dalivk的虚拟机每一个Android应用程序都在它自己的进程中运行都拥有一个独立的Dalvik虚拟机实例而每一个DVM都是在... -
Android面试题及答案整理(2022年最新Android面试题大全带答案)
2022-01-17 21:08:55Android面试题及答案(2022年最新Android面试题大全带答案),发现网上很多Android面试题整理都没有答案,所以花了很长时间搜集,本套Android面试题大全,Android面试题大汇总,有大量经典的Android面试题以及答案,...Android面试题及答案(2022年最新Android面试题大全带答案),发现网上很多Android面试题整理都没有答案,所以花了很长时间搜集,本套Android面试题大全,Android面试题大汇总,有大量经典的Android面试题以及答案,包含Android语言常见面试题、Android工程师高级面试题及一些大厂Android开发面试宝典,面试经验技巧等,应届生,实习生,企业工作过的,都可参考学习!
这套Android面试题汇总大全,希望对大家有帮助哈~
此面试题合集分为9个部分:Java基础、Android基础、UI控件篇、网络通信篇、架构设计篇、性能优化篇、源码流程篇、新技术篇、面试篇,共1932页,从知识点到面试题到新技术都进行了全面以及详细的解析!
由于篇幅限制,下文中只展示部分内容,朋友们如果需要这份完整版的PDF资料合集,微信扫描下方CSDN官方二维码免费领取【
保证100%免费
】。第一章 Java基础
- 静态内部类和非静态内部类的比较
- 多态的理解与应用
- java方法的多态性理解
- java中接口和继承的区别
- 线程池的好处,详解,单例(绝对好记)
- 线程池的优点及其原理
- 线程池的优点(重点)
- 为什么不推荐通过Executors直接创建线程池
- 不怕难之BlockingQueue及其实现
- 深入理解ReentrantLock与Condition
- Java多线程:线程间通信之Lock
- Synchronized 关键字原理
- ReentrantLock原理
- HashMap中的Hash冲突解决和扩容机制
- JVM常见面试题
- JVM内存结构
- 类加载机制/双亲委托
第二章 Android基础
- Activity知识点(必问)
- Fragment知识点
- Service知识点
- Intent知识点
第三章 UI控件篇
- 屏幕适配
- 主要控件优化
- 事件分发与嵌套滚动
- 动态化页面构建方案
第四章 网络通信篇
- 网络协议
第五章 架构设计篇
- MVP架构设计
- 组件化架构
第六章 性能优化篇
- 启动优化
- 内存优化
- 绘制优化
- 安装包优化
第七章 源码流程篇
- 开源库源码分析
- Glide源码分析
- Android面试题:Glide
- day 20 面试题:Glide面试题
- 聊一聊关于Glide在面试中的那些事
- 面试官:简历上如果写Glide,请注意以下几点…
- OkHttp源码分析
- okhttp连接池复用机制
- okhttp 流程和优化的实现
- 一篇让你受用的okhttp分析
- OkHttp面试之–OkHttp的整个异步请求流程
- OkHttp面试之–HttpEngine中的sendRequest方法详解
- OkHttp解析大总结
- Okhttp任务队列工作原理
- Android高频面试专题 - 架构篇(二)okhttp面试必知必会
- Android 网络优化,使用 HTTPDNS 优化 DNS,从原理到 OkHttp 集成
- Retrofit源码分析
- RxJava源码分析
第八章 新技术篇
- 实战问题篇
第九章 面试篇
- 开源文档
- 面试文献
篇幅有限,详细内容就不作完全展示了,欢迎大家一键三连,若需要此面试题合集,直接扫描下方CSDN官方二维码免费领取【
保证100%免费
】~ -
2022年Android面试题及答案汇总,每天20题【六】持续更新中...(从面试官角度帮你审视问题)
2022-05-10 20:29:53这是我既前两次做Android面试题合集之后重新整理和完善的一份新的面试题。 写在前面,之前面试题带入的都是咱们求职者的视角,这次我联络的是部分招聘人员,当然具体名字和公司不方便透露,总之,该部分面试是从招聘...文末有福利
前言
本文乃找工作、招人必备之良品。后期不断完善中…
这是我既前两次做Android面试题合集之后重新整理和完善的一份新的面试题。
写在前面,之前面试题带入的都是咱们求职者的视角,这次我联络的是部分招聘人员,当然具体名字和公司不方便透露,总之,该部分面试是从招聘角度出发,当然作为求职者我觉得只会收获更加丰富。
如何招聘人,搜集了一些知识点。如何做好应聘准备,也收集了一些主要知识点,供你参考。
- Android基础知识:基本涵盖Android所有知识体系,四大组件,Fragment,WebView,事件分发,View绘制…
- Java基础知识&高阶知识点:基础部分不谈了,高阶部分:泛型,反射,Java虚拟机…
- 算法与数据结构:链表,堆,栈,树…
- Android常用框架:异步,网络,图片加载,内存优化,依赖注入,数据库等框架
- Android前沿技术:Android组件化,热更新,插件化,消息推送,AOP面向切面编程,Flutter(谷歌的移动UI框架)…
- 源码分析:Android源码分析,启动一个app的源码分析,常用框架源码分析,Java源码分析,集合源码分析…
- 网络基础:五层网络模型,三次握手&四次挥手,请求头&响应头,Socket&WebSocket…
81、试从源码角度分析Handler的post和sendMessage方法的区别和应用场景?
handler.post和handler.sendMessage方法最后都会调用sendMessageAtTime方法进行消息的发送,但是在post方法中message是通过getPostMessage(Runnable r)这个方法获取的message,在这个方法中有这样一句代码m.callback = r ,给message的callback赋值为runnable对象,而在dispatchMessage这个方法中对消息进行分发的时候,先进行了msg.callback != null的判断,如果不为null,消息是通handleCallback(msg);这个方法处理的,在这个方法中message.callback.run();调用的是post方法传递过来的runnable内的run方法处理消息,如果为空,再进行handler内部的callback判断mCallback != null,如果handler内的callback不为空,执行mCallback.handleMessage(msg)这个处理消息并判断返回是否为true,如果返回true,消息处理结束,如果返回false,消息交给handler的handleMessage(msg)处理。所以区别就是调用post方法的消息是在post传递的Runnable对象的run方法中处理,而调用sendMessage方法需要重写handleMessage方法或者给handler设置callback,在callback的handleMessage中处理并返回true。
82、 Handler中有Loop死循环,为什么没有阻塞主线程,原理是什么?
主线程挂起
Looper 是一个死循环, 不断的读取MessageQueue中的消息, loop 方法会调用 MessageQueue 的 next 方法来获取新的消息,next 操作是一个阻塞操作,当没有消息的时候 next 方法会一直阻塞, 进而导致 loop 一直阻塞,理论上 messageQueue.nativePollOnce 会让线程挂起-阻塞-block 住, 但是为什么, 在发送 delay 10s 的消息, 假设消息队列中, 目前只有这一个消息;那么为什么在这 10s 内, UI是可操作的, 或者列表页是可滑动的, 或者动画还是可以执行的?
先不讲 nativePollOnce 是怎么实现的阻塞, 我们还知道, 另外一个 nativeWake, 是实现线程唤醒的;
那么什么时候会, 触发这个方法的调用呢, 就是在有新消息添加进来的时候, 可是并没有手动添加消息啊?
display 每隔16.6秒, 刷新一次屏幕
SurfaceFlingerVsyncChoreographer 每隔16.6秒, 发送一个 vSync 信号;
FrameDisplayEventReceiver 收到信号后, 调用 onVsync方法, 通过 handler 消息发送到主线程处理, 所以就会有消息添加进来, UI线程就会被唤醒;
事实上, 安卓系统, 不止有一个屏幕刷新的信号, 还有其他的机制, 比如输入法和系统广播, 也会往主线程的MessageQueue 添加消息;所以, 可以理解为, 主线程也是随时挂起, 随时被阻塞的;系统怎么实现的阻塞与唤醒
这种机制是通过pipe(管道)机制实现的;简单来说, 管道就是一个文件在管道的两端, 分别是两个打开文件的, 文件描述符, 这两个打开文件描述符, 都是对应同一个文件, 其中一个是用来读的, 别一个是用来写的;
一般的使用方式就是, 一个线程通过读文件描述符, 来读管道的内容, 当管道没有内容时, 这个线程就会进入等待状态,而另外一个线程, 通过写文件描述符, 来向管道中写入内容,写入内容的时候, 如果另一端正有线程, 正在等待管道中的内容, 那么这个线程就会被唤醒;这个等待和唤醒的操作是如何进行的呢, 这就要借助 Linux系统中的 epoll 机制了, Linux 系统中的 epoll 机制为处理大批量句柄而作了改进的 poll,是 Linux 下多路复用 IO 接口 select/poll 的增强版本, 它能显著减少程序, 在大量并发连接中, 只有少量活跃的情况下的系统 CPU 利用率;
即当管道中有内容可读时, 就唤醒当前正在等待管道中的内容的线程;
怎么证明, 线程被挂起了
@Override public void onCreateData(@Nullable Bundle bundle) { new Thread() { @SuppressLint("HandlerLeak") @Override public void run() { super.run(); LogTrack.v("thread.id = " + Thread.currentThread().getId()); Looper.prepare(); Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { super.handleMessage(msg); LogTrack.v("thread.id = " + Thread.currentThread().getId() + ", what = " + msg.what); }特性 补间动画 属性动画 view 动画 支持 支持 非view动画 不支持 支持 可扩展性和灵活性 差 好 view属性是否变化 无变化 发生变化 复杂动画能力 局限 良好 场景应用范围 一般 满足大部分应用场景 第三节 Android UI 绘制相关 3.1 Android 补间动画和属性动画的区别? }; LogTrack.w("loop.之前"); // 执行了 Looper.loop(); // 执行了 LogTrack.w("loop.之后"); // 无法执 行 } }.start(); }
83、Android 补间动画和属性动画的区别?
特性 补间动画 属性动画 view动画 支持 支持 非view动画 不支持 支持 可扩展性和灵活性 差 好 view属性是否变化 无变化 发生变化 复杂动画能力 局限 良好 场景应用范围 一般 满足大部分应用场景 84、Window和DecorView是什么?DecorView又是如何和Window建立联系的?
Window 是 WindowManager 最顶层的视图,它负责背景(窗口背景)、Title之类的标准的UI元素,Window 是一个抽象类,整个Android系统中, PhoneWindow是 Window 的唯一实现类。至于 DecorView,它是一个顶级 View,内部会包含一个竖直方向的LinearLayout,这个LinearLayout 有上下两部分,分为 titlebar 和contentParent 两个子元素,contentParent 的 id 是content,而我们自定义的 Activity 的布局就是contentParent 里面的一个子元素。View 层的所有事件都要先经过 DecorView 后才传递给我们的 View。DecorView 是 Window 的一个变量,即 DecorView 作为一切视图的根布局,被 Window 所持有,我们自定义的View 会被添加到 DecorView ,而DecorView 又会被添加到 Window 中加载和渲染显示。此处放一张它们的简单内部层次结构图:
85、简述一下 Android 中 UI 的刷新机制?
界面刷新的本质流程
1.通过ViewRootImpl的scheduleTraversals()进行界面的三大流程。
2.调用到scheduleTraversals()时不会立即执行,而是将该操作保存到待执行队列中。并给底层的刷新信号注册监听。
3.当VSYNC信号到来时,会从待执行队列中取出对应的scheduleTraversals()操作,并将其加入到主线程的消息队列中。
4.主线程从消息队列中取出并执行三大流程:onMeasure()-onLayout()-onDraw()同步屏障的作用
1.同步屏障用于阻塞住所有的同步消息(底层VSYNC的回调onVsync方法提交的消息是异步消息)
2.用于保证界面刷新功能的performTraversals()的优先执行。同步屏障的原理?
1.主线程的Looper会一直循环调用MessageQueue的next方法并且取出队列头部的Message执行,遇到同步屏障(一种特殊消息)后会去寻找异步消息执行。如果没有找到异步消息就会一直阻塞下去,除非将同步屏障取出,否则永远不会执行同步消息。
2.界面刷新操作是异步消息,具有最高优先级3. 我们发送的消息是同步消息,再多耗时操作也不会影响UI的刷新操作86、LinearLayout, FrameLayout,RelativeLayout 哪个效率高, 为什么?
对于比较三者的效率那肯定是要在相同布局条件下比较绘制的流畅度及绘制过程,在这里流畅度不好表达,并且受其他外部因素干扰比较多,比如CPU、GPU等等,我说下在绘制过程中的比较,
1、Fragment是从上到下的一个堆叠的方式布局的,那当然是绘制速度最快,只需要将本身绘制出来即可,但是由于它的绘制方式导致在复杂场景中直接是不能使用的,所以工作效率来说Fragment仅使用于单一场景,
2、LinearLayout 在两个方向上绘制的布局,在工作中使用页比较多,绘制的时候只需要按照指定的方向绘制,绘制效率比Fragment要慢,但使用场景比较多,
3、RelativeLayout 它的没个子控件都是需要相对的其他控件来计算,按照View树的绘制流程、在不同的分支上要进行计算相对应的位置,绘制效率最低,但是一般工作中的布局使用较多,所以说这三者之间效率分开来讲个有优势、不足,那一起来讲也是有优势、不足,所以不能绝对的区分三者的效率,好马用好铵 那需求来说87、谈谈Android的事件分发机制?
当点击的时候,会先调用顶级viewgroup的dispatchTouchEvent,如果顶级的viewgroup拦截了此事件(onInterceptTouchEvent返回true),则此事件序列由顶级viewgroup处理。如果顶级viewgroup设置setOnTouchListener,则会回调接口中的onTouch,此时顶级的viewgroup中的onTouchEvent不再回调,如果不设置setOnTouchListener则onTouchEvent会回调。如果顶级viewgroup设置setOnClickListener,则会回调接口中的onClick。如果顶级viewgroup不拦截事件,事件就会向下传递给他的子view,然后子view就会调用它的dispatchTouchEvent方法。
88、 谈谈自定义View的流程?
1.安卓View的绘制流程(比较简单,想要深入的可以去
看源码)
2.安卓自定义View的绘制步骤自定义View是一个老生常谈的问题,对于一个Android开发者来说是必须掌握的知识点,也是Android开发进阶的必经之路。
要想安卓理解自定义View的流程,首先我们要了解View的绘制流程。分析之前,我们先来看底下面这张图:
View的绘制流程
DecorView是一个应用窗口的根容器,它本质上是一个FrameLayout。DecorView有唯一一个子View,它是一个垂直LinearLayout,包含两个子元素,一个是TitleView(ActionBar的容器),另一个是ContentView(窗口内容的容器)。关于ContentView,它是一个FrameLayout(android.R.id.content),我们平常用的setContentView就是设置它的子View。上图还表达了每个Activity都与一个Window(具体来说是PhoneWindow)相关联,用户界面则由Window所承载。ViewRoot
在介绍View的绘制前,首先我们需要知道是谁负责执行View绘制的整个流程。实际上,View的绘制是由ViewRoot来负责的。每个应用程序窗口的decorView都有一个与之关联的ViewRoot对象,这种关联关系是由WindowManager来维护的。那么decorView与ViewRoot的关联关系是在什么时候建立的呢?答案是Activity启动时,ActivityThread.handleResumeActivity()方法中建立了它们两者的关联关系。这里我们不具体分析它们建立关联的时机与方式,感兴趣的同学可以参考相关源码。下面我们直入主题,分析一下ViewRoot是如何完成View的绘制的。
View绘制的起点
当建立好了decorView与ViewRoot的关联后,ViewRoot类的requestLayout()方法会被调用,以完成应用程序用户界面的初次布局。实际被调用的是ViewRootImpl类的requestLayout()方法,这个方法的源码如下:@Override public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { // 检查发起布局请求的线程是否为主线程 checkThread(); mLayoutRequested = true; scheduleTraversals(); } }
上面的方法中调用了scheduleTraversals()方法来调度一次完成的绘制流程,该方法会向主线程发送一个“遍历”消息,最终会导致ViewRootImpl的performTraversals()方法被调用。下面,我们以performTraversals()为起点,来分析View的整个绘制流程。
三个阶段
View的整个绘制流程可以分为以下三个阶段:- measure: 判断是否需要重新计算View的大小,需要的话则计算;
- layout: 判断是否需要重新计算View的位置,需要的话则计算;
- draw: 判断是否需要重新绘制View,需要的话则重绘制。
这三个子阶段可以用下图来描述:
measure阶段此阶段的目的是计算出控件树中的各个控件要显示其内容的话,需要多大尺寸。起点是ViewRootImpl的measureHierarchy()方法,这个方法的源码如下:
private boolean measureHierarchy(final View host, final WindowManager.LayoutParams lp, final Resources res, final int desiredWindowWidth, final int desiredWindowHeight) { // 传入的desiredWindowXxx为窗口尺寸 int childWidthMeasureSpec; int childHeightMeasureSpec; boolean windowSizeMayChange = false; . . .上面的代码中调用getRootMeasureSpec()方法来获取根 MeasureSpec,这个根MeasureSpec代表了对decorView 的宽高的约束信息。具体的内部方法您可以直接再AS进行 查看,不再赘述。 layout阶段 layout阶段的基本思想也是由根View开始,递归地完成整 个控件树的布局(layout)工作。 View.layout() boolean goodMeasure = false; if (!goodMeasure) { childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width); childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height); performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); if (mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight()) { windowSizeMayChange = true; } } return windowSizeMayChange; }
上面的代码中调用getRootMeasureSpec()方法来获取根MeasureSpec,这个根MeasureSpec代表了对decorView的宽高的约束信息。具体的内部方法您可以直接再AS进行查看,不再赘述。
layout阶段
ayout阶段的基本思想也是由根View开始,递归地完成整个控件树的布局(layout)工作。
View.layout()
我们把对decorView的layout()方法的调用作为布局整个控件树的起点,实际上调用的是View类的layout()方法,源码如下:public void layout(int l, int t, int r, int b) { // l为本View左边缘与父View左边缘的距离 // t为本View上边缘与父View上边缘的距离 // r为本View右边缘与父View左边缘的距离 // b为本View下边缘与父View上边缘的距离 . . . boolean changed = isLayoutModeOptical(mParent) ? setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { onLayout(changed, l, t, r, b); . . . } . . . }
这个方法会调用setFrame()方法来设置View的mLeft、mTop、mRight和mBottom四个参数,这四个参数描述了View相对其父View的位置(分别赋值为l, t, r, b),在setFrame()方法中会判断View的位置是否发生了改变,若发生了改变,则需要对子View进行重新布局,对子View的局部是通过onLayout()方法实现了。由于普通View( 非ViewGroup)不含子View,所以View类的onLayout()方法为空。因此接下来,您可以通过源码查看ViewGroup类的onLayout()方法的实现,不再赘述。
draw阶段
对于本阶段的分析,我们以decorView.draw()作为分析的起点,也就是View.draw()方法,它的源码如下:public void draw(Canvas canvas) { . . . // 绘制背景,只有dirtyOpaque为false时才进行绘 制,下同 int saveCount; if (!dirtyOpaque) { drawBackground(canvas); } . . . // 绘制自身内容 if (!dirtyOpaque) onDraw(canvas); // 绘制子View dispatchDraw(canvas); . . . // 绘制滚动条等 onDrawForeground(canvas); }
简单起见,在上面的代码中我们省略了实现滑动时渐变边框效果相关的逻辑。实际上,View类的onDraw()方法为空,因为每个View绘制自身的方式都不尽相同,对于decorView来说,由于它是容器View,所以它本身并没有什么要绘制的。dispatchDraw()方法用于绘制子View,显然普通View(非ViewGroup)并不能包含子View,所以View类中这个方法的实现为空。
ViewGroup类的dispatchDraw()方法中会依次调用drawChild()方法来绘制子View,drawChild()方法的源码如下:
protected boolean drawChild(Canvas canvas, View child, long drawingTime) { return child.draw(canvas, this, drawingTime); }
这个方法调用了View.draw(Canvas, ViewGroup,long)方法来对子View进行绘制。在draw(Canvas, ViewGroup,long)方法中,首先对canvas进行了一系列变换,以变换到将要被绘制的View的坐标系下。完成对canvas的变换后,便会调用View.draw(Canvas)方法进行实际的绘制工作,此时传入的canvas为经过变换的,在将被绘制View的坐标系下的canvas。
进入到View.draw(Canvas)方法后,会向之前介绍的一样,执行以下几步:
- 绘制背景;
- 通过onDraw()绘制自身内容;
- 通过dispatchDraw()绘制子View;
- 绘制滚动条
至此,整个View的绘制流程我们就分析完了。
Android自定义View / ViewGroup的步骤大致如下:
1.自定义属性;
2.选择和设置构造方法;
3.重写onMeasure()方法;
4.重写onDraw()方法;
5.重写onLayout()方法;
6.重写其他事件的方法(滑动监听等);89、针对RecyclerView你做了哪些优化?
1 onBindViewHolder
这个方法含义应该都知道是绑定数据,并且是在UI线程,所以要尽量在这个方法中少做一些业务处理
2 数据优化
采用android Support 包下的DIffUtil集合工具类结合RV分页加载会更加友好,节省性能
3item优化
减少item的View的层级,(pps:当然推荐把一个item自定义成一个View,如果有能力的话),如果item的高度固定的话可以设置setHasFixedSize(true),避免requestLayout浪费资源
4 使用RecycledViewPool
RecycledViewPool是对item进行缓存的,item相同的不同RV可以才使用这种方式进行性能提升
5 Prefetch预取
这是在RV25.1.0及以上添加的新功能,预取详情
6 资源回收
通过重写RecyclerView.onViewRecycled(holder)来合理的回收资源。
90、谈谈如何优化ListView?
ViewHolder什么的持有View
预加载/懒加载数据什么的
大招:用RecyclerView替换ListView
绝招:直接删除控件91、 谈谈自定义LayoutManager的流程?
1.确定Itemview的LayoutParams
generateDefaultLayoutParams2.确定所有itemview在recyclerview的位置,并且回收和复
用itemview
onLayoutChildren3.添加滑动
canScrollVertically92、什么是 RemoteViews?使用场景有哪些?
RemoteViews
RemoteViews翻译过来就是远程视图.顾名思义,RemoteViews不是当前进程的View,是属于SystemServer进程.应用程序与RemoteViews之间依赖Binder实现了进程间通信.
用法
通常是在通知栏//1.创建RemoteViews实例 RemoteViews mRemoteViews=new RemoteViews("com.example.remoteviewdemo", R.layout.remoteview_layout); //2.构建一个打开Activity的PendingIntent Intent intent=new Intent(MainActivity.this,MainActivity.class); PendingIntent mPendingIntent=PendingIntent.getActivity(Main Activity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); //3.创建一个Notification mNotification = new Notification.Builder(this) .setSmallIcon(R.drawable.ic_launcher) .setContentIntent(mPendingIntent) .setContent(mRemoteViews) .build(); //4.获取NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE ); Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //弹出通知 manager.notify(1, mNotification); } });
93、谈一谈获取View宽高的几种方法?
1.OnGlobalLayoutListener获取
2.OnPreDrawListener获取
3.OnLayoutChangeListener获取
4.重写View的onSizeChanged()
5.使用View.post()方法94、谈一谈插值器和估值器?
1、插值器,根据时间(动画时常)流逝的百分比来计算属性变化的百分比。系统默认的有匀速,加减速,减速插值器。
2、估值器,通过上面插值器得到的百分比计算出具体变化的值。系统默认的有整型,浮点型,颜色估值器
3、自定义只需要重写他们的evaluate方法就可以了。95、 getDimension、getDimensionPixelOffset 和getDimensionPixelSize 三者的区别?
相同点
单位为dp/sp时,都会乘以density,单位为px则不乘
不同点
1、getDimension返回的是float值
2、getDimensionPixelSize,返回的是int值,float转成int时,四舍五入
3、getDimensionPixelOffset,返回的是int值,float转int时,向下取整(即忽略小数值)96、 请谈谈源码中StaticLayout的用法和应用场景?
构造方法:
public StaticLayout(CharSequence source, int bufstart, int bufend, TextPaint paint, int outerwidth, Alignment align, float spacingmult, float spacingadd, boolean includepad, TextUtils.TruncateAt ellipsize, int ellipsizedWidth) { this(source, bufstart, bufend, paint, outerwidth, align, TextDirectionHeuristics.FIRSTSTRONG_LTR, spacingmult, spacingadd, includepad, ellipsize, ellipsizedWidth, Integer.MAX_VALUE); }
说明参数的作用:
CharSequence source 需要分行的字符串 int bufstart 需要分行的字符串从第几的位置开始 int bufend 需要分行的字符串到哪里结束 TextPaint paint 画笔对象 int outerwidth layout的宽度,超出时换行 Alignment align layout的对其方式,有 ALIGN_CENTER, ALIGN_NORMAL, ALIGN_OPPOSITE 三种 float spacingmult 相对行间距,相对字体大小,1.5f表 示行间距为1.5倍的字体高度。 float spacingadd 在基础行距上添加多少 boolean includepad, TextUtils.TruncateAt ellipsize 从什么位置开始省 略 int ellipsizedWidth 超过多少开始省略
97、有用过ConstraintLayout吗?它有哪些特点?
属性图:
98、关于LayoutInflater,它是如何通过inflate 方法获取到具体View的?
系统通过LayoutInflater.from创建出布局构造器,inflate方法中,最后会掉用createViewFromTag 这里他会去判断两个参数 factory2 和factory 如果都会空就会系统自己去创建view, 并且通过一个xml解析器,获取标签名字,然后判断是<Button还是xxx.xxx.xxView. 然后走createView 通过拼接得到全类名路径,反射创建出类。
99、谈一谈Fragment懒加载?
重写setUserVisibleHint()
100、谈谈RecyclerView的缓存机制?
scrap viewCache recyclerPool
scrap 是当前展示的缓存, 在onlayout时候 缓存viewCache 是屏幕外看不见的缓存, 可以吧viewCache设置大点,空间换时间 避免段距离内快速滑动卡顿以上两种缓存是不走 createView和 onbindrecyclerPool 比较特殊他是会走 onbind的,他可以被多个recyclerView共享内部的item,实际用途是:多个recyclerView之间共享item,应用在 垂直recyclerView 内嵌水平recyclerView,或者viewpager中多个recyclerView
最后
按照国际惯例,给大家分享一套十分好用的Android进阶资料:《全网最全Android开发笔记》。
整个笔记一共8大模块、729个知识点,3382页,66万字,可以说覆盖了当下Android开发最前沿的技术点,和阿里、腾讯、字节等等大厂面试看重的技术。
好啦,这份资料就给大家介绍到这了,有需要详细文档的小伙伴,可以微信扫下方二维码回复JJ免费领取哈~
因为所包含的内容足够多,所以,这份笔记不仅仅可以用来当学习资料,还可以当工具书用。
如果你需要了解某个知识点,不管是Shift+F 搜索,还是按目录进行检索,都能用最快的速度找到你要的内容。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照整个知识体系编排的。
(一)架构师必备Java基础
1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……
(二)设计思想解读开源框架
1、热修复设计
2、插件化框架设计
3、组件化框架设计
4、图片加载框架
5、网络访问框架设计
6、RXJava响应式编程框架设计
……
(三)360°全方位性能优化
1、设计思想与代码质量优化
2、程序性能优化
- 启动速度与执行效率优化
- 布局检测与优化
- 内存优化
- 耗电优化
- 网络传输与数据储存优化
- APK大小优化
3、开发效率优化
- 分布式版本控制系统Git
- 自动化构建系统Gradle
……
(四)Android框架体系架构
1、高级UI晋升
2、Android内核组件
3、大型项目必备IPC
4、数据持久与序列化
5、Framework内核解析
……
(五)NDK模块开发
1、NDK开发之C/C++入门
2、JNI模块开发
3、Linux编程
4、底层图片处理
5、音视频开发
6、机器学习
……
(六)Flutter学习进阶
1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter Dart语言系统入门
……
(七)微信小程序开发
1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战
……
(八)kotlin从入门到精通
1、准备开始
2、基础
3、类和对象
4、函数和lambda表达式
5、其他
……
好啦,这份资料就给大家介绍到这了,有需要详细文档的小伙伴,可以微信扫下方二维码回复JJ免费领取哈~
-
2021年Android面试题及答案收集(不断更新中)
2018-10-15 18:40:202021年Android面试题及答案(适合中高级) 找工作、招人必备之良品。后期不断完善中…… -
android面试题及答案
2021-03-07 15:15:47引导语:android是这段时间非常热门的开发专业之一,而有关android的面试题及答案哪里有呢?接下来是小编为你带来收集整理的文章,欢迎阅读!在android中,请简述jni的调用过程。1安装和下载cygwin,下载 android ... -
android面试题大全(含答案)
2017-03-03 18:10:15最新整理的android常问面试题,还有详细答案 -
Android面试题及答案(详细整理)
2017-04-17 08:12:13onStop(): Activity被停止并转为不可见阶段及后续的生命周期事件时调用。 onRestart(): Activity被重新启动时调用。该活动仍然在栈中,而不是启动新的Activity。 1、完整生命周期: 即从一个Activity从出现... -
android 面试题及答案
2013-12-09 13:34:22android 面试题及其答案 希望对大家有帮助! -
71道经典Android面试题和答案
2018-04-03 22:30:06------71道经典Android面试题和答案助你轻松拿下offer------ -
软件测试android面试题及答案(2).docx
2020-08-13 22:31:02请介绍下Android的数据存储方式 一.SharedPreferences方式 二.文件存储方式 三.SQLite数据库方式 四.内容提供器(Content provider)方式 五. 网络存储方式 请介绍下ContentProvider是如何实现数据共享的 创建一个属于... -
2019最新android高级工程师面试题整理.doc
2019-09-09 11:13:532019年高级安卓工程师面试最新整理,从基础到框架都有涉及,非常全面,希望对你有帮助。 -
2022年Android面试题及答案汇总,每天20题【三】持续更新中...(从面试官角度帮你审视问题)
2022-04-21 15:59:54这是我既前两次做Android面试题合集之后重新整理和完善的一份新的面试题。 写在前面,之前面试题带入的都是咱们求职者的视角,这次我联络的是部分招聘人员,当然具体名字和公司不方便透露,总之,该部分面试是从招聘... -
Android面试题及答案
2012-08-14 21:08:04嘿嘿,献上Android面试题及答案,面试的时候有点底了 -
2022年Android面试题及答案汇总,每天20题【四】持续更新中...(从面试官角度帮你审视问题)
2022-04-21 16:18:37这是我既前两次做Android面试题合集之后重新整理和完善的一份新的面试题。 写在前面,之前面试题带入的都是咱们求职者的视角,这次我联络的是部分招聘人员,当然具体名字和公司不方便透露,总之,该部分面试是从招聘... -
2022年Android面试题及答案收集(不断更新中)
2022-02-21 16:17:19Android基础知识:基本涵盖Android所有知识体系,四大组件,Fragment,WebView,事件分发,View绘制… Java基础知识&高阶知识点:基础部分不谈了,高阶部分:泛型,反射,Java虚拟机… 算法与数据结构:链表,堆,栈... -
2022最新Android面试题及答案整理(共计4176页PDF)包含腾讯、字节、百度、小米、阿里等大厂面试真题
2022-03-03 16:46:36前言 最近在准备面试,然后复习下之前写过的项目,书籍,笔记,文章。一看很多知识点都没有印象,最可拍的是连自己为了防止忘记写的文章竟然都感觉不是自己写...这里给大家分享一份最新整理的1932页《2022年Android 中 -
字节跳动(头条)2021 最新 Android 面试题及答案 (已收 offer)
2022-04-11 17:57:09阿里面试的情况 [](()【6面 - 大 Boss】 算法 - 数组插入,考虑扩容 在项目的遇到的比较有挑战的事是什么? 你在美团负责的业务有哪些? 未来几年的规划是什么? 你觉得你的优点是什么?缺点是什么? 现在的职级,... -
Android面试题集2020版(包含答案整理)第二部分.pdf
2021-03-11 15:54:51多看一眼离大厂越进一步