安卓面试基础知识

1、什么是ANR 如何避免它?

这个对话框称作应 用程序无响应(ANR:Application NotResponding)对话框。

不同的组件发生ANR的时间不一样,Activity是5秒,BroadCastReceiver是10秒,Service是20秒(均为前台)。

如果开发机器上出现问题,我们可以通过查看/data/anr/traces.txt即可,最新的ANR信息在最开始部分。

存在情形:

  • 主线程存在耗时操作,被阻塞
  • 应用在5秒内未响应用户的输入事件(如按键或者触摸)
  • BroadcastReceiver未在10秒内完成相关的处理
  • Service在特定的时间内无法处理完成 20秒

解决方案:放在子线程执行,然后通过handler、runOnUIThread、AsyncTask等方式更新UI

2、Activity和Fragment生命周期有哪些?

image.png

3、横竖屏切换时候Activity的生命周期

  1. 不设置Activity的android:configChanges时,切屏会重新回调各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
  2. 设置Activity的android:configChanges=”orientation”时,切屏还是会调用各个生命周期,切换横竖屏只会执行一次
  3. 设置Activity的android:configChanges=”orientation |keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

5、onSaveInstanceState() 与 onRestoreIntanceState()

当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。

在activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。

onSaveInstanceState在stop方法之前调用。
onRestoreInstanceState在start方法后调用

6、android中进程的优先级?

  1. 前台进程:
    即与用户正在交互的Activity或者Activity用到的Service等,如果系统内存不足时前台进程是最晚被杀死的
  2. 可见进程:
    可以是处于暂停状态(onPause)的Activity或者绑定在其上的Service,即被用户可见,但由于失了焦点而不能与用户交互
  3. 服务进程:
    其中运行着使用startService方法启动的Service,虽然不被用户可见,但是却是用户关心的,例如用户正在非音乐界面听的音乐或者正在非下载页面下载的文件等;当系统要空间运行,前两者进程才会被终止
  4. 后台进程:
    其中运行着执行onStop方法而停止的程序,但是却不是用户当前关心的,例如后台挂着的QQ,这时的进程系统一旦没了有内存就首先被杀死
  5. 空进程:
    不包含任何应用程序的进程,这样的进程系统是一般不会让他存在的

7、Bunder传递对象为什么需要序列化?Serialzable和Parcelable的区别?

因为bundle传递数据时只支持基本数据类型,所以在传递对象时需要序列化转换成可存储或可传输的本质状态(字节流)。

序列化后的对象可以在网络、IPC(比如启动另一个进程的Activity、Service和Reciver)之间进行传输,也可以存储到本地。

Serialzable和Parcelable的区别?
image.png

8、动画

帧动画

是在xml中定义好一系列图片之后,使用AnimatonDrawable来播放的动画。

补间动画

可以实现平移、旋转、放缩、渐变等功能,但是动画执行完后,焦点还是在原来的位置,控件的属性未真的改变

属性动画

比补件动画功能强大,可以定义出各式各样的动画,并且支持对控件的属性进行改变,动画的特征是在一定的时间内不断修改对象属性值的机制,所以不会影响动画执行后所在位置的正常使用

过程

  1. 首先制定目标对象的开始、结束、持续时间。
  2. 计算已完成动画百分比
  3. 调用TimeInterpolator计算插值分数,调用TypeEvaluator去计算运动中的属性值。设置动画操作的属性值

插值器:属性变化的百分比
估值器:属性变化的数值

其实就是利用插值器和估值器,来计出各个时刻View的属性,然后通过改变View的属性来实现View的动画效果。

9、Context相关

ContextThemeWrapper其内部包含了与主题(Theme)相关的接口,就是指在AndroidManifest.xml中通过android:theme为Application元素或者Activity元素指定的主题

作用域

一个Activity的启动必须要建立在另一个Activity的基础之上,Dialog则必须在一个Activity上面弹出(除非是System Alert类型的Dialog)

image.png

Application和Service所不推荐的两种使用情况

  1. 用ApplicationContext去启动一个LaunchMode为standard的Activity的时候会报AndroidRuntimeException,因为非Activity类型的Context并没有任务栈,所以待启动的Activity就找不到栈了,需要加FLAG_ACTIVITY_NEW_TASK标记位位,此时Activity启动模式变成singleTask。
  2. 在Application和Service中去layout inflate是合法的,但是会使用系统默认的主题样式,自定义样式可能不会被使用。

