Android面试题 - 01

一、简述Android的4大组件是哪些,它们的作用?

Android的四大基本组件包括Activity、Service、Content Provider和BroadcastReceiver。

  1. Activity:一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信,Intent的描述结构中有两个最重要的部分:动作和动作对应的数据。例如,要查看一个人的联系方式,你需要创建一个动作类型为VIEW的intent,以及一个表示这个人的URI。

  2. Service:Service用于在后台完成用户指定的操作。它可以在不需要用户交互的情况下执行长时间的操作,或者在后台处理网络请求等任务。Service分为两种:启动模式和绑定模式。

  3. Content Provider:Content Provider是Android中的数据管理组件,主要用于在不同应用程序之间共享数据。它提供了一种标准的方法来访问和操作数据,使得不同的应用程序可以访问和使用相同的数据。

  4. BroadcastReceiver:BroadcastReceiver是一种广播接收器组件,它可以接收系统或其他应用程序发送的广播消息,并对其进行处理。例如,当设备启动时,系统会发送一条广播消息,所有注册了接收该消息的应用程序都会收到这条消息并进行相应的处理。

这四个组件分别完成了UI(用户界面)、后台任务(区别于线程)、广播(天然的推模型,观察者模式)和进程间数据通信的任务。

二、详细请介绍下Android中常用的五种布局?

Android系统中常用的五种布局分别是:FrameLayout(框架布局)、LinearLayout(线性布局)、RelativeLayout(相对布局)、TableLayout(表格布局)和ConstraintLayout(约束布局)。

  1. FrameLayout(框架布局):这是最简单的布局类型,所有控件都会放在左上角,并且会重叠。因此这种布局一般只用于放置简单的元素。

  2. LinearLayout(线性布局):该布局按照垂直或水平方向排列其子元素。可以通过设置android:orientation属性为"vertical"实现垂直布局,设置为"horizontal"实现水平布局。

  3. RelativeLayout(相对布局):这是一种比较灵活的布局方式,允许子元素相对于其他元素(如父元素、兄弟元素等)定位。它提供了丰富的属性来控制子元素的位置和大小。

  4. TableLayout(表格布局):此布局按照行和列的方式组织子元素,类似于HTML中的表格。每个单元格可以包含一个控件或者一个其他的表格布局。

  5. ConstraintLayout(约束布局):这是一种相对较新的布局方式,允许开发者通过创建约束来确定子元素的位置和其他属性。相比于其他四种布局,ConstraintLayout提供了更加强大和灵活的布局解决方案,可以帮助开发者更有效地处理各种屏幕尺寸和设备。

三、简述Android ListView的优化方案?

  1. 在adapter中的getView方法中,应尽量减少逻辑处理,以提升执行效率。
  2. 利用垃圾回收器GC及时释放不再使用的对象,避免内存泄露。
  3. 加载图片时,建议使用异步加载的方式,以避免阻塞UI线程。
  4. 将ListView的scrollingCache和animateCache属性设置为false,能够减少内存消耗以及提高列表滚动的流畅性。
  5. 布局深度对性能有影响,因此减少item布局的深度有助于提升渲染性能。
  6. 采用ViewHolder模式,这可以缓存convertView,避免重复findViewById,从而提高列表滚动的流畅性。
  7. 还可以通过convertView + ViewHolder重写getView()方法,这是ListView使用的最优化方式。

四、Android跟Activity和Task 有关的 Intent启动方式有哪些?

  1. 显性Intent:明确指出要启动的Activity的名称。例如,通过调用startActivity()方法并传入一个包含Action为"android.intent.action.VIEW"和Data为网址的Intent对象来启动浏览器。

  2. 隐性Intent:不直接指定要启动的Activity,而是通过描述要执行的操作来间接启动相应的Activity。例如,当用户在屏幕上看到一个网址时,系统会识别该操作并将隐式Intent传递给浏览器应用以打开该网址。

  3. 通过PackageManager获取LaunchIntent:利用PackageManager类的getLaunchIntentForPackage()方法直接获取要启动的应用的Intent。这种方式适用于需要动态判断目标应用是否存在或已安装的情况。

  4. 设置Component启动:使用Intent类的setComponent()方法手动设置要启动的Activity组件,并通过resolveActivityInfo()或queryIntentActivities()方法来确保该组件有效。

  5. 隐式类别启动:配置Activity时,可以为其添加一些元数据标签,如category。这样,当用户进行某种操作时,系统可以根据这些标签来确定要启动的Activity。但需要注意,如果将category的值修改为android.intent.category.DEFAULT,那么这个应用将在桌面看不到图标,无法直接打开。

  6. 通过URL启动Activity:使用Intent机制,可以通过描述操作的意图(Intent)来启动其他应用中的Activity。例如,当用户点击一个网址时,系统会识别该操作并将隐式Intent传递给浏览器应用以打开该网址。

