Android面试题大全

本文目录

Android面试题总结

  • Android四大组件
    • Activity(活动)
      • 概念
    • Service(服务)
      • 概念
      • 定义与作用
    • Content Provider(内容提供器)
      • 介绍
      • 作用
      • 系统的Content Provider
      • 自定义Content Provider
    • Broadcast Receiver(广播)
      • 概述
      • 广播的作用
      • 广播接收者的创建
      • 广播接收者的类型
      • 注册广播的两种方式
      • 静态注册和动态注册的区别
      • 有序广播和无序广播的区别
      • 有序广播接收者们的优先级
      • 有序广播的拦截和篡改
  • Android类加载器
  • Android的系统架构
  • Android应用程序结构
  • Android中的几种动画
  • Android内存溢出内存泄露
  • 跨进程通讯的几种方式
  • Android中为什么子线程不能更新UI
    • 如果不做这个校验,是不是我也可以正常在子线程更新UI
    • 但是google为什么要这样去设计呢
    • ViewRootImp是在onActivityCreated方法后面创建的吗
    • 为什么一定需要checkThread呢
    • 那为什么不加锁呢
    • 为什么一开始在Activity的onCreate方法中创建一个子线程访问UI,程序还是正常能跑起来呢
    • Android中子线程真的不能更新UI吗
      • 保证上述条件1成立不就可以避免checkThread时候抛出异常了吗?为什么还需要开启消息循坏
    • 使用子线程更新UI有实际应用场景吗
  • Android程序运行时权限与文件系统权限的区别
  • Android进程与线程
    • 进程
      • 前台进程
      • 可见进程
      • 服务进程(service进程)
      • 后台进程
      • 空进程
    • Android线程间通信有哪几种方式
    • Devik进程和Linux进程的区别
    • 进程保活(不死进程)
      • 当前Android进程保活手段主要分为 黑、白、灰 三种
        • 黑色保活
        • 白色保活
        • 灰色保活
  • Android的数据存储
    • 使用SharedPreferences存储数据
    • 文件存储数据
    • SQLite数据库存储数据
    • 使用ContentProvider存储数据
    • 网络存储数据
  • Android六大布局
  • Activity(持续更新中~~~)

Android四大组件

简单介绍:Android四大核心组件指的是 Activity、Service、Content Provider、BroadCast Receiver,核心组件都是由 Android系统进行管理和维护的,一般都要在清单文件中进行注册或者在代码中动态注册。

活动(activity):用于表现功能;
服务(service):后台运行服务,不提供界面呈现;
内容提供者(Content Provider):支持多个应用中存储和读取数据;
广播接受者(Broadcast Receive):用于接收广播。

Activity(活动)

概念

概念:在android中,Activity相当于一个页面,可以在 Activity中添加 Button、CheckBox 等控件,一个android程序有多个Activity组成。
// Activity 之间通过 Intent 进行通信;直接通过 Bundle 对象来传递

  • 一个 Activity 通常就是一个单独的屏幕(窗口)
  • Activity 之间通过 Intent 进行通信。
  • Android 应用中每一个 Activity 都必须要在 AndroidManifest.xml 配置文件中声明,否则系统将不识别也不执行该Activity。在 android stdio会自动生成,但 eclipse 需要自己手动添加
    定义与作用: Activity 的中文意思是 活动,代表手机屏幕的一屏,或是平板电脑中的一个窗口,提供了和用户交互的可视化界面。一个活动开始,代表 Activity 组件启动,活动 结束,代表一个 Activity 的生命周期结束。一个 Android 应用必须通过 Activity 来 运行 和 启动,Activity 的生命周期交给系统统一管理。Activity 是用于处理 UI 相关业务的,比如加载界面、监听用户操作事件。

Service(服务)

概念

概念:Service(服务)是安卓中的四大组件之一,它通常用作在后台处理耗时的逻辑,与 Activity 一样,它存在自己的生命周期,也需要在 AndroidManifest.xml 配置相关信息。开发人员需要在应用程序配置文件中声明全部的 service,使用 标签。
Service 通常位于后台运行,它一般不需要与用户交互,因此 Service 组件没有图形用户界面。Service 组件需要继承Service 基类。Service 组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。

定义与作用