获取Context对象
View.getContext获取Activity对象,Activity.getApplicationContext获取Application对象,Activity.this获取当前Activity对象,
ContextWrapper.getBaseContext()获取被装饰前的Context,不推荐使用。

内存泄露
Application的Context对象可以理解为随着进程存在

参考地址:
http://www.jianshu.com/p/94e0f9ab3f1d
http://stay4it.com/course/25
http://blog.csdn.net/guolin_blog/article/details/47028975
http://blog.csdn.net/yanbober/article/details/459676

10、Android各版本新特性

Android8.0(O)新特性
  • 优化通知
  • 通知渠道 (Notification Channel)通知标志 休眠 通知超时 通知设置 通知清除
  • 画中画模式:清单中Activity设置android:supportsPictureInPicture
  • 后台限制
  • 自动填充框架
  • 系统优化
Android9.0(P)新特性
  • 室内WIFI定位
  • “刘海”屏幕支持
  • 安全增强
Android10.0(Q)目前曝光的新特性
  • 可折叠
  • 5G网络
  • 夜间主题,适配:在主题背景中设置可自动适配。
  • Live Caption,此功能将自动向视频、播客和音频消息添加说明文字。
  • 分区存储,针对外部存储做的改变,

    • 应用私有的外部存储还是和以前一样,使用getExternalFilesDir()访问。应用在卸载后,会将App-specific目录下的数据删除,如果在AndroidManifest.xml中声明:android:hasFragileUserData="true"用户可以选择是否保留。
    • 共享的媒体文件,必须使用MediaStore访问
    • 其他文件则要通过存储访问框架进行访问
  • 权限变化

    • 引入后台访问位置权限(授予粗或精确位置使用权限的同时。如果没有在清单文件中定义该权限,那么仅有前台有访问权。如果定义了,那么前后台都可以有访问权)
    • 一些电话、蓝牙和WLAN的API需要精确位置权限
  • 后台启动activity限制,应用处于后台时,无法启动activity

    • 因为此项行为变更适用于在 Android 10 上运行的所有应用,所以这一限制导致最明显的问题就是点击推送信息时,有些应用无法进行正常的跳转(具体的实现问题导致)。所以针对这类问题,可以采取PendingIntent的方式,发送通知时使用setContentIntent方法。
  • 限制了对剪切板数据的访问权限

参看:https://weilu.blog.csdn.net/article/details/104513170

11、Json

JSON是存储和交换文本信息的语法,类似XML,但是比XML更小、更快,更易解析 JSON是轻量级的文本数据交换格式,独立于语言,具有可描述性,更易理解,对象可以包含多个名称/值对

使用谷歌的GSON包进行解析

优点:

  • 轻量级的数据交换格式
  • 读写更加容易
  • 易于机器的解析和生成
  • 缺点:
  • 语义性较差,不如 xml 直观

13、Jar和Aar的区别

Jar包里面只有代码,aar里面不光有代码还包括资源文件,比如 drawable 文件,xml资源文件。对于一些不常变动的 Android Library,我们可以直接引用 aar,加快编译速度。

14、Android为每个应用程序分配的内存大小是多少

android程序内存一般限制在16M,也有的是24M。近几年手机发展较快,一般都会分配两百兆左右,和具体机型有关。

15、更新UI方式

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable),View.postDelay(Runnable, long)(可以理解为在当前操作视图UI线程添加队列)
  • Handler
  • AsyncTask
  • Rxjava
  • LiveData

16、ContentProvider使用方法。

进行跨进程通信,实现进程间的数据交互和共享。通过Context 中 getContentResolver() 获得实例,通过 Uri匹配进行数据的增删改查。ContentProvider使用表的形式来组织数据,无论数据的来源是什么,ConentProvider 都会认为是一种表,然后把数据组织成表格。