五、Android 如何启用Service,如何停用Service?

在Android中,Service是一种在后台执行长时间运行操作的组件。启用和停用Service的方式有多种。

首先,你需要定义一个Service。这可以通过在Android Studio中选择File→New→Service→Service来完成。在此过程中,你可以配置服务的名称,以及设置是否允许除了当前程序之外的其他程序访问这个服务,以及是否启用这个服务。

要启动Service,可以使用startService()方法或bindService()方法。其中,startService()方法用于启动一个独立的服务,即使调用者退出了,服务仍然运行。而bindService()方法则是调用者与服务建立连接,一旦调用者退出,服务也会停止。

另外,你还可以通过Intent来控制服务的启动与停止。例如,创建一个Intent对象,然后调用startService()或stopService()方法来启动或停止服务。

至于如何停止Service,你可以调用stopService()方法来停止服务。如果你使用的是startService()方法启动的服务,那么你需要在Activity中调用stopService()方法来停止服务。如果你使用的是bindService()方法启动的服务,那么你需要在Activity中先调用unbindService()方法,然后再调用stopService()方法来停止服务。

Android 8.0之后启动服务的方式:

在Android 8.0及以后的版本中,启动服务的方式有所改变。为了改进系统性能和电池寿命,Android 8.0限制了后台应用创建后台服务的能力。因此,应用需要使用Context.startForegroundService()方法来启动服务。

启动服务后的操作也有所变化。创建服务后,应用必须在5秒内调用该服务的startForeground()方法,显示一条可见通知,声明有服务正在运行。如果没有这样做,系统会停止服务并导致应用无响应(ANR)。此外,如果保活机制在服务运行期间再次启动了一次相同的服务,那么不会调用服务的onCreate方法,只会调用onStart方法。

关于通知渠道,如果应用支持多个账户,可以为每个账户创建一个通知渠道组,用于管理应用内的多个同名通知渠道。例如,一款社交网络应用可能为个人账户和企业账户提供支持,每个账户可能需要多个功能和名称相同的通知渠道。

总之,Android 8.0及以后的版本对Service的权限进行了收紧,需要在启动服务时实现服务的前台化,否则可能会遇到崩溃问题。

六、请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系?

在Android的单线程模型中,Message、Handler、Message Queue和Looper共同构成了一个消息传递与处理的核心机制。首先,Message可以理解为线程间交流的信息,例如处理数据后台线程需要更新UI时,可以通过发送Message内含一些数据给UI线程。Handler则扮演了主要处理者的角色,它负责Message的发送和内容的处理。

Message Queue(消息队列)是用来存放通过Handler发布的消息的数据结构,它通常附属于某一个创建它的线程。当Handler发布一条消息后,这条消息会被放入与此Handler关联的消息队列中等待处理。而Looper则是一个线程循环器,它在每个线程中只有一个实例。Looper的主要作用是从存放Message的MessageQueue中取出Message,并交由Handler进行Message的分发和处理。

为了实现上述流程,首先需要通过Handler获取当前线程中的looper对象。然后,looper会不断地从Message Queue中读取并移除Message,这些Message随后被交给Handler进行处理。这样,通过Handler、Message Queue和Looper的协同工作,可以实现在单一线程环境下高效地处理和分发消息。

七、如何对 Android 应用进行性能分析?

在Android应用的性能分析方面,Android Studio提供了强大的工具——Android Profiler。这是一个集成了多种性能分析工具的集合体,使开发者可以在Android Studio中进行开发和性能调优工作,无需再下载其他工具。

首先,你可以从开发模拟器或设备启动应用,然后在Android Studio中选择"View > Tool Windows > Profiler"来启动性能分析器。此外,为了获取准确、可重复、可操作的基准测试结果,你需要在尽可能接近生产环境的系统上进行测试,并抑制噪声来源。

性能优化的主要指标包括渲染问题(如过度绘制、布局冗杂)、内存问题(如内存浪费、内存泄漏)和功耗问题(如耗电)。在进行性能优化时,应坚持性能测试,使用各种性能工具进行测试及快速定位问题,使用低配置的设备以暴露问题,并在保证产品稳定、按时完成需求的前提下进行优化。

