安卓面试基础(如会必过)_安卓系统原理面试-程序员宅基地

技术标签: 安卓  面试  基础  安卓基础  

Activity
1、 什么是Activity?
Activity是四大组件之一,他给用户的感受就是一个用户交互界面。一个Activity就是一个可见的界面。
他的特点是:1、可见 2、可交互
他之所以可交互,是因为他同时实现了Window.Callback和KeyEvent.Callback, 可以处理与窗体用户交互的事件和按键事件.这两个特点,是他和service最大的区别。
一个Activity在创建于销毁的过程中,会经历一些生命周期。
如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity.
在这里插入图片描述
2、Activity的生命周期

a、简述一下生命周期
生命周期描述的是一个类 从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法…
在这个过程中 会针对不同的生命阶段会调用不同的方法

Activity从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:onCreate onDestroy onStop onStart onResume onPause onRestart
当从A界面跳转到B界面的时候,A界面会调用onPause onStop B界面会调用onCreate、onStart、onResume等。在回到A界面的时候,A界面会调用onReStart、onStart、onResume
如果B界面是透明的activity,那么进行跳转的时候,A界面是不会调用onStop的,只会调用onPause 再回到A界面的时候,A界面会调用onResume
b、A界面跳转到B界面的时候,再回到A界面,A界面必然会执行的是哪几个方法。
两个Activity之间的跳转必然会执行的是onResume方法,这个具体的应用场景是每次回到该界面的时候,如果界面需要展示最新的数据,那么可以在该方法中实现。
多媒体播放视频的时候, 来了一个电话. onStop() 视频, 视频声音设置为0 , 记录视频播放的位置 mediaplayer.pause();
onResume() 根据保存的状态恢复现场. mediaplayer.start();
c、在屏幕旋转的时候,activity的生命周期是怎样的?
横竖屏进行切换的时候,默认的情况下,Activity会重新的调用onCreate方法。因为竖屏的activity销毁了,再生成一个横屏的activity 。
在AndroidManifest.xml可以进行配置,我们可以通过android:configChanges进行配置。android:configChanges=“orientation|keyboardHidden|screenSize” 配置了之后,横竖屏切换的时候,就不会调用onCreate了,而是调用onConfigurationChanged的方法。
在一些特殊应用中,屏幕的方向是写死的,比如游戏。在AndroidManifest中配置android:screenOrientation=“landscape"就可以了。
d、讲一讲你对activity的理解
e、设置activity的样式为窗口的样式,对生命周期有什么影响?
设置窗口样式,需要在配置文件中增加theme的属性
android:theme=”@android:style/Theme.Dialog"
activity设置为窗口样式的时候,当启动这个activity的时候,之前那个activity是不会走onStop方法的,而是只走到了onPause方法。

3、你后台的Activity被系统 回收如何在被系统回收之前保存当前状态?
在这里插入图片描述
除了在栈顶的activity,其他的activity在系统资源匮乏的时候,都有可能会被系统回收。这时候系统会调用onSaveInstanceState方法,我们可以往bundle里面存放数据。在activity onCreate里面我们先判断一下bundle是不是为空,如果不为空,就代表这个activity之前被系统回收掉,应该恢复一下现场。我们就可以从bundle里面取值。

4、对android主线程的运用和理解
a、主线程也就是UI线程,四大组件都是运行在主线程中的。
b、主线程中有一个消息队列,主要处理窗口绘制、按钮响应等消息。
c、如果在主线程里面做耗时的操作,会导致窗口绘制等消息得不到及时的处理,从而有可能会报出anr的错误。

在这里插入图片描述

5、如何避免anr?如何解决anr?
anr是android not response 安卓无响应,这里指的是主线程无响应。将耗时的操作放在子线程中进行可以有效的避免anr。如果出现了anr,我们可以通过log信息以及traces.txt文件进行分析。
traces.txt里面记录的是stack信息。