17、Thread、AsyncTask、IntentService的使用场景与特点。

  • Thread线程,独立运行与于 Activity 的,当Activity 被 finish 后,如果没有主动停止 Thread或者 run 方法没有执行完,其会一直执行下去。
  • AsyncTask 封装了两个线程池和一个Handler(SerialExecutor用于排队(内部维护一个队列,通过同步锁修饰execute(),保证AsyncTask的任务是串行执行的),THREAD_POOL_EXECUTOR为真正的执行任务,Handler将工作线程切换到主线程),其必须在 UI线程中创建,execute 方法必须在 UI线程中执行,一个任务实例只允许执行一次,执行多次抛出异常,用于网络请求或者简单数据处理。
  • IntentService:处理异步请求,实现多线程,在onHandleIntent中处理耗时操作,多个耗时任务会依次执行,执行完毕自动结束。(IntentService 中使用的 Handler、Looper、MessageQueue 机制把消息发送到线程中去执行的,所以多次启动 IntentService 不会重新创建新的服务和新的线程,只是把消息加入消息队列中等待执行,而如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。)

18、Merge、ViewStub 的作用。

  • Merge: 可以删除多余的层级,降低UI布局的嵌套层次。
  • ViewStub: 按需加载,减少内存使用量、加快渲染速度、不支持 merge 标签。(原理:当手动调用inflate()或者设置visible(实际上也是调用inflate函数),会将ViewStub从父控件移除,并加装目标控件,然后将目标控件添加到ViewStub父控件中去,这就完成了视图动态替换,也就是延迟加载功能)

19、activity的startActivity和context的startActivity区别?

(1)、从Activity中启动新的Activity时可以直接mContext.startActivity(intent)就好
(2)、如果从其他Context中启动Activity则必须给intent设置Flag:

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ; 
mContext.startActivity(intent);

20、怎么在Service中创建Dialog对话框?
1.在我们取得Dialog对象后,需给它设置类型,即:

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)

2.在Manifest中加上权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINOW" />

21、Asset目录与res目录的区别?
assets:不会在 R 文件中生成相应标记,存放到这里的资源在打包时会打包到程序安装包中。(通过 AssetManager 类访问这些文件)
res:会在 R 文件中生成 id 标记,资源在打包时如果使用到则打包到安装包中,未用到不会打入安装包中。
res/anim:存放动画资源。
res/raw:和 asset 下文件一样,打包时直接打入程序安装包中(会映射到 R 文件中)。

22、Android怎么加速启动Activity?

onCreate() 中不执行耗时操作
把页面显示的 View 细分一下,放在 AsyncTask 里逐步显示,用 Handler 更好。这样用户的看到的就是有层次有步骤的一个个的 View 的展示,不会是先看到一个黑屏,然后一下显示所有 View。最好做成动画,效果更自然。
利用多线程的目的就是尽可能的减少 onCreate() 和 onReume() 的时间,使得用户能尽快看到页面,操作页面。
减少主线程阻塞时间。
提高 Adapter 和 AdapterView 的效率。
优化布局文件。

23、Handler机制

Android消息循环流程图如下所示:

[图片上传失败...(image-679480-1583388414380)]

<figcaption></figcaption>

主要涉及的角色如下所示:

  • message:消息。
  • MessageQueue:消息队列,负责消息的存储与管理,负责管理由 Handler 发送过来的 Message。读取会自动删除消息,单链表维护,插入和删除上有优势。在其next()方法中会无限循环,不断判断是否有消息,有就返回这条消息并移除。
  • Looper:消息循环器,负责关联线程以及消息的分发,在该线程下从 MessageQueue获取 Message,分发给Handler,Looper创建的时候会创建一个 MessageQueue,调用loop()方法的时候消息循环开始,其中会不断调用messageQueue的next()方法,当有消息就处理,否则阻塞在messageQueue的next()方法中。当Looper的quit()被调用的时候会调用messageQueue的quit(),此时next()会返回null,然后loop()方法也就跟着退出。
  • Handler:消息处理器,负责发送并处理消息,面向开发者,提供 API,并隐藏背后实现的细节。

整个消息的循环流程还是比较清晰的,具体说来:

  • 1、Handler通过sendMessage()发送消息Message到消息队列MessageQueue。
  • 2、Looper通过loop()不断提取触发条件的Message,并将Message交给对应的target handler来处理。
  • 3、target handler调用自身的handleMessage()方法来处理Message。