在处理Android应用的性能问题时,主要关注以下几个方面:

  1. 渲染问题:过度绘制和布局冗杂会降低渲染性能。为了优化布局和渲染性能,可以使用ConstraintLayout等更优化的布局方式,避免视图重叠和过多的布局层级。此外,还可以使用硬件加速和缓存技术来提升渲染性能。

  2. 内存问题:内存泄漏和内存占用量过多可能会导致应用卡顿或崩溃。减少内存泄漏和内存占用量可以有效降低这种风险。例如,可以使用异步任务和多线程技术将耗时操作移至后台线程,避免在主线程中进行耗时操作。

  3. 功耗问题:如耗电过高会影响设备的续航时间。应尽量减少IO操作和网络请求,使用缓存技术和尽可能少的网络请求可以减少IO操作和网络请求的次数,从而降低功耗。

  4. 性能优化工具的使用:Android Studio提供了一套完整的性能优化工具,可以帮助开发者识别并定位应用中的性能问题,并提供相应的解决方案。

  5. 动画和过渡效果的使用:虽然动画和过渡效果可以增加应用的交互性和趣味性,但过多的动画和过渡效果可能会导致应用卡顿,因此需要根据实际需求进行适度使用。

  6. 定期进行应用优化:只有持续不断地进行应用优化,才能保证应用的性能不断提升,减少卡顿、崩溃等问题的出现。

八、简述Android什么情况下会导致内存泄露?

在Android开发中,内存泄露是一个常见的问题。内存泄露是指程序在向系统申请分配内存空间后(例如使用new操作符),在使用完毕后未释放,从而导致这部分内存无法再次被使用。这可能会导致应用性能下降,甚至导致应用崩溃。

内存泄露的原因有很多,以下是一些常见的原因:

  1. 长生命周期的对象持有短生命周期对象的引用,导致短生命周期对象无法被回收。
  2. 静态变量持有Context引用,导致Context无法被回收。
  3. Handler引用了Activity,导致Activity无法被回收。
  4. 使用了匿名类或者内部类并且引用了外部类的实例,导致外部类的实例无法被回收。

为了避免内存泄露,开发者可以采取以下措施:

  1. 及时释放对象:当对象不再使用时,应该及时将其设置为null,以便垃圾回收器可以回收它。
  2. 使用弱引用:弱引用可以让垃圾回收器更快地回收对象。
  3. 避免使用静态变量、匿名类和内部类:这些都会阻止垃圾回收器回收对象。
  4. 正确处理Handler:在Activity中使用Handler时,应该使用静态内部类+弱引用的方式来处理。

九、简述Android篇-界面尺寸?

在Android界面设计中,考虑屏幕尺寸是非常重要的一个环节。屏幕尺寸通常分为四个广义的大小:小,正常,大,特大。最常见的手机屏幕分辨率是360x640。并且,Android的字号单位是SP,720×1280常见的字体大小有:24px、26px、28px、30px、32px、34px,36px等等。图标的设计规范中,方形的高度和宽度都为152dp,圆形的直径为176dp,垂直长方形的高度为176dp,宽度为128dp,水平长方形的高度为128dp,宽度为176dp。快捷图标的实际面积高度和宽度都为44dp。

根据安卓规范,导航栏、工具栏等的尺寸没有明确的规定。一种常见的布局规范是状态栏高度为50px, 导航栏、操作栏高度为96px(对应48dp x 2),主菜单栏高度也为96px,内容区域高度为1038px(1280-50-96*2=1038)。另外,应用图标的整体大小推荐为48 x 48 dp。以上这些规范可以帮助设计师创建出更加友好的用户界面,提升用户体验。

十、移动设计中与字号有关的基本概念(重要概念) ?

移动设计中与字号有关的基本概念有很多,以下是一些重要的:

  • 像素(px):Pixels即像素,是基本原色素及其灰度的基本编码。在移动设备上,像素是显示的最小单位。
  • DPI(dots per inch):DPI是印刷上的记量单位,意思是每个英寸上,所能印刷的网点数。在移动设备上,DPI是屏幕的分辨率,表示每英寸所拥有的像素数,即像素密度。
  • PPI(pixels per inch):PPI是数字影像的解析度,意思是每英寸所拥有的像素数,即像素密度。在移动设备上,PPI越高,屏幕显示效果越清晰。
  • 字号:字号是指字体的大小。在移动设备上,由于空间有限且环境光通常比较微弱,所以在选择字体和字号时要格外注意。文字大小只是一个范围,这要根据设计的视觉效果来决定。在APP设计中,一般涉及4种字号:32px、28px、24px和20px。字号要用偶数,都是4的倍数。

十一、简述Android ContentProvider是如何实现数据共享的 ?

ContentProvider是Android四大组件之一,它主要用于在不同应用程序之间实现数据的共享和访问。为实现这一目标,ContentProvider将数据进行封装,并通过ContentResolver接口向其他应用提供这些数据。

每个使用ContentProvider的应用程序需要通过创建一个ContentResolver对象来操作指定的数据。具体来说,当一个应用程序需要获取其他应用程序的数据时,它会发送一个请求,该请求会由ContentResolver对象进行处理。然后,ContentResolver会查询ContentProvider以获取相应的数据,最后将数据返回给请求的应用程序。