6、Activity的数据传递
a、基础的数据类型通过Bundle进行传递
b、传递对象的话,需要该对象实现Serializable或者Parcelable接口,放到bundle进行传递。
c、在Application中进行存储。其他界面要用的话,就直接来application取就可以了。一个应用程序application的实例只有一个。
d、大对象,比如bitmap,我们一般都不传递这个对象,我们传递的一般都是路径就可以了。然后通过URI.fromFile()来传递URI

  1. 如何退出Activity?
    退出activity我们只需要调用finish就可以了。退出activity 会执行 onDestroy()方法。
    如何一次性的退出多个Activity?
    a、抛异常强制退出:
    该方法通过抛异常,使程序Force Close。
    验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。
    b、记录打开的Activity:
    每打开一个Activity,就记录下来。放到application里面去存起来。在需要退出时,关闭每一个Activity即可。
    8、Activity的启动模式
    首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an “application.” It’s a group of related activities, arranged in a stack. A task is a stack of activities, not a class or an element in the manifest file. 这意思就是说Task实际上是一个Activity栈,通常用户感受的一个Application就是一个Task。从这个定义来看,Task跟Service或者其他Components是没有任何联系的,它只是针对Activity而言的。
    Activity有不同的启动模式, 可以影响到task的分配
    Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的Activity,才会有机会与用户进行交互。而当栈顶的Activity完成使命退出的时候,Task会将其退栈,并让下一个将跑到栈顶的Activity来于用户面对面,直至栈中再无更多Activity,Task结束。

standard", “singleTop”, “singleTask”, “singleInstance”。

standard模式, 是默认的也是标准的Task模式,在没有其他因素的影响下,使用此模式的Activity,会构造一个Activity的实例,加入到调用者的Task栈中去,对于使用频度一般开销一般什么都一般的Activity而言,standard模式无疑是最合适的,因为它逻辑简单条理清晰,所以是默认的选择。

而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来处理新的Intent(当然,也可以无视…)。这个模式,降低了位于栈顶时的一些重复开销

singleTask,和singleInstance,则都采取的另辟Task的蹊径。
标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。singleTask,很象概念中的单件模式,所有的修改都是基于一个实例,这通常用在构造成本很大,但切换成本较小的Activity中。最典型的例子,还是浏览器应用的主Activity(名为Browser…),它是展示当前tab,当前页面内容的窗口。它的构造成本大,但页面的切换还是较快的,于singleTask相配,还是挺天作之合的。

singleInstance显得更为极端一些。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity, 这个栈,只有一个activity

activity是运行在任务栈中的,一个activity启动另外一个activity,默认的情况下,新的activity也是运行在同一个任务栈里的。service和广播接收者也是没有任务栈的,所以,他们启动activity的时候,给intent设置flag, Intent的flag添加FLAG_ACTIVITY_NEW_TASK

Service
9、什么是Service以及描述下它的生命周期?
service是一个服务,它是不可见的,同样也是运行在主线程中。它的生命周期的方法有onCreate、onStart、onDestory,它还有一些activity的没有的生命周期方法,onBind和onUnbind
不同的启动方式,生命周期调用的也不同。
启动Service的方式有两种,一种是startService和bindService
a、通过startService
Service会经历 onCreate 到onStart,然后处于运行状态,stopService的时候调用onDestroy方法。
这种方式,activity和service是相互独立的。如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行
b、通过bindService
Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑定在一起。调用者退出了,Service就会调用onUnbind->onDestroyed方法。
这种方式,activity就和service相互捆绑在一起了。所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService方法来停止服务,这时候Service就会调用onUnbind->onDestroyed方法。

Activity为什么要绑定Service?是因为有些情况下,我们需要调用service里面的方法。startService的方式我们是调用不到Service里面的方法的。

如何让服务长期在后台运行,而activity又可以调用到服务里面的方法?
先startService 然后bindService进行绑定,这个时候就可以调用服务里面的方法了。调用完了之后,你就unBindService,这时候退出界面的时候,服务是一直在后台跑的。