事实上,在整个消息循环的流程中,并不只有Java层参与,很多重要的工作都是在C++层来完成的。我们来看下这些类的调用关系。

[图片上传失败...(image-b348d9-1583388414379)]

<figcaption></figcaption>

注:虚线表示关联关系,实线表示调用关系。

在这些类中MessageQueue是Java层与C++层维系的桥梁,MessageQueue与Looper相关功能都通过MessageQueue的Native方法来完成,而其他虚线连接的类只有关联关系,并没有直接调用的关系,它们发生关联的桥梁是MessageQueue。

总结
  • Handler 发送的消息由 MessageQueue 存储管理,并由 Looper 负责回调消息到 handleMessage()。
  • 线程的转换由 Looper 完成,handleMessage() 所在线程由 Looper.loop() 调用者所在线程决定。
Handler 引起的内存泄露原因以及最佳解决方案

Handler 允许我们发送延时消息,如果在延时期间用户关闭了 Activity,那么该 Activity 会泄露。 这个泄露是因为 Message 会持有 Handler,而又因为 Java 的特性,内部类会持有外部类,使得 Activity 会被 Handler 持有,这样最终就导致 Activity 泄露。

解决:将 Handler 定义成静态的内部类,在内部持有 Activity 的弱引用,并在Acitivity的onDestroy()中调用handler.removeCallbacksAndMessages(null)及时移除所有消息。

为什么我们能在主线程直接使用 Handler,而不需要创建 Looper ?

通常我们认为 ActivityThread 就是主线程。事实上它并不是一个线程,而是主线程操作的管理者。在 ActivityThread.main() 方法中调用了 Looper.prepareMainLooper() 方法创建了 主线程的 Looper ,并且调用了 loop() 方法,所以我们就可以直接使用 Handler 了。

因此我们可以利用 Callback 这个拦截机制来拦截 Handler 的消息。如大部分插件化框架中Hook ActivityThread.mH 的处理。

主线程的 Looper 不允许退出

主线程不允许退出,退出就意味 APP 要挂。

Handler 里藏着的 Callback 能干什么?

Handler.Callback 有优先处理消息的权利 ,当一条消息被 Callback 处理并拦截(返回 true),那么 Handler 的 handleMessage(msg) 方法就不会被调用了;如果 Callback 处理了消息,但是并没有拦截,那么就意味着一个消息可以同时被 Callback 以及 Handler 处理。

创建 Message 实例的最佳方式

因为Message内部维护了1个Message池,用于Message消息对象的复用,使用obtain()则是直接从池内获取,避免内存new Message重新分配内存。

为了节省开销,Android 给 Message 设计了回收机制,所以我们在使用的时候尽量复用 Message ,减少内存消耗:

  • 通过 Message 的静态方法 Message.obtain();
  • 通过 Handler 的公有方法 handler.obtainMessage()。
子线程里弹 Toast 的正确姿势

本质上是因为 Toast 的实现依赖于 Handler,按子线程使用 Handler 的要求修改即可,同理的还有 Dialog。

妙用 Looper 机制
  • 将 Runnable post 到主线程执行;
  • 利用 Looper 判断当前线程是否是主线程。
主线程的死循环一直运行是不是特别消耗CPU资源呢?

loop虽然是死循环,但是如果messagequeue里面没有消息的话,会休眠在native层那个nativePollonce方法

并不是,这里就涉及到Linux pipe/epoll机制,简单说就是在主线程的MessageQueue没有消息时,便阻塞在loop的queue.next()中的nativePollOnce()方法里,此时主线程会释放CPU资源进入休眠状态,直到下个消息到达或者有事务发生,通过往pipe管道写端写入数据来唤醒主线程工作。这里采用的epoll机制,是一种IO多路复用机制,可以同时监控多个描述符,当某个描述符就绪(读或写就绪),则立刻通知相应程序进行读或写操作,本质是同步I/O,即读写是阻塞的。所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。

handler postDelay这个延迟是怎么实现的?

handler.postDelay并不是先等待一定的时间再放入到MessageQueue中,而是直接进入MessageQueue,以MessageQueue的时间顺序排列和唤醒的方式结合实现的。

如何保证在msg.postDelay情况下保证消息次序?

Handler 都没搞懂,拿什么去跳槽啊?