此外,只有当需要在多个应用之间共享数据时,才需要使用ContentProvider。例如,一个联系人应用可能需要访问电话应用中的联系人信息,这时就可以使用ContentProvider来实现这两个应用之间的数据共享。

十二、阐述Android中Service和Thread的区别?

在Android中,Thread和Service都扮演着重要的角色,但它们之间存在着显著的区别。Thread是程序执行的最小单元,它被视为分配CPU的基本单位,并且可以用于执行异步操作。另一方面,Service是Android的一种机制,当其运行的时候,如果它是本地服务(Local Service),那么对应的服务将运行在主进程的主线程上。如果是远程服务(Remote Service),那么对应的服务将在独立进程的主线程上运行。

特别需要注意的是,Thread的运行是独立的,也就是说,即使一个Activity被finish之后,如果没有主动停止Thread或者Thread里的run方法没有执行完毕,Thread也会继续执行。然而对于Service来说,它的生命周期是由系统管理的,通常在不需要时由系统回收。

十三、阐述Android的IPC (进程间通信) 机制?

在Android中,进程间通信(IPC)是一种关键的机制,它使得不同的进程能够进行数据的交换和通信。主要的IPC方式有Binder、AIDL、Messenger、ContentProvider以及Socket等。

其中,Binder是Android中最常使用的进程间通信方式之一,它不仅支持跨进程通信,还能支持跨语言的通信。Binder机制是基于C/S架构实现的,客户端通过Binder向服务端发起远程调用请求,服务端在接收到请求后进行处理并返回结果。

另一种常见的IPC方式是AIDL,它是一种基于接口的描述语言,用于定义客户端和服务端之间的交互接口。Messenger则是一种轻量级的IPC方式,它基于Handler实现,通常用于在同一个进程中的不同组件之间传递消息。

ContentProvider是Android四大组件之一,主要用于在不同应用程序之间实现数据的共享和访问。最后,Socket也是一种常用的IPC方式,它提供了基于网络的进程间通信能力。

此外,为了实现进程间的数据交换,Android还提供了序列化与反序列化的方法。序列化是将数据转换为字节流的过程,而反序列化则是将字节流恢复为数据的过程。这两种技术对于实现进程间的数据交换至关重要。

十四、如何理解Activity,View,Window三者之间的关系?

Activity,View,Window三者在Android开发中扮演着重要的角色。理解这三者之间的关系有助于我们更好地理解Android的运行机制。

首先,Activity是四大组件之一,它提供一个界面让用户进行点击和各种滑动操作。具体来说,Activity就像工匠,而XML配置则像窗花图纸。开发人员可以通过Activity来管理应用程序的生命周期和状态。

其次,View代表用户界面组件的基本构建块,UI组件。每一个UI元素都是一个View对象。换句话说,如果把应用程序比作一座房子,那么View就是构成这座房子的每一个砖块。

最后,Window是顶级窗口外观和行为策略的抽象基类,唯一实现是PhoneWindow类。它是View的容器,并且负责将View显示出来。每个Activity都包含一个Window,这个Window通常是由PhoneWindow实现的。

从表面上看,Activity的参与度比较低,大部分View的添加操作都被封装到Window中进行实现。Activity更像是一个提供给开发人员的管理类,通过它能更简单地实现Window和View的操作逻辑。

总的来说,Activity、View、Window三者相互关联,共同构成了Android的用户界面。Activity作为管理者,负责处理用户的操作请求;View则是用户界面的基础构建块;而Window则负责管理View的显示。

十五、阐述ANR 是什么? 怎样避免和解决 ANR?

ANR(Application Not Responding)是指应用程序无响应,通常是由于主线程被阻塞或处理时间过长导致的。当用户与应用程序交互时,如果应用程序长时间无法响应用户的输入,系统就会弹出ANR对话框,提示用户应用程序无响应。

为了避免和解决ANR问题,可以采取以下措施:

  1. 避免在主线程中执行耗时操作。将耗时操作放在子线程中执行,以避免阻塞主线程。

  2. 使用异步任务来执行耗时操作。可以使用AsyncTask、Handler、Thread等机制来实现异步操作。

  3. 优化布局和视图操作。减少布局嵌套层次和不必要的视图操作,以减少绘制时间。

  4. 合理使用广播接收器。避免在广播接收器中执行耗时操作,以免影响应用程序的响应速度。

  5. 使用StrictMode工具检测和防止ANR问题。StrictMode可以帮助开发人员检测和防止ANR问题,并提供有关应用程序性能的详细信息。

  6. 对于一些需要长时间运行的操作,可以考虑使用Service来实现后台运行。Service可以在后台执行长时间运行的操作,而不会阻塞主线程。

你可能感兴趣的:(Android面试题,android)