目录
1、操作系统
2、计算机网络
3、C++
4、安卓
1.进程的常见状态?以及各种状态之间的转换条件?
就绪:进程已处于准备好运行的状态,即进程已分配到除CPU外的所有必要资源后,只要再获得CPU,便可立即执行。执行:进程已经获得CPU,程序正在执行状态。阻塞:正在执行的进程由于发生某事件(如I/O请求、申请缓冲区失败等)暂时无法继续执行的状态。
2.进程同步
进程同步的主要任务:是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。
3.进程的通信方式有哪些?
进程通信,是指进程之间的信息交换(信息量少则一个状态或数值,多者则是成千上万个字节)。因此,对于用信号量进行的进程间的互斥和同步,由于其所交换的信息量少而被归结为低级通信。
高级通信机制可归结为三大类: (1)共享存储器系统 (2)消息传递系统 (3)管道通信系统
管道:管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。
信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。
消息队列:是一个在系统内核中用来保存消 息的队列,它在系统内核中是以消息链表的形式出现的。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享内存:共享内存允许两个或多个进程访问同一个逻辑内存。
套接字:套接字也是一种进程间通信机制,与其它通信机制不同的是,它可用于不同机器间的进程通信。
5.进程与线程的区别和联系?
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
进程和线程的关系
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。 同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。(3)处理机分给线程,即真正在处理机上运行的是线程。(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
进程与线程的区别?
(1)进程有自己的独立地址空间,线程没有(2)进程是资源分配的最小单位,线程是CPU调度的最小单位
(3)进程和线程通信方式不同(4)进程上下文切换开销大,线程开销小(5)一个进程挂掉了不会影响其他进程,而线程挂掉了会影响其他线程(6)对进程进程操作一般开销都比较大,对线程开销就小了
为什么进程上下文切换比线程上下文切换代价高?
进程切换分两步:
线程可以分为两类:
用户级线程(user level thread):对于这类线程,有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在。用户级线程的好处是非常高效,不需要进入内核空间,但并发效率不高。
内核级线程(kernel level thread):对于这类线程,有关线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只能调用内核线程的接口。
6.非抢占式:直到进程完成或发生进程调度进程调度某事件而阻塞时,才把处理机分配给另一个进程。
抢占式:操作系统将正在运行的进程强行暂停,由调度程序将CPU分配给其他就绪进程的调度方式。
7.死锁定义:在两个或多个并发进程中,如果每个进程持有某种资源而又都等待别的进程释放它或它们现在保持着的资源,,称这一组进程产生了死锁。通俗地讲,就是两个或多个进程被无限期地阻塞、相互等待的一种状态。
产生死锁的必要条件:
互斥条件:资源不能被共享,只能由一个进程使用。请求与保持条件:已经得到资源的进程可以再次申请新的资源。
非抢占条件:已经分配的资源不能从相应的进程中被强制地剥夺。循环等待条件:
如何处理死锁问题:
忽略该问题。检测死锁并且恢复。仔细地对资源进行动态分配.破除死锁四个必要条件之一
8.临界资源
在操作系统中,进程是占有资源的最小单位。但对于某些资源来说,其在同一时间只能被一个进程所占用。这些一次只能被一个进程所占用的资源就是所谓的临界资源。必须是互斥进行。也就是当临界资源被占用时,另一个申请临界资源的进程会被阻塞,直到其所申请的临界资源被释放。而进程内访问临界资源的代码被成为临界区。
9.一个程序从开始运行到结束的完整过程(四个过程)1、预处理:2、编译_>汇编语言:3、汇编:4、链接:
10.内存池、进程池、线程池。(c++程序员必须掌握)
首先介绍一个概念“池化技术 ”。池化技术就是:提前保存大量的资源,以备不时之需以及重复使用。
由于在实际应用当做,分配内存、创建进程、线程都会设计到一些系统调用,系统调用需要导致程序从用户态切换到内核态,是非常耗时的操作。因此,当程序中需要频繁的进行内存申请释放,进程、线程创建销毁等操作时,通常会使用内存池、进程池、线程池技术来提升程序的性能。
线程池:类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当需要一个开辟一个线程去做具体的工作时,就会唤醒线程池中的某一个睡眠线程,让它去做具体工作,当工作完成后,线程又处于睡眠状态,而不是将线程销毁。 进程池与线程池同理。
内存池:内存池是指程序预先从操作系统申请一块足够大内存,此后,当程序中需要申请内存的时候,是直接从内存池中获取;当程序释放内存的时候,返回内存池。
11.动态链接库与静态链接库的区别: 静态库在编译的时候,就将库函数装在到程序中去了,而动态库函数必须在运行的时候才被装载,使用静态库速度快
12.虚拟内存?优缺点?定义:具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充得一种存储器系统。其逻辑容量由内存之和和外存之和决定。虚拟内存的实现有以下两种方式:请求分页存储管理。请求分段存储管理。
13.页面置换算法
操作系统将内存按照页面进行管理,在需要的时候才把进程相应的部分调入内存。当产生缺页中断时,需要选择一个页面写入。置换算法,就是要选出最合适的一个页面,使得置换的效率最高。
一、最优页面置换算法(这样的算法不可能实现,因为不确定一个页面在何时会被用到。)二、先进先出页面置换算法:这种算法的思想和队列是一样的,该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予淘汰。三、最近最少使用页面置换算法LRU(Least Recently Used)根据页面调入内存后的使用情况做出决策。LRU置换算法是选择最近最久未使用的页面进行淘汰。
14.中断:在计算机执行程序的过程中,由于出现了某些特殊事情,使得CPU暂停对程序的执行,转而去执行处理这一事件的程序。等这些特殊事情处理完之后再回去执行之前的程序。中断一般分为三类:
由计算机硬件异常或故障引起的中断,称为内部异常中断;由程序中执行了引起中断的指令而造成的中断,称为软中断;由外部设备请求引起的中断,称为外部中断。简单来说,对中断的理解就是对一些特殊事情的处理。
当中断发生的时候,系统需要去对中断进行处理,对这些中断的处理是由操作系统内核中的特定函数进行的,这些处理中断的特定的函数就是我们所说的中断处理程序了。
典型的中断优先级如下所示:
机器错误 > 时钟 > 磁盘 > 网络设备 > 终端 > 软件中断
用户态切换到内核态的方式如下:系统调用:异常:外围设备的中断:
用户态和核心态(内核态)之间的区别是什么呢? 权限不一样。
用户态的进程能存取它们自己的指令和数据,但不能存取内核指令和数据(或其他进程的指令和数据)。
15.C++多线程,互斥,同步
所谓同步,是指在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。所谓互斥,是指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。
多线程同步和互斥有几种实现方法
用户模式下的方法有:原子操作,临界区。内核模式下的方法有:事件,信号量,互斥量。
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2、互斥量:为协调共同对一个共享资源的单独访问而设计的。
3、信号量:为控制一个具有有限数量用户资源而设计。
4、事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。
19.什么是线程安全
如果多线程的程序运行结果是可预期的,而且与单线程的程序运行结果一样,那么说明是“线程安全”的。
20.同步与异步
同步:同步的定义:是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么,这个进程将会一直等待下去,直到收到返回信息才继续执行下去。
特点:(1是阻塞模式;(2是按顺序执行,执行完一个再执行下一个,需要等待,协调运行;
异步:是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
特点:(1非阻塞模式,无需等待;(2异步是彼此独立,在等待某事件的过程中,继续做自己的事,不需要等待这一事件完成后再工作。线程是异步实现的一个方式。
23.Semaphore(信号量) Vs Mutex(互斥锁)
对于semaphore而言,在初始化变量的时候可以控制允许多少个线程/进程同时访问一个临界区,其他的线程/进程会被堵塞,直到有人解锁。Mutex相当于只允许一个线程/进程访问的semaphore。
25.线程安全
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
线程安全问题都是由全局变量及静态变量引起的。
26、时间局部性(temporal locality) 时间局部性指的是:被引用过一次的存储器位置在未来会被多次引用(通常在循环中)。 空间局部性(spatial locality) 如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。
1、TCP和UDP是OSI模型中的运输层中的协议。TCP提供可靠的通信传输,而UDP则常被用于让广播和细节控制交给应用的通信传输。
两者的区别大致如下:TCP面向连接,UDP面向非连接即发送数据前不需要建立链接(2)提供可靠的服务(数据传输),UDP无法保证(3)TCP面向字节流,UDP面向报文(4)TCP数据传输慢,UDP数据传输快
2、TCP对应的协议:
FTP:使用21端口。Telnet: 23端口, SMTP: 25号端口。POP3:HTTP:80 SSH:22
UDP对应的协议:DNS: 53 SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的;TFTP
3、TCP中的流量控制和拥塞控制
流量控制:因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度.主要针对的是端到端传输中控制流量大小并保证传输可靠性。流量控制往往是指点对点通信量的控制,所要做的是抑制发送端发送数据的速率。
拥塞控制主要是一个全局性过程,涉及到所有主机,路由器,以及与降低网络传输性能有关的所有因素。防止过多的数据注入到网络中。如果有发生丢包则通过拥塞控制减小窗口,确定出合适的拥塞窗口。
4、三、四:核心思想:让双方都证实对方能发收。知道对方能收是因为收到对方的因为收到信息之后发的回应(ACK)。
TCP客户端最后还要发送一次确认呢?主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误.
为什么客户端最后还要等待2MSL?:第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失。第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。
5、交换机/路由器:交换机工作于数据链路层。交换机内部的CPU会在每个端口成功连接时,通过ARP协议学习它的MAC地址,保存成一张ARP表。路由器(Router)是一种计算机网络设备,提供了路由与转发两种重要机制。
6、200 (成功) 服务器已成功处理了请求。 304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。403 (禁止) 服务器拒绝请求。404 (未找到) 服务器找不到请求的网页。
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
7、HTTP与HTTPS区别1、https协议需要到ca申请证书,一般需要一定费用。2、http是明文传输,https则是具有安全性的ssl加密传输协议。 3、http和https使用的端口也不一样,前者是80,后者是443。4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
8、cookie 和session 的区别:
存储位置不同:session在服务器端存储,比较安全,cookies在客户端存储,安全性稍弱
生命周期不同:session生命周期在指定的时间(如20分钟)到了之后会结束,不到指定的时间,也会随着浏览器进程的结束而结束。cookies默认情况下也随着浏览器进程结束而结束,但如果手动指定时间,则不受浏览器进程结束的影响。
9、TCP: 连接管理(三四)、确认应答机制(ACK机制)、超时重传机制、滑动窗口、 流量控制(Flow Control)、拥塞控制、校验和
1. C/C++内存有哪几种类型?
C中,内存分为5个区:堆(malloc)、栈(如局部变量、函数参数)、程序代码区(存放二进制代码)、全局/静态存储区(全局变量、static变量)和常量存储区(常量)。此外,C++中有自由存储区(new)一说。
全局变量、static变量会初始化为零,而堆和栈上的变量是随机的,不确定的。
2. 堆和栈的区别?
1).堆存放动态分配的对象——即那些在程序运行时分配的对象,比如局部变量,其生存期由程序控制;
2).栈用来保存定义在函数内的非static对象,仅在其定义的程序块运行时才存在;
3、static关键字的作用:
(1)函数体内static变量的作用范围为该函数体,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;(2)在模块内的static全局变量和函数可以被模块内的函数访问,但不能被模块外其它函数访问;(3)在类中的static成员变量属于整个类所拥有(4)在类中的static成员函数属于整个类所拥有
4、const关键字的作用:
(1)阻止一个变量被改变(2)声明常量指针和指针常量(3)const修饰形参,表明它是一个输入参数,在函数内部不能改变其值;(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为”左值”。
5、宏和内联(inline)函数的比较?
1). 首先宏是C中引入的一种预处理功能;
2). 内联(inline)函数是C++中引用的一个新的关键字;C++中推荐使用内联函数来替代宏代码片段;
3). 内联函数将函数体直接扩展到调用内联函数的地方,这样减少了参数压栈,跳转,返回等过程;
4). 由于内联发生在编译阶段,所以内联相较宏,是有参数检查和返回值检查的,因此使用起来更为安全;
5). 需要注意的是, inline会向编译期提出内联请求,但是是否内联由编译期决定
6).在某些情况下,即使没有显示的声明内联,比如定义在class内部的方法,编译器也可能将其作为内联函数。
7). 内联函数不能过于复杂,
6. C++中有了malloc / free , 为什么还需要 new / delete?
maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
7、虚函数在一个基类中声明一个函数为virtual类型,即virtual void Run();那么这个函数就是虚函数,
作用:实现多态,父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。
虚继承 是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类。
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界面必然会执行的是哪几个方法。
多媒体播放视频的时候, 来了一个电话. 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"就可以了。
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
如何退出Activity?
退出activity我们只需要调用finish就可以了。退出activity 会执行 onDestroy()方法。
如何一次性的退出多个Activity?
a、抛异常强制退出:
该方法通过抛异常,使程序Force Close。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。
b、记录打开的Activity:
每打开一个Activity,就记录下来。放到application里面去存起来。在需要退出时,关闭每一个Activity即可。
8、Activity的启动模式
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栈中去
而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来处理新的Intent(
singleTask的Activity,最多仅有一个实例存在,
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?有何优点?
1、Service中的程序仍然运行于主线程中,而在IntentService中的程序运行在我们的异步后台线程中。
2、在Service中当我的后台服务执行完毕之后需要在外部组件中调用stopService方法销毁服务,而IntentService并不需要,它会在工作执行完毕后自动销毁。
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在画布上(不过在此之前要 onMeasure和onLayout)
onMeasure->onLayout->onDraw
onMeasure:计算宽和高,调用setMeasuredDimension
onLayout: 计算位置
onDraw: 画在画布上
自定义控件需要在onMeasure、onLayout、onDraw中的某些方法进行修改,这样才能保证自定义的控件能够在正确的位置正确的大小被正确的画出来。
自定义属性的使用?
在values的目录下需要建立一个文件attrs.xm, 定义属性规则的。一个属性的名字、取值类型、取值范围
在布局文件中需要加入命名空间,最后在自定义控件中获取这些值。
17、View的事件传递
事件分发dispatchTouchEvent
事件拦截onInterceptTouchEvent{如在桌面中滑动时,返回true时父拦截事件,点击事件 时,点击时返回false时,不拦截事件传递给子控件就响应了点击事件}
事件响应onTouchEvent
事件传递的方向是由父类到子类,事件响应的方向是从子类到父类。
18、ListView的优化
listView是由item充填,每个item都是有getView返回的(如果有千百个item,就会有千百个inflate会很占内存的所以系统就给提供了convertView)
重用了convertView,减少了inflate的次数
使用ViewHolder,减少findViewById的次数,很大程度上的减少了内存的消耗。
19、布局的优化(就是提高UI的流程度)
1、优化布局层次。不要不断的嵌套LinearLayout ,多使用RelativeLayout 尽可能的减少布局的层次。如:左边是图片,右边是文字的,可以就使用一个TextView来完成。
2、使用抽象布局标签include、merge(include 辅助扩展 )、ViewStub (延时加载的view,当使用时才加载)、
3、使用最新布局ConstaintLayout
4、Android Lint工具寻求可能优化布局的层次
其他
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