默认情况下,服务是运行在主线程中的,在特殊的情况下,我们可以通过AndroidManifest文件中进行配置android:process="" 这种情况下,服务就在另外一个进程的主线程中。
10. 什么是IntentService?有何优点?
普通的service ,默认运行在ui main 主线程(ID默认是1)
Sdk给我们提供的方便的,带有异步处理的service类,
OnHandleIntent() 处理耗时的操作
11、什么时候需要使用到Service
因为service是具有较高优先级。Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。所以我们需要使用到服务Service
在某些情况下,比如服务以及onStart了,那么此时服务的优先级会稍微的低一些,这时候还是有可能被系统回收,可以通过startForground提高服务的优先级,这个时候,系统就不会回收这个服务了。
因为服务的优先级较高,所以在一些场景中比较适合使用服务,比如:
a、拥有长连接QQ
b、定时轮询、耗时操作
c、服务里面注册广播接收者。有些广播接收者只能通过代码注册,比如屏幕锁屏、屏幕解锁

广播接收者
12、简单描述一下广播接收者
广播接收者有两类,一种是系统本身就有的,一种是我们自己写的广播接收者。
广播接收者注册的方式也有两种,一种是动态注册,一种是静态注册。
只能用代码注册的广播,这种广播产生的频率是比较高的。比如电量变化的广播,屏幕解锁的广播。电量变化的广播。
广播接收者在注册的时候可以指定优先级,用于提高接收到广播的顺序。
广播一般是用于跨进程通讯的时候。
13、如何发广播
广播分为两种,一种是有序广播,一种是无序广播
有序广播是按顺序被接收的,是可以被拦截和修改里面的数据的。而无序广播则没有接收顺序,也无法修改广播里面的数据。
拦截广播可以使用abortBroadcast()将有序广播给abort掉
数据存储
14、ContentProvider的使用
把自己的数据通过uri的形式共享出去,这个uri是事先约定好的。
android 系统下 不同程序 数据默认是不能共享访问,通过ContentProvider可以将自己应用的数据提供给别的应用。
我们在写内容提供者的时候,需要写一个类继承ContentProvider,然后实现里面的增删改查方法
query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[])
delete(Uri, String, String[])
15、Android提供的数据存储方式有哪些(内存:效率快,文件中存储临时文件,开关等)
a、SharedPreferences、sd卡的文件
b、数据库sqlite(大量的数据存储)
c、数据存储到服务器上(http协议访问后台接口传输上去)

View
16、View的绘制流程,自定义控件的使用
View如何绘制到手机上,一般用onDraw(Canvas canvas)在画布上(不过在此之前要 onMeasure和onLayout)
onMeasure->onLayout->onDraw
onMeasure:计算宽和高,调用setMeasuredDimension
onLayout: 计算位置
onDraw: 画在画布上
自定义控件需要在onMeasure、onLayout、onDraw中的某些方法进行修改,这样才能保证自定义的控件能够在正确的位置正确的大小被正确的画出来。
自定义属性的使用?
在values的目录下需要建立一个文件,叫做attrs.xml 这个文件是定义属性规则的。一个属性的名字、取值类型、取值范围
在布局文件中需要加入命名空间,最后在自定义控件中获取这些值。
17、View的事件传递
事件分发dispatchTouchEvent
事件拦截onInterceptTouchEvent{如在桌面中滑动时,返回true时父拦截事件,点击事件 时,点击时返回false时,不拦截事件传递给子控件就响应了点击事件}
事件响应onTouchEvent
事件传递的方向是由父类到子类,事件响应的方向是从子类到父类。

18、ListView的优化
listView是由item充填,每个item都是有getView返回的(如果有千百个item,就会有千百个inflate会很占内存的所以系统就给提供了convertView)
重用了convertView,减少了inflate的次数
使用ViewHolder,减少findViewById的次数,很大程度上的减少了内存的消耗。
在这里插入图片描述
19、布局的优化(就是提高UI的流程度)
优化布局层次。不要不断的嵌套LinearLayout ,多使用RelativeLayout 尽可能的减少布局的层次。如:左边是图片,右边是文字的,可以就使用一个TextView来完成。drawableLeft。
ViewStub(延时加载的view,当使用时才加载)、include(提取一个basePager.xml),listview子元素高度的计算