24、程序A能否接收到程序B的广播?
能,使用全局的BroadCastRecevier能进行跨进程通信,但是注意它只能被动接收广播。此外,LocalBroadCastRecevier只限于本进程的广播间通信。

25、数据加载更多涉及到分页,你是怎么实现的?
分页加载就是一页一页加载数据,当滑动到底部、没有更多数据加载的时候,我们可以手动调用接口,重新刷新RecyclerView。

26、通过google提供的Gson解析json时,定义JavaBean的规则是什么?
1). 实现序列化 Serializable
2). 属性私有化,并提供get,set方法
3). 提供无参构造
4). 属性名必须与json串中属性名保持一致 (因为Gson解析json串底层用到了Java的反射原理)

28、线程池的相关知识。
Android中的线程池都是直接或间接通过配置ThreadPoolExecutor来实现不同特性的线程池.Android中最常见的类具有不同特性的线程池分别为FixThreadPool、CachedhreadPool、SingleThreadPool、ScheduleThreadExecutr.
1).FixThreadPool
只有核心线程,并且数量固定的,也不会被回收,所有线程都活动时,因为队列没有限制大小,新任务会等待执行.
优点:更快的响应外界请求.
2).SingleThreadPool
只有一个核心线程,确保所有的任务都在同一线程中按序完成.因此不需要处理线程同步的问题.
3).CachedThreadPool
只有非核心线程,最大线程数非常大,所有线程都活动时会为新任务创建新线程,否则会利用空闲线程(60s空闲时间,过了就会被回收,所以线程池中有0个线程的可能)处理任务.
优点:任何任务都会被立即执行(任务队列SynchronousQuue相当于一个空集合);比较适合执行大量的耗时较少的任务.
4).ScheduledThreadPool
核心线程数固定,非核心线程(闲着没活干会被立即回收数)没有限制.
优点:执行定时任务以及有固定周期的重复任务

29、内存泄露,怎样查找,怎么产生的内存泄露?

30、类的初始化顺序依次是?

(静态变量、静态代码块)>(变量、代码块)>构造方法