定义与作用:Service(服务)是一个没有用户界面的专门在后台处理耗时任务的 Android 组件,它没有UI。它有两种启动方式,startService和bindService。其他应用组件能够启动 Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。
Service 还有一个作用就是提升进程(每个应用都是一个进程)的优先级,进程的优先级指的是在 Android 系统中,会把正在运行的应用确定一个优先级,当内存空间不足时,系统会根据进程的优先级清理掉一部分进程占用的内存空间,以获得足够的内存空间以供新启用的应用运行。
详细的进程优先级划分如下:

  • 前台进程:应用程序存在Activity正位于前台,可见并可控
  • 可见进程:应用程序存在Activity处于局部可见状态,即局部可见却不可控
  • 服务进程:应用程序存在正在运行的Service
  • 后台进程:应用程序的所有Activity均被置于后台,没有任何Activity可见
  • 空进程:已经退出的应用程序

Content Provider(内容提供器)

介绍

介绍:Content Provider是 android 四大组件之一的内容提供器,它主要的作用就是将程序的内部的数据和外部进行共享,为数据提供外部访问接口,被访问的数据主要以数据库的形式存在,而且还可以选择共享哪一部分的数据。这样一来,对于程序当中的隐私数据可以不共享,从而更加安全。Content Provider 是 android中 一种跨程序共享数据的重要组件

  • android 平台提供了 ContentProvider 把一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类 从该内容提供者中获取或存入数据。
  • 只有需要在多个应用程序间共享数据是才需要 内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。
  • ContentProvider 实现数据共享。ContentProvider 用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为 android 没有提供所有应用共同访问的公共存储区。
  • 开发人员不会直接使用 ContentProvider 类的对象,大多数是通过 ContentResolver 对象实现对 Content Provider 的操作。
  • Content Provider 使用 URI 来唯一标识其数据集,这里的 URI 以 content:// 作为前缀,表示该数据由 Content Provider来管理。

四大基本组件都需要注册才能使用,每个 Activity、service、Content Provider 都需要在 AndroidManifest 文件中进行配置。AndroidManifest 文件中未进行声明的 activity、服务 以及 内容提供者 将不为系统所见,从而也就不可用。而 broadcast receiver 广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)和通过代码动态创建并以调用Context.registerReceiver()的方式注册至系统。需要注意的是在AndroidManifest文件中进行配置的广播接收者会随系统的启动而一直处于活跃状态,只要接收到感兴趣的广播就会触发(即使程序未运行)。

作用

作用:Content Provider中文意思是内容提供者,Content Provider可以将应用程序自身的数据对外(对其它应用程序)共享,使得其它应用可以对自身的数据进行增、删、改、查操作。

系统的Content Provider

// 使用系统的 Content Provider:
Android 系统使用了许多 Content Provider,将系统中的绝大部分常规数据进行对外共享,系统的 ContentProvider 有很多,例如:通讯录、通话记录、短信、相册、歌曲、视频、日历等等,一般这些数据都存放于一个个的数据库中。同时这些数据一般都需要和第三方的 app 进行共享数据。既然是使用系统的,那么 Content Provider的具体实现就不需要我们担心了,使用内容提供者的步骤如下:
1、获取 Content Resolver 实例
2、确定 Uri 的内容,并解析为具体的 Uri 实例
3、通过 Content Resolver 实例来调用相应的方法,传递相应的参数,但是第一个参数总是 Uri,它制定了我们要操作的数据的具体地址

自定义Content Provider

// 自定义 ContentProvider:
系统的 Content Provider在与我们交互的时候,只接受了一个 Uri 的参数,然后根据我们的操作返回给我们结果。系统到底是如何根据一个 Uri 就能够提供给我们准确的结果呢?只有自己亲自实现一个看看了。
和之前提到的一样,想重新自定义自己程序中的四大组件,就必须重新实现一个类,重写这个类中的抽象方法,在清单文件中注册,最后才能够正常使用。

Broadcast Receiver(广播)

概述

概述:
Broadcast Receiver( 广播接收者 )顾名思义就是用来接收来自系统和应用中的广播 的 系统组件。广播是一种一对多的通信方式,即存在1个发送方,若干个接收方。在 Android 系统中,广播体现在方方面面,例如:当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。把这种数据的传递方式的机制称之为 “广播” 。Android 系统会在特定的情景下发出各种广播,例如开机、锁屏了、电量不足了、正在充电了、呼出电话了、被呼叫了……
// android广播分为两个角色:发送者和接收者