其他
20、线程间的通讯
Handler是用来进行线程间的通信。
Looper是用来管理所属线程的消息队列MessageQueue的
每一个线程都需要有一个looper,每一个looper管理一个MessageQueue
Handler.sendMessage的意思是将某一个message放到MessageQueue中去,looper是个死循环,不断的读MessageQueue中的新消息。
要让looper的死循环运行起来,得调用Looper.loop()方法。
我们通常都会在子线程中,发一个消息到主线程中的messagequeue中去。
21、内存泄露的查找
内存泄漏本身不会产生什么危害,真正有危害的是内存泄漏的堆积。Android应用内存泄漏的的原因有以下几个:
0、register之后没有unregister
1查询数据库后没有关闭游标cursor file没有close
2 构造Adapter时,没有使用 convertView 重用
3 Bitmap对象不在使用时调用recycle()释放内存
4 对象被生命周期长的对象引用,如activity被静态集合引用导致activity不能释放
内存泄漏如何解决:
生成hprof文件可以通过adt的工具也可以通过代码生成。debug的dump方法
22、如何处理大图片,图片缓存

  1. 有效加载大图片,合理设置BitmapFactory.Options的inSampleSize值,减少图片内存占用;
  2. 仅请求图片的大小,inJustDecodeBounds = true,仅请求图片大小,而不会加载图片到内存;
  3. 缓存图片,内存缓存LruCache
    23、描述一下AIDL的原理
    AIDL的全称是android interface definition language 接口定义语言。它所做的事情就是跨进程范围另外一个服务里面的方法的。跨进程范围另外一个服务里面的方法。
    在手机卫士中挂断电话用到过AIDL。我们要获取手机系统的电话服务,用到了aidl 它其实工作的原理就是绑定到一个远程的服务上。然后这个远程服务会返回回来一个代理对象。
    这个代理对象里面的方法,就是我们定义的aidl
    aidl的写法也非常简单,主要分两种。调用系统服务的话,直接找到那个服务的aidl拷贝到我们的项目中就可以了。另外一种是我们自己写aidl,主要注意的一点是aidl是没有访问修饰符的。因为aidl本身就是公开的,就是为了给别人调用的,不需要私有的private方法。
    其实呢,在实际的开发过程中,比较少会写这个aidl,特别是写app,几乎用不到 做rom的时候,倒会遇到。那也比较少。但是你得懂它相关的知识是吧。
    在面试的时候,这个也是经常被用的。所以大家要熟悉这个问题的回答方法。
    我以前在中兴面试别人的时候,只要他能回答上几个关键点,我就会让他过我这关噢。
    1、跨进程 2、aidl在服务端和客户端都需要有一份 3、通过绑定的方式获取远程服务对象的代理IBinder,就可以调用相关的方法。
    跨进程:可用Aidl,广播,隐式意图,或者自己写一个跨进程的一个进程将数据定时存入sd 卡中,然后另一个进程定时从sd卡里面取出数据。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wdx_1136346879/article/details/86132341

智能推荐

while循环&CPU占用率高问题深入分析与解决方案_main函数使用while(1)循环cpu占用99-程序员宅基地

文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。​​​​​​while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99

【无标题】jetbrains idea shift f6不生效_idea shift +f6快捷键不生效-程序员宅基地

文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效

node.js学习笔记之Node中的核心模块_node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是-程序员宅基地

文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是

数学建模【SPSS 下载-安装、方差分析与回归分析的SPSS实现(软件概述、方差分析、回归分析)】_化工数学模型数据回归软件-程序员宅基地

文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件

利用hutool实现邮件发送功能_hutool发送邮件-程序员宅基地

文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件

docker安装elasticsearch,elasticsearch-head,kibana,ik分词器_docker安装kibana连接elasticsearch并且elasticsearch有密码-程序员宅基地

文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码

随便推点

Python 攻克移动开发失败!_beeware-程序员宅基地

文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware

Swift4.0_Timer 的基本使用_swift timer 暂停-程序员宅基地

文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停

元素三大等待-程序员宅基地

文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待

Java软件工程师职位分析_java岗位分析-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析

Java:Unreachable code的解决方法_java unreachable code-程序员宅基地

文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code

标签data-*自定义属性值和根据data属性值查找对应标签_如何根据data-*属性获取对应的标签对象-程序员宅基地

文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象

推荐文章

热门文章

相关标签