31、JSON的结构?
json是一种轻量级的数据交换格式,
json简单说就是对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构
1、对象:对象表示为“{}”扩起来的内容,数据结构为 {key:value,key:value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。
2、数组:数组在json中是中括号“[]”扩起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种。
经过对象、数组2种结构就可以组合成复杂的数据结构了。

32、ViewPager使用细节,如何设置成每次只初始化当前的Fragment,其他的不初始化(提示:Fragment懒加载)?

我们经常在使用fragment时,常常会结合着viewpager使用,那么我们就会遇到一个问题,就是初始化fragment的时候,会连同我们写的网络请求一起执行,这样非常消耗性能,最理想的方式是,只有用户点开或滑动到当前fragment时,才进行请求网络的操作。因此,我们就产生了懒加载这样一个说法。

Viewpager配合fragment使用,默认加载前两个fragment。很容易造成网络丢包、阻塞等问题。

在Fragment中有一个setUserVisibleHint这个方法,而且这个方法是优于onCreate()方法的,它会通过isVisibleToUser告诉我们当前Fragment我们是否可见,我们可以在可见的时候再进行网络加载。

从log上看setUserVisibleHint()的调用早于onCreateView,所以如果在setUserVisibleHint()要实现懒加载的话,就必须要确保View以及其他变量都已经初始化结束,避免空指针。

使用步骤:

申明一个变量isPrepare=false,isVisible=false,标明当前页面是否被创建了
在onViewCreated周期内设置isPrepare=true
在setUserVisibleHint(boolean isVisible)判断是否显示,设置isVisible=true
判断isPrepare和isVisible,都为true开始加载数据,然后恢复isPrepare和isVisible为false,防止重复加载。

关于Android Fragment的懒加载,可以参考下面的链接:Fragment的懒加载https://blog.csdn.net/u011315960/article/details/71404177

35、Android为什么引入Parcelable?
可以肯定的是,两者都是支持序列化和反序列化的操作。
两者最大的区别在于 存储媒介的不同,Serializable 使用 I/O 读写存储在硬盘上,而 Parcelable 是直接 在内存中读写。很明显,内存的读写速度通常大于 IO 读写,所以在 Android 中传递数据优先选择 Parcelable。
Serializable 会使用反射,序列化和反序列化过程需要大量 I/O 操作, Parcelable 自已实现封送和解封(marshalled &unmarshalled)操作不需要用反射,数据也存放在 Native 内存中,效率要快很多。

36、有没有尝试简化Parcelable的使用?

使用Parcelable插件(Android Parcelable code generator)进行实体类的序列化的实现。

37、Bitmap 使用时候注意什么?
1、要选择合适的图片规格(bitmap类型):

ALPHA_8   每个像素占用1byte内存        
ARGB_4444 每个像素占用2byte内存       
ARGB_8888 每个像素占用4byte内存(默认)      
RGB_565 每个像素占用2byte内存

2、降低采样率。BitmapFactory.Options 参数inSampleSize的使用,先把options.inJustDecodeBounds设为true,只是去读取图片的大小,在拿到图片的大小之后和要显示的大小做比较通过calculateInSampleSize()函数计算inSampleSize的具体值,得到值之后。options.inJustDecodeBounds设为false读图片资源。
3、复用内存。即,通过软引用(内存不够的时候才会回收掉),复用内存块,不需要再重新给这个bitmap申请一块新的内存,避免了一次内存的分配和回收,从而改善了运行效率。
4、使用recycle()方法及时回收内存。
5、压缩图片。

Bitmap内存优化https://www.jianshu.com/p/25f279b44bf1

39、多进程场景遇见过么?
1、在新的进程中,启动前台Service,播放音乐。
2、一个成熟的应用一定是多模块化的。首先多进程开发能为应用解决了OOM问题,因为Android对内存的限制是针对于进程的,所以,当我们需要加载大图之类的操作,可以在新的进程中去执行,避免主进程OOM。而且假如图片浏览进程打开了一个过大的图片,java heap 申请内存失败,该进程崩溃并不影响我主进程的使用。

40、Canvas.save()跟Canvas.restore()的调用时机
save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。
restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。
save和restore要配对使用(restore可以比save少,但不能多),如果restore调用次数比save多,会引发Error。save和restore操作执行的时机不同,就能造成绘制的图形不同。

42、编译期注解跟运行时注解
运行期注解(RunTime)利用反射去获取信息还是比较损耗性能的,对应@Retention(RetentionPolicy.RUNTIME)。
编译期(Compile time)注解,以及处理编译期注解的手段APT和Javapoet,对应@Retention(RetentionPolicy.CLASS)。
其中apt+javaPoet目前也是应用比较广泛,在一些大的开源库,如EventBus3.0+,页面路由 ARout、Dagger、Retrofit等均有使用的身影,注解不仅仅是通过反射一种方式来使用,也可以使用APT在编译期处理

44、强引用置为null,会不会被回收?
不会立即释放对象占用的内存。 如果对象的引用被置为null,只是断开了当前线程栈帧中对该对象的引用关系,而 垃圾收集器是运行在后台的线程,只有当用户线程运行到安全点(safe point)或者安全区域才会扫描对象引用关系,扫描到对象没有被引用则会标记对象,这时候仍然不会立即释放该对象内存,因为有些对象是可恢复的(在 finalize方法中恢复引用 )。只有确定了对象无法恢复引用的时候才会清除对象内存。

45、Bundle传递数据为什么需要序列化?
序列化,表示将一个对象转换成可存储或可传输的状态。序列化的原因基本三种情况:

1.永久性保存对象,保存对象的字节序列到本地文件中;

2.对象在网络中传递;

3.对象在IPC间传递。

46、广播传输的数据是否有限制,是多少,为什么要限制?
Intent在传递数据时是有大小限制的,大约限制在1MB之内,你用Intent传递数据,实际上走的是跨进程通信(IPC),跨进程通信需要把数据从内核copy到进程中,每一个进程有一个接收内核数据的缓冲区,默认是1M;如果一次传递的数据超过限制,就会出现异常。
不同厂商表现不一样有可能是厂商修改了此限制的大小,也可能同样的对象在不同的机器上大小不一样。
传递大数据,不应该用Intent;考虑使用ContentProvider或者直接匿名共享内存。简单情况下可以考虑分段传输。
47、是否了解硬件加速?
硬件加速就是运用GPU优秀的运算能力来加快渲染的速度,而通常的基于软件的绘制渲染模式是完全利用CPU来完成渲染。
1.硬件加速是从API 11引入,API 14之后才默认开启。对于标准的绘制操作和控件都是支持的,但是对于自定义View的时候或者一些特殊的绘制函数就需要考虑是否需要关闭硬件加速。
2.我们面对不支持硬件加速的情况,就需要限制硬件加速,这个兼容性的问题是因为硬件加速是把View的绘制函数转化为使用OpenGL的函数来进完成实际的绘制的,那么必然会存在OpenGL中不支持原始回执函数的情况,对于这些绘制函数,就会失效。
3.硬件加速的消耗问题,因为是使用OpenGL,需要把系统中OpenGL加载到内存中,OpenGL API调用就会占用8MB,而实际上会占用更多内存,并且使用了硬件必然增加耗电量了。
4.硬件加速的优势还有display list的设计,使用这个我们不需要每次重绘都执行大量的代码,基于软件的绘制模式会重绘脏区域内的所有控件,而display只会更新列表,然后绘制列表内的控件。

CPU更擅长复杂逻辑控制,而GPU得益于大量ALU和并行结构设计,更擅长数学运算。

48、ContentProvider的权限管理(读写分离,权限控制-精确到表级,URL控制)。

49、Fragment状态保存
Fragment状态保存入口:
1、Activity的状态保存, 在Activity的onSaveInstanceState()里, 调用了FragmentManger的saveAllState()方法, 其中会对mActive中各个Fragment的实例状态和View状态分别进行保存.
2、FragmentManager还提供了public方法: saveFragmentInstanceState(), 可以对单个Fragment进行状态保存, 这是提供给我们用的。
3、FragmentManager的moveToState()方法中, 当状态回退到ACTIVITY_CREATED, 会调用saveFragmentViewState()方法, 保存View的状态.

https://www.cnblogs.com/mengdd/p/5582244.html

50、直接在Activity中创建一个thread跟在service中创建一个thread之间的区别?
在Activity中被创建:该Thread的就是为这个Activity服务的,完成这个特定的Activity交代的任务,主动通知该Activity一些消息和事件,Activity销毁后,该Thread也没有存活的意义了。
在Service中被创建:这是保证最长生命周期的Thread的唯一方式,只要整个Service不退出,Thread就可以一直在后台执行,一般在Service的onCreate()中创建,在onDestroy()中销毁。所以,在Service中创建的Thread,适合长期执行一些独立于APP的后台任务,比较常见的就是:在Service中保持与服务器端的长连接。

51、如何计算一个Bitmap占用内存的大小,怎么保证加载Bitmap不产生内存溢出?
Bitamp 占用内存大小 = 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存
复制代码
注:这里inDensity表示目标图片的dpi(放在哪个资源文件夹下),inTargetDensity表示目标屏幕的dpi,所以你可以发现inDensity和inTargetDensity会对Bitmap的宽高进行拉伸,进而改变Bitmap占用内存的大小。
在Bitmap里有两个获取内存占用大小的方法。
getByteCount():API12 加入,代表存储 Bitmap 的像素需要的最少内存。
getAllocationByteCount():API19 加入,代表在内存中为 Bitmap 分配的内存大小,代替了 getByteCount() 方法。
在不复用 Bitmap 时,getByteCount() 和 getAllocationByteCount 返回的结果是一样的。在通过复用 Bitmap 来解码图片时,那么 getByteCount() 表示新解码图片占用内存的大 小,getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小(即 mBuffer 的长度)。
为了保证在加载Bitmap的时候不产生内存溢出,可以使用BitmapFactory进行图片压缩,主要有以下几个参数:
BitmapFactory.Options.inPreferredConfig:将ARGB_8888改为RGB_565,改变编码方式,节约内存。
BitmapFactory.Options.inSampleSize:缩放比例,可以参考Luban那个库,根据图片宽高计算出合适的缩放比例。
BitmapFactory.Options.inPurgeable:让系统可以内存不足时回收内存。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,513评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,312评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,124评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,529评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,937评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,913评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,084评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,816评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,593评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,788评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,267评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,601评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,265评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,158评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,953评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,066评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,852评论 2 277

推荐阅读更多精彩内容