广播的作用

  • 用于不同组件间的通信(含:应用内/不同应用之间)
  • 用于多线程通信
  • 与 android 系统的通信

广播接收者的创建

  1. 构建 Intent,使用 sendBroadcast 方法发出广播。
  2. 自定义一个类,该 类 继承 BroadcastReceive 基类
  3. 重写抽象方法 onReceive() 方法
  4. 注册该广播接收者,我们可以在代码中注册,也可以在 manifest.xml 中注册。

广播接收者的类型

  • Normal broadcasts:默认广播。发送一个默认广播使用 Content.sendBroadcast() 方法,普通广播对于接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。
  • Ordered broadcasts:有序广播。发送一个有序广播使用 Content.sendOrderedBroadcast() 方法,有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接收者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播
  • Sticky Broadcast:粘性广播。当处理完之后的 Intent,依然存在,直到你把它去掉。

注册广播的两种方式

广播接收者的注册有两种方法,分别是AndroidManifest文件中进行静态注册和程序动态注册。

  1. 第一种是静态注册,也可成为常驻型广播,这种广播需要在Androidmanifest.xml中进行注册,这中方式注册的广播,不受页面生命周期的影响,即使退出了页面,也可以收到广播这种广播一般用于想开机自启动啊等等,由于这种注册的方式的广播是常驻型广播,所以会占用CPU的资源。
  2. 第二种是动态注册,而动态注册的话,是在代码中注册的,这种注册方式也叫非常驻型广播,收到生命周期的影响,退出页面后,就不会收到广播,我们通常运用在更新UI方面。这种注册方式优先级较高。最后需要解绑,否会会内存泄露。

静态注册和动态注册的区别

  • 动态注册广播接收者特点是当用来注册的 Activity 关掉后,广播也就失效了。( 动态注册广播不是常驻型广播,也就是说广播跟随 activity 的生命周期。注意:在 activity 结束前,移除广播接收器。 )
  • 静态注册时无需担忧广播接收者是否被关闭,只要设备是开启状态,广播接收者也是打开着的。也就是说哪怕 app 本身未启动,该 app 订阅的广播在触发时也会对它起作用。( 静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。 )

有序广播和无序广播的区别

  • 普通广播: 即为 无序广播,谁都可以接收,并不会相互打扰。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播 Intent 的传播;
  • 有序广播:调用 sendOrderedBroadcast(Intent, String permission)方法发送的广播,各广播接收者在接收广播时,会存在一定的先后顺序,即某接收者会先收到广播,其他接收者后收到广播,广播会在各接收者之间按照一定的先后顺序进行传递。在广播的传递过程中,先接收到广播的接收者可以对广播进行拦截或篡改。( 有序广播是按照接收者声明的优先级别(声明在 intent-filter 元素的 android:priority 属性中,数越大优先级别越高,取值范围:-1000 到 1000。也可以调用IntentFilter 对象的 setPriority() 进行设置),被接收者依次接收广播。如:A 的级别高于 B,B 的级别高于 C,那么,广播先传给A,再传给B,最后传给C。A 得到广播后,可以往广播里存入数据,当广播传给 B 时,B可以从广播中得到 A 存入的数据

总结:

  • 当广播为有序广播时:
    1. 优先级高的先接收
    2. 同优先级的广播接收器,动态优先于静态
    3. 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
  • 当广播为普通广播时:
    1. 无视优先级,动态广播接收器优先于静态广播接收器
    2. 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。

有序广播接收者们的优先级

有序广播的接收者们的优先级用于确定接收的先后顺序,优先级越高的接收者,将更优先接收到广播,反之,则更靠后接收到广播。

  1. 注册广播时,在广播对应的 IntentFilter 中的 priority 属性直接决定优先级,该属性值为 int 类型的数值,取值越大,则优先级越高!
  2. 如果存在多个广播接收者配置的 priority 属性值相同,则动态注册的广播接收者的优先级高于静态注册的广播接收者。
  3. 如果根据以上两条规则都无法确定优先级,则根据注册的先后顺序确定各接收者们的优先级。

有序广播的拦截和篡改

  • 拦截:在广播接收者中,使用abortBroadcast()方法,可以终止有序广播向后继续传递,即后续的接收者们将无法接收到该广播。注意:该方法只能在接收有序广播时调用!
  • 篡改:在广播接收者中,调用setResult()方法,可以向广播中添加数据,并在后续的接收者中,可以通过getResult()获取这些数据,同时,后续的接收者也可以再次调用setResult()方法重新向广播中写入数据,即覆盖原有的数据,以实现篡改。

Android类加载器

在Android开发中,不管是插件化还是组件化,都是基于Android系统的类加载器ClassLoader来设计的。只不过Android平台上虚拟机运行的是Dex字节码,一种对class文件优化的产物,传统Class文件是一个Java源码文件会生成一个.class文件,而Android是把所有Class文件进行合并、优化,然后再生成一个最终的class.dex,目的是把不同class文件重复的东西只需保留一份,在早期的Android应用开发中,如果不对Android应用进行分dex处理,那么最后一个应用的apk只会有一个dex文件。

Android中常用的类加载器有两种,DexClassLoader和PathClassLoader,它们都继承于BaseDexClassLoader。区别在于调用父类构造器时,DexClassLoader多传了一个optimizedDirectory参数,这个目录必须是内部存储路径,用来缓存系统创建的Dex文件。而PathClassLoader该参数为null,只能加载内部存储目录的Dex文件。所以我们可以用DexClassLoader去加载外部的apk文件,这也是很多插件化技术的基础。

Android的系统架构

从小到上就是:linux,kernel,lib,dalvik vm,application,framework, app

Android应用程序结构

  1. main code
  2. unit test
  3. manifest
  4. res -> drawable,drawable-xxhdpi,layout,value,mipmap
    mipmap 是一种很早就有的技术了,翻译过来就是纹理映射技术.
    google建议只把启动图片放入。
  5. lib
  6. color

Android中的几种动画

帧动画:指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果,比如想听的律动条。

视图动画(补间动画):指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有Alpha、Scale、Translate、Rotate四种效果。注意:只是在视图层实现了动画效果,并没有真正改变View的属性,比如滑动列表,改变标题栏的透明度。

属性动画:在Android3.0的时候才支持,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。比如view的旋转,放大,缩小。
通过变化属性来达到动画的效果,性能略差,支持点击等事件。android 3.0

Gif动画:原理和帧动画差不多,是canvas画出来。

Android内存溢出内存泄露

// 内存溢出:
out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存溢出通俗的讲就是内存不够用。
// 内存泄露:
memory leak:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光
// 内存泄露检测工具 → LeakCanary

跨进程通讯的几种方式

// Android 跨进程通信,像intent,contentProvider,广播,service都可以跨进程通信。
1、Files 文件系统(包括内存映射)
2、Sockets
3、Pipes 管道
4、共享内存
5、Intents, ContentProviders, Messenger
6、Binder

intent:这种跨进程方式并不是访问内存的形式,它需要传递一个uri,比如说打电话。
contentProvider:这种形式,是使用数据共享的形式进行数据共享。
service:远程服务,aidl
广播

Android中为什么子线程不能更新UI

// Android中为什么子线程不能更新UI?
viewRootImpl对象是在Activity中的onResume方法执行完成之后,View变得可见时才创建的,之前的操作是没有进行线程检查的,所以没有报错。但是ViewRootImpl创建之后,由于进行了checkThread操作,所以就不能在子线程更改UI了
当访问 UI 时,ViewRootImpl 会调用 checkThread方法去检查当前访问 UI 的线程是否为创建 UI 的那个线程,如果不是。则会抛出异常

如果不做这个校验,是不是我也可以正常在子线程更新UI

// 如果不做这个校验,是不是我也可以正常在子线程更新UI?
按理来说,这样是可以的

但是google为什么要这样去设计呢

// 但是google为什么要这样去设计呢
1.如果在不同的线程去控制用一个控件,由于网络延时或者大量耗时操作,会使UI绘制错乱,出了问题也很难去排查到底是哪个线程更新时出了问题;
2.主线程负责更新,子线程负责耗时操作,能够大大提高响应效率
3.UI线程非安全线程,多线程进行并发访问有可能会导致内存溢出,降低硬件使用寿命;且非线程安全不能加Lock线程锁,否则会阻塞其他线程对View的访问,效率就会变得低下!

ViewRootImp是在onActivityCreated方法后面创建的吗

// ViewRootImp是在onActivityCreated方法后面创建的吗?
1、ViewRootImpl是在Activity的onResume()方法后面创建出来的,所以在onResume之前的UI更新可以在子线程操作而不报错,因为这个时候ViewRootImpl还没有创建,没有执行checkThread()方法。
2、安卓系统中,操作viwe对象没有加锁,所以如果在子线程中更新UI,会出现多线程并发的问题,导致页面展示异常。

为什么一定需要checkThread呢

// 为什么一定需要checkThread呢?
因为UI控件不是线程安全的

那为什么不加锁呢

// 那为什么不加锁呢?
一是加锁会让UI访问变得复杂;
二是加锁会降低UI访问效率,会阻塞一些线程访问UI。
所以干脆使用单线程模型处理UI操作,使用时用Handler切换即可

为什么一开始在Activity的onCreate方法中创建一个子线程访问UI,程序还是正常能跑起来呢

// 为什么一开始在Activity的onCreate方法中创建一个子线程访问UI,程序还是正常能跑起来呢?
因为ViewRootImpl 的创建在 onResume 方法回调之后,而我们一开篇是在 onCreate 方法中创建了子线程并访问 UI,在那个时刻,ViewRootImpl 还没有创建,我们在因此 ViewRootImpl#checkThread 没有被调用到,也就是说,检测当前线程是否是创建的 UI 那个线程 的逻辑没有执行到,所以程序没有崩溃一样能跑起来。而之后修改了程序,让线程休眠了 3000 毫秒后,程序就崩了。很明显 3000 毫秒后 ViewRootImpl 已经创建了,可以执行 checkThread 方法检查当前线程

Android中子线程真的不能更新UI吗

// Android中子线程真的不能更新UI吗?
任何线程都可以更新自己创建的UI,但是需要满足各自对应的条件

  1. ViewRootImpl 还没创建出来之前。UI 修改的操作没有线程限制。因为 checkThread 方法不会被执行到。
  2. 在 ViewRootImpl 创建完成之后,保证「创建 ViewRootImpl 的操作」和「执行修改 UI 的操作」在同一个线程即可。也就是说,要在同一个线程调用 ViewManager的addView 和 ViewManager的updateViewLayout 方法。
    // 注:ViewManager 是一个接口,WindowManger 接口继承了这个接口,我们通常都是通过 WindowManger(具体实现为 WindowMangerImpl) 进行 view 的 add remove update 操作的。
    对应的线程需要创建 Looper 并且调用 Looper的loop 方法,开启消息循环。

保证上述条件1成立不就可以避免checkThread时候抛出异常了吗?为什么还需要开启消息循坏

// 保证上述条件1成立,不就可以避免checkThread时候抛出异常了吗?为什么还需要开启消息循坏?
条件 1 可以避免检查异常,但是无法保证 UI 可以被绘制出来。
条件 2 可以让更新的 UI 效果呈现出来。
:WindowManger的addView 最终会调用WindowManageGlobal的addView方法,进而触发ViewRootImpl的setView 方法,该方法内部会调用ViewRootImpl的requestLayout 方法。根据 UI 绘制原理,下一步就是 scheduleTraversals了,该方法会往消息队列中插入一条消息屏障,然后调用 Choreographer的postCallback 方法,往 looper 中插入一条异步的 MSG_DO_SCHEDULE_CALLBACK 消息。等待垂直同步信号回来之后执行

使用子线程更新UI有实际应用场景吗

// 使用子线程更新 UI 有实际应用场景吗?
Android 中的 SurfaceView 通常会通过一个子线程来进行页面的刷新。如果我们的自定义 View 需要频繁刷新,或者刷新时数据处理量比较大,那么可以考虑使用 SurfaceView 来取代 View

Android程序运行时权限与文件系统权限的区别

文件的系统权限是由linux系统规定的,只读,读写等。
运行时权限是对于某个系统上的app的访问权限,允许,拒绝,询问。这个可以防止非法的程序访问敏感的信息。

Android进程与线程

进程

  • 前台进程
  • 可见进程
  • 服务进程
  • 后台进程
  • 空进程

前台进程

// 前台进程

  1. 当前进程activity正在与用户进行交互。
  2. 当前进程service正在与activity进行交互或者当前service调用了startForground()属于前台进程或者当前service正在执行生命周期(onCreate(),onStart(),onDestory())
  3. 进程持有一个BroadcostReceiver,这个BroadcostReceiver正在执行onReceive()方法

可见进程

// 可见进程:

  1. 进程持有一个activity,这个activity不再前台,处于onPouse()状态下,当前覆盖的activity是以dialog形式存在的。
  2. 进程有一个service,这个service和一个可见的Activity进行绑定。

服务进程(service进程)

// service进程:
当前开启startSerice()启动一个service服务就可以认为进程是一个服务进程。

后台进程

// 后台进程
activity的onStop()被调用,但是onDestroy()没有调用的状态。该进程属于后台进程。

空进程

// 空进程:
改进程没有任何运行的数据了,且保留在内存空间,并没有被系统killed,属于空进程。该进程很容易被杀死。

Android线程间通信有哪几种方式

  • 共享变量(内存)
  • 管道
  • handler机制
    • runOnUiThread(Runnable)
    • view.post(Runnable)

Devik进程和Linux进程的区别

// Davik 进程:

  • Dalvik 虚拟机运行在 Linux 系统之上。
  • Davik 进程就是 Linux 操作系统中的一个进程,属于 Linux 进程。
  • 每一个 Android 应用程序进程都有一个 Dalvik 虚拟机实例。这样做的好处是 Android 应用程序进程之间不会相互影响,也就是说,一个 Android 应用程序进程的意外终止,不会影响到其他的应用程序进程的正常运行。
    :每个 Android 应用程序都会对应一个独立的 Dalvik 虚拟机

// Linux 进程:

  • 有独立的内核堆栈和独立的存储空间,它是操作系统中资源分配和调度的最小单位。
  • 以进程为单位,分配系统资源,给程序进行调度。
  • 在执行一个程序时,它会创建一个进程,来执行应用程序,并且伴随着资源的分配和释放。

进程保活(不死进程)

当前Android进程保活手段主要分为 黑、白、灰 三种

黑色保活:不同的app进程,用广播相互唤醒(包括利用系统提供的广播进行唤醒)
白色保活:启动前台Service
灰色保活:利用系统的漏洞启动前台Service

黑色保活

所谓黑色保活,就是利用不同的app进程使用广播来进行相互唤醒

  • 场景1 :开机,网络切换、拍照、拍视频时候,利用系统产生的广播唤醒app
  • 场景2 :接入第三方SDK也会唤醒相应的app进程,如微信sdk会唤醒微信,支付宝sdk会唤醒支付宝。由此发散开去,就会直接触发了下面的 场景3
  • 场景3 :假如你手机里装了支付宝、淘宝、天猫等阿里系的app,那么你打开任意一个阿里系的app后,有可能就顺便把其他阿里系的app给唤醒了。(只是拿阿里打个比方,其实BAT系都差不多)

白色保活

// 白色保活
白色保活手段非常简单,就是调用系统api启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification,用来让用户知道有这样一个app在运行着

灰色保活

// 灰色保活
灰色保活,这种保活手段是应用范围最广泛。它是利用系统的漏洞来启动一个前台的Service进程,与普通的启动方式区别在于,它不会在系统通知栏处出现一个Notification,看起来就如同运行着一个后台Service进程一样。这样做带来的好处就是,用户无法察觉到你运行着一个前台进程(因为看不到Notification),但你的进程优先级又是高于普通后台进程的。那么如何利用系统的漏洞呢,大致的实现思路和代码如下:
思路一:API 思路二:API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理

Android的数据存储

使用SharedPreferences存储数据

它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能在不同的包之间使用。

文件存储数据

文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。

SQLite数据库存储数据

SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库

使用ContentProvider存储数据

主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此Content Provider的各种数据类型

网络存储数据

通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息

Android六大布局

Activity(持续更新中~~~)

未经允许不得转载:木盒主机 » Android面试题大全

赞 (5)

相关推荐

    暂无内容!