| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android常见基础面试题 -> 正文阅读 |
|
[移动开发]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 一个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 ? 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程序的区别?
? 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时,没有使用缓存convertView。 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解锁。 26.android 中的动画有哪几类,它们的特点和区别是什么 ? 三种,Tween(补间)?动画、Frame(帧动画)?动画和最新的属性动画。 Tween 动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化 ; Frame 动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。属性动画和补间动画类似,不过是真的属性在变动,包括可视属性和其他属性。一般情况下推荐使用最新的属性动画。 27.handler 机制的原理 Android 提供了 Handler 和 Looper 来满足线程间的通信。 Handler 先进先出原则。 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange) 。 1)Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 Message Queue( 消息队列 ) 。 2)Handler: 你可以构造 Handler 对象来与 Looper 沟通,以便 push 新消息到 Message Queue 里; 或者接收 Looper 从 Message Queue 取出 ) 所送来的消息。 3) Message Queue( 消息队列 ): 用来存放线程放入的消息。
整个消息的循环流程还是比较清晰的,具体说来: Handler通过sendMessage()发送消息Message到消息队列MessageQueue。 Looper通过loop()不断提取触发条件的Message,并将Message交给对应的target handler来处理。 target handler调用自身的handleMessage()方法来处理Message。 28.android 中线程与线程,进程与进程之间如何通信 1 、一个 Android 程序开始运行时,会单独启动一个 Process 。默认情况下,所有这个程序中的 Activity 或者 Service 都会跑在这个 Process 。默认情况下,一个 Android 程序也只有一个 Process ,但一个 Process 下却可以有许多个 Thread。 2 、一个 Android 程序开始运行时,就有一个主线程 Main Thread 被创建。该线程主要负责 UI 界面的显示、更新和控件交互,所以又叫 UI Thread 。一个 Android 程序创建之初,一个 Process 呈现的是单线程模型 — 即 Main Thread ,所有的任务都在一个线程中运行。所以, Main Thread 所调用的每一个函数,其耗时应该越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象)。 3 、 Android 单线程模型: Android UI 操作并不是线程安全的并且这些操作必须在 UI 线程中执行。如果在子线程中直接修改 UI ,会导致异常。 29. 4 种 activity 的启动模式 standard: 标准模式 ,一调用 startActivity() 方法就会产生一个新的实例。 singleTop : 如果已经有一个实例位于 Activity 栈的顶部时,就不产生新的实例,而只是调用 Activity中的 newInstance() 方法。如果不位于栈顶,会产生一个新的实例。 singleTask : 会在一个新的 task 中产生这个实例,以后每次调用都会使用这个,不会去产生新的实例了。 singleInstance : 这个跟 singleTask 基本上是一样,只有一个区别:在这个模式下的 Activity 实例所处的 task 中,只能有这个 activity 实例,不能有其他的实例。 30.什么是 ANR 如何避免它 ? 在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application NotResponding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要这样,这样系统就不会显示ANR给用户。 不同的组件发生ANR的时间不一样,Activity是5秒,BroadCastReceiver是10秒,Service是20秒(均为前台)。 如果开发机器上出现问题,我们可以通过查看/data/anr/traces.txt即可,最新的ANR信息在最开始部分。 主线程被IO操作(从4.0之后网络IO不允许在主线程中)阻塞。 主线程中存在耗时的计算 主线程中错误的操作,比如Thread.wait或者Thread.sleep等 Android系统会监控程序的响应状况,一旦出现下面两种情况,则弹出ANR对话框 应用在5秒内未响应用户的输入事件(如按键或者触摸) BroadcastReceiver未在10秒内完成相关的处理 Service在特定的时间内无法处理完成 20秒 修正: 1、使用AsyncTask处理耗时IO操作。 2、使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同。 3、使用Handler处理工作线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。 4、Activity的onCreate和onResume回调中尽量避免耗时的代码。 BroadcastReceiver中onReceive代码也要尽量减少耗时,建议使用IntentService处理。 解决方案: 将所有耗时操作,比如访问网络,Socket通信,查询大 量SQL 语句,复杂逻辑计算等都放在子线程中去,然 后通过handler.sendMessage、runonUIThread、AsyncTask、RxJava等方式更新UI。无论如何都要确保用户界面的流畅 度。如果耗时操作需要让用户等待,那么可以在界面上显示度条。 31.android 谈谈socket通信 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信。两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据。而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求。 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信。通过建立socket连接,可为通信双方的数据传输传提供通道。socket的主要特点有数据丢失率低,使用简单且易于移植。 Socket是一种抽象层,应用程序通过它来发送和接收数据,使用Socket可以将应用程序添加到网络中,与处于同一网络中的其他应用程序进行通信。简单来说,Socket提供了程序内部与外界通信的端口并为通信双方的提供了数据传输通道。 Socket类型为流套接字(streamsocket)和数据报套接字(datagramsocket)。流套接字将TCP作为其端对端协议,提供了一个可信赖的字节流服务。数据报套接字使用UDP协议,提供数据打包发送服务 基于TCP协议的Socket 1)服务器端首先声明一个ServerSocket对象并且指定端口号,然后调用Serversocket的accept()方法接收客户端的数据。accept()方法在没有数据进行接收的处于堵塞状态。(Socketsocket=serversocket.accept()),一旦接收到数据,通过inputstream读取接收的数据。 2)客户端创建一个Socket对象,指定服务器端的ip地址和端口号(Socketsocket=newSocket(“172.168.10.108”,8080);),通过inputstream读取数据,获取服务器发出的数据(OutputStreamoutputstream=socket.getOutputStream()),最后将要发送的数据写入到outputstream即可进行TCP协议的socket数据传输。 基于UDP协议的数据传输 1)服务器端首先创建一个DatagramSocket对象,并且指点监听的端口。接下来创建一个空的DatagramSocket对象用于接收数据(bytedata[]=newbyte[1024;]DatagramSocketpacket=newDatagramSocket(data,data.length)),使用DatagramSocket的receive方法接收客户端发送的数据,receive()与serversocket的accepet()类似,在没有数据进行接收的处于堵塞状态。 2)客户端也创建个DatagramSocket对象,并且指点监听的端口。接下来创建一个InetAddress对象,这个对象类似与一个网络的发送地址(InetAddressserveraddress=InetAddress.getByName(“172.168.1.120”)).定义要发送的一个字符串,创建一个DatagramPacket对象,并制定要讲这个数据报包发送到网络的那个地址以及端口号,最后使用DatagramSocket的对象的send()发送数据。 32.Android系统架构 从上到下依次分为六层:应用框架层、进程通信层、系统服务层、Android运行时层、硬件抽象层、Linux内核层。而我们经常说的五层:应用层、FrameWork层、Libarary 层、Linux层。 33.广播分为哪几种,应用场景是什么? 普通广播:调用sendBroadcast()发送,最常用的广播。 有序广播:调用sendOrderedBroadcast(),发出去的广播会被广播接受者按照顺序接收,广播接收者按照Priority属性值从大-小排序,Priority属性相同者,动态注册的广播优先,广播接收者还可以选择对广播进行截断和修改。 34.广播的两种注册方式有什么区别? (1)静态注册:常驻系统,不受组件生命周期影响,即便应用退出,广播还是可以被接收,耗电、占内存。 (2)动态注册:非常驻,跟随组件的生命变化,组件结束,广播结束。在组件结束前,需要先移除广播,否则容易造成内存泄漏。 35.广播发送和接收的原理了解吗? (1)、继承BroadcastReceiver,重写onReceive()方法。 (2)、通过Binder机制向ActivityManagerService注册广播。 (3)、通过Binder机制向ActivityMangerService发送广播。 (4)、ActivityManagerService查找符合相应条件的广播(IntentFilter/Permission)的BroadcastReceiver,将广播发送到BroadcastReceiver所在的消息队列中。 (5)、BroadcastReceiver所在消息队列拿到此广播后,回调它的onReceive()方法。 36.描述一下View的绘制原理? View的绘制流程主要分为三步: (1)、onMeasure:测量视图的大小,从顶层父View到子View递归调用measure()方法,measure()调用onMeasure()方法,onMeasure()方法完成绘制工作。 (2)、onLayout:确定视图的位置,从顶层父View到子View递归调用layout()方法,父View将上一步measure()方法得到的子View的布局大小和布局参数,将子View放在合适的位置上。
(1)、BroadcastReceiver 是跨应用广播,利用Binder机制实现。 (2)、LocalBroadcastReceiver 是应用内广播,利用Handler实现,利用了IntentFilter的match功能,提供消息的发布与接收功能,实现应用内通信,效率比较高。 38.Activity的通信方式有哪些? 答:startActivityForResult、EventBus、LocalBroadcastReceiver 39.Android应用里有几种Context对象? Context是个抽象类,它的具体实现类是ContextImpl,ContextWrapper是个包装类,内部的成员变量mBase指向的也是个ContextImpl对象,ContextImpl完成了实际的功能,Activity、Service与Application都直接或者间接的继承ContextWrapper。
常见的产生内存泄漏的情况如下所示: ①持有静态的Context(Activity)引用; ②持有静态的View引用; ③内部类&匿名内部类实例无法释放(有延迟时间等等),而内部类又持有外部类的强引用,导致外部类无法释放,这种匿名内部类常见于监听器、Handler、Thread、TimerTask; ④资源使用完成后没有关闭,例如:BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap。 ⑤不正确的单例模式,比如单例持有Activity。 ⑥集合类内存泄漏,如果一个集合类是静态的(缓存HashMap),只有添加方法,没有对应的删除方法,会导致引用无法被释放,引发内存泄漏。 ⑦错误的覆写了finalize()方法,finalize()方法执行执行不确定,可能会导致引用无法被释放。 如何分析内存泄漏:查找内存泄漏可以使用Android Profiler工具或者利用LeakCanary工具。 40.遇到过哪些关于Fragment的问题,如何处理的? (1)、getActivity()空指针:这种情况一般发生在在异步任务里调用getActivity(),而Fragment已经onDetach(),此时就会有空指针,解决方案是在Fragment里使用一个全局变量mActivity,在onAttach()方法里赋值,这样可能会引起内存泄漏,但是异步任务没有停止的情况下本身就已经可能内存泄漏,相比直接crash,这种方式显得更妥当一些。 (2)、Fragment视图重叠:在类onCreate()的方法加载Fragment,并且没有判断saveInstanceState==null或if(findFragmentByTag(mFragmentTag) == null),导致重复加载了同一个Fragment导致重叠。(PS:replace情况下,如果没有加入回退栈,则不判断也不会造成重叠,但建议还是统一判断下)。 41、Android里的Intent传递的数据有大小限制吗,如何解决? Intent传递数据大小的限制大概在1M左右,超过这个限制就会静默崩溃。处理方式如下: ①.进程内:EventBus,文件缓存、磁盘缓存。 ②.进程间:通过ContentProvider进行款进程数据共享和传递。 42、Activity的通信方式有哪些? 答:startActivityForResult、EventBus、LocalBroadcastReceiver。 43.Android如何在不压缩的情况下加载高清大图? 使用BitmapRegionDecoder进行布局加载。 44.了解插件化和热修复吗? ①.插件化:插件化是体现在功能拆分方面的,它将某个功能独立提取出来,独立开发,独立测试,再插入到主应用中。依次来较少主应用的规模。 ②.热修复:热修复是体现在bug修复方面的,它实现的是不需要重新发版和重新安装,就可以去修复已知的bug。 45、如何做性能优化? ①.节制的使用Service,当启动一个Service时,系统总是倾向于保留这个Service依赖的进程,这样会造成系统资源的浪费,可以使用IntentService,执行完成任务后会自动停止。 ②.当界面不可见时释放内存,可以重写Activity的onTrimMemory()方法,然后监听TRIM_MEMORY_UI_HIDDEN这个级别,这个级别说明用户离开了页面,可以考虑释放内存和资源。 ③.避免在Bitmap浪费过多的内存,使用压缩过的图片,也可以使用Fresco等库来优化对Bitmap显示的管理。 ④.使用优化过的数据集合SparseArray代替HashMap,HashMap为每个键值都提供一个对象入口,使用SparseArray可以免去基本对象类型转换为引用数据类想的时间。 46、MVC、MVP与MVVM之间的对比分析? ①.MVC:PC时代就有的架构方案,在Android上也是最早的方案,Activity/Fragment这些上帝角色既承担了V的角色,也承担了C的角色,小项目开发起来十分顺手,大项目就会遇到 耦合过重,Activity/Fragment类过大等问题。 ②.MVP:为了解决MVC耦合过重的问题,MVP的核心思想就是提供一个Presenter将视图逻辑I和业务逻辑相分离,达到解耦的目的。 ③.MVVM:使用ViewModel代替Presenter,实现数据与View的双向绑定,这套框架最早使用的data-binding将数据绑定到xml里,这么做在大规模应用的时候是不行的,不过数据绑定是一个很有用的概念,后续Google又推出了ViewModel组件与LiveData组件。ViewModel组件规范了ViewModel所处的地位、生命周期、生产方式以及一个Activity下多个Fragment共享ViewModel数据的问题。LiveData组件则提供了在Java层面View订阅ViewModel数据源的实现方案。 47、 说一下四大组件。 四大组件指Activity、Service、BroadcastReceiver、ContentProvider,这四大组件都需要在AndroidManifest文件中注册才可以使用。 48、Android进程间通信方式
Activity,Service,Receiver 都支持在 Intent 中传递 Bundle 数据,而 Bundle 实现了 Parcelable 接口,可以在不同的进程间进行传输。在一个进程中启动了另一个进程的 Activity,Service 和 Receiver ,可以在 Bundle 中附加要传递的数据通过 Intent 发送出去。 二、使用文件共享 Windows 上,一个文件如果被加了排斥锁会导致其他线程无法对其进行访问,包括读和写;而 Android 系统基于 Linux ,使得其并发读取文件没有限制地进行,甚至允许两个线程同时对一个文件进行读写操作,尽管这样可能会出问题。可以在一个进程中序列化一个对象到文件系统中,在另一个进程中反序列化恢复这个对象(注意:并不是同一个对象,只是内容相同。)。 三、使用 Messenger Messenger 是一种轻量级的 IPC 方案,它的底层实现是 AIDL ,可以在不同进程中传递 Message 对象,它一次只处理一个请求,在服务端不需要考虑线程同步的问题,服务端不存在并发执行的情形。服务端进程:服务端创建一个 Service 来处理客户端请求,同时通过一个 Handler 对象来实例化一个 Messenger 对象,然后在 Service 的 onBind 中返回这个 Messenger 对象底层的 Binder 即可。 四、使用 AIDL Messenger 是以串行的方式处理客户端发来的消息,如果大量消息同时发送到服务端,服务端只能一个一个处理,所以大量并发请求就不适合用 Messenger ,而且 Messenger 只适合传递消息,不能跨进程调用服务端的方法。AIDL 可以解决并发和跨进程调用方法的问题,要知道 Messenger 本质上也是 AIDL ,只不过系统做了封装方便上层的调用而已。 五、使用 ContentProvider 用于不同应用间数据共享,和 Messenger 底层实现同样是 Binder 和 AIDL,系统做了封装,使用简单。 系统预置了许多 ContentProvider ,如通讯录、日程表,需要跨进程访问。 使用方法:继承 ContentProvider 类实现 6 个抽象方法,这六个方法均运行在 ContentProvider 进程中,除 onCreate 运行在主线程里,其他五个方法均由外界回调运行在 Binder 线程池中。 ContentProvider 的底层数据,可以是 SQLite 数据库,可以是文件,也可以是内存中的数据。 六、使用 Socket 49、TCP与UDP的区别与联系 区别: 一:TCP 是面向连接的协议UDP是面向无连接的协议,TCP 发送数据之前需要先连接,UDP发出请求后,即发送数据之前不需要先连接; 二:UDP 相对TCP来说是不可靠的,因为 UDP 在发送数据以后,没有采用超时重发,停止等待机制,拥塞控制; 三:TCP 面向流,UDP 面向报文 优缺点:TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。 缺点:慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。 UDP优缺点:优点:快,UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击…… 缺点:不可靠,不稳定 。因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。 三次握手与四次挥手 三次握手: 第一次握手:第一次连接时,客户端向服务器端发送SYN(syn=j),等待服务器端的确认,此时客户端进入SYN_SEND状态,SYN:同步序列号 第二次握手:服务器端收到客户端发来的SYN,必须向客户端发送ACK包(ack=j+1=k),同时自己必须发送一个SYN包,即syn+ack,此时进入SYN_REC状态 第三次握手:客户端收到服务器端发来的syn+ack包,向服务器发送ack包(ack=k+1),发送完毕,此时进入ESTABLISH状态,连接成功,完成第三次连接。 4次挥手 当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接的请求 A进入终止等待1(FIN-WAIT-1)状态;主机B收到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1 tcp处于半关闭状态(half-close)a收到b端的确认后,就进入终止等待2状态 由B 端再提出反方向的关闭请求,将FIN置1进入last-wait状态主机A对主机B的请求进行确认,将ACK置1,双方向的关闭结束.进入时间等待状态(time-wait)时间等待计数器设置的时间过了2msl以后,进入closed状态。 50、说说对 Application 的理解 作用:做初始化操作、提供上下文。另外 Application 是一个 Context ,它直接继承了 ContextWrapper ;这个 ContextWrapper 的成员变量 mBase 可以用来存放系统实现的 ContextImpl,这样我们在调用 Application 的 Context 方法时,都是通过静态代理的方式最终调用到 ContextImpl 的方法。我们调用 ContextWrapper 的 getBaseContext 方法就能拿到 ContextImpl 的实例 问:平常开发会把全局变量放在 Application ? 那应用在后台被回收,重新打开的时候值丢失怎么办? 答:不会,保存全局变量用静态变量,或单例可以把它们聚集在更合适的位置。 避免应用被回收数据丢失,可以页面传递参数时,通过 Intent 传递参数,这样被回收后打开重新从 Intent 取参还是有值的。数据量大的话也可以考虑数据持久化;另一个方法是通过 onSaveInstanceState 和 onRestoreInstanceState 分别在被回收时保存相应的数据以及在重新打开时恢复数据。 相比 Activity ,Application 的生命周期简直不要太简单。首先创建的时候会调用构造函数,然后系统准备好 ContextImpl 通过 attachBaseContext( Context ) 方法注入到 Application,接着调用我们最熟悉的 onCreate 方法。 51、Android 开发中常用到的设计模式有哪些? 设计模式总共是23种,常用的有下面几种 : 1 单例模式,application 就是单例 可以存储一些数据例如记录activity的启动数量 ; 2 观察者模式: button的onClickListener ,监听button的响应; 3 适配器模式 :例如recyclerView 的adapter ; 4 命令模式: 例如开源库eventBus ,把数据封装好 发送出去,然后接收等。 52、HTTP 与 HTTPS ?的区别 1、HTTPS ?协议需要到 CA (Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用。(以前的网易官网是http,而网易邮箱是 https 。) 2、HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。 3、HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。4、HTTP 的连接很简单,是无状态的。HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。(无状态的意思是其数据包的发送、传输和接收都是相互独立的。无连接的意思是指通信双方都不长久的维持对方的任何信息。) 53、Android--最新常用框架
54、?自定义View面试总结
?55、Android 上的 Kotlin 协程 ? ? 协程是一种并发设计模式,可以在 Android 平台上使用它来简化异步执行的代码, 特点:①.轻量:可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。 ②.内存泄漏更少:使用结构化并发机制在一个作用域内执行多项操作。 ③.内置取消支持:取消操作会自动在运行中的整个协程层次结构内传播。 ④.Jetpack 集成:许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可供您用于结构化并发。? 56、BroadcastReceiver与LocalBroadcastReceiver有什么区别? 1、BroadcastReceiver 是跨应用广播,利用Binder机制实现。 2、LocalBroadcastReceiver 是应用内广播,利用Handler实现,利用了IntentFilter的match功能,提供消息的发布与接收功能,实现应用内通信,效率比较高。 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 23:01:07- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |