Handler
- 谈谈消息机制Handler作用 ?有哪些要素 ?流程是怎样的 ?
- 一个线程能否创建多个Handler,Handler跟Looper之间的对应关系 ?
- Handler 引起的内存泄露原因以及最佳解决方案
- 软引用跟弱引用的区别
- 、为什么系统不建议在子线程访问UI?
- Looper死循环为什么不会导致应用卡死?
- 使用Handler的postDealy后消息队列会有什么变化?
- 可以在子线程直接new一个Handler吗?怎么做?
- Message可以如何创建?哪种效果更好,为什么?
- Looper能创建多个实例嘛?能自己创建Looper实例嘛?
- 在子线程创建的handler能与主线程通信嘛?如果能怎么实现。
- handler,asyncTask有什么区别?
线程
- 线程池的好处? 四种线程池的使用场景,线程池的几个参数的理解?
- Android中还了解哪些方便线程切换的类?
- 讲讲AsyncTask的原理
- IntentService有什么用 ?
- 直接在Activity中创建一个thread跟在service中创建一个thread之间的区别
- ThreadPoolExecutor的工作策略 ?
- Handler、Thread和HandlerThread的差别?
- ThreadLocal的原理
- 多线程是否一定会高效(优缺点)
- 多线程中,让你做一个单例,你会怎么做
- 除了notify还有什么方式可以唤醒线程
- 什么是ANR ? 什么情况会出现ANR ?如何避免 ? 在不看代码的情况下如何快速定位出现ANR问题所在 ?
- 可重入锁的实现,公平锁非公平锁都是什么定义?
- 说说Android中线程池的实现
- 进程线程在操作系统中的实现
- 安卓线程间通信有哪几种方式
- 能在子线程创建handler嘛?有什么要注意的吗?
- 说一下为什么要用线程池?线程池的几个参数,以及它是怎么工作的?核心线程数一般有多少?
- Android多线程的实现方式有哪些?
- Android开发中何时使用多进程?使用多进程的好处是什么?
数据结构与算法
- 都用过那些常用的数据结构,说说对树的了解?
- 快排写一下,动态规划了解吗?
- 冒泡排序的链表实现
- HashMap如果Hash冲突了怎么解决?
- 双线程通过线程同步的方式打印12121212…….
- 快排 堆排 选择排序
- 二叉树排序方式
- 二分查找(手写)
- 10大排序算法
Bitmap
- Bitmap使用需要注意哪些问题 ?
- Bitmap.recycle()会立即回收么?什么时候会回收?如果没有地方使用这个Bitmap,为什么垃圾回收不会直接回收?
- 一张Bitmap所占内存以及内存占用的计算
- Android中缓存更新策略 ?
- LRU的原理 ?
性能优化
- 图片的三级缓存中,图片加载到内存中,如果内存快爆了,会发生什么?怎么处理?
- 内存中如果加载一张500*500的png高清图片.应该是占用多少的内存?
- WebView的性能优化 ?
- Bitmap如何处理大图,如一张30M的大图,如何预防OOM?
- 内存回收机制与GC算法(各种算法的优缺点以及应用场景);GC原理时机以及GC对象
- 内存泄露和内存溢出的区别 ?AS有什么工具可以检测内存泄露?
- 性能优化,怎么保证应用启动不卡顿? 黑白屏怎么处理?
- 强引用置为null,会不会被回收?
- ListView跟RecyclerView的区别?
- ListView的adapter是什么adapter?
- LinearLayout、FrameLayout、RelativeLayout性能对比,为什么?
- Android UI优化
- Android启动优化
- 屏幕适配方式
- apk瘦身技巧
- webp使用的注意事项
- 要做一个尽可能流畅的ListView,你平时在工作中如何进行优化的?
- Android下解决滑动冲突的常见思路是什么?
- 内存泄露检测有什么好方法?
设计模式
- 你所知道的设计模式有哪些?
- 谈谈MVC、MVP和MVVM,好在哪里,不好在哪里 ?
- 封装p层之后.如果p层数据过大,如何解决?
- 是否能从Android中举几个例子说说用到了什么设计模式 ?
- 装饰模式和代理模式有哪些区别 ?
- 实现单例模式有几种方法 ?懒汉式中双层锁的目的是什么 ?两次判空的目的又是什么 ?
- 用到的一些开源框架,介绍一个看过源码的,内部实现过程。
- Fragment如果在Adapter中使用应该如何解耦?
- 是否了解责任链模式?
- 说说你对设计模式的理解,开发过程中主要用到了哪些设计模式?
- 写个单例模式
Java
- 如何理解Java的多态?其中,重载和重写有什么区别?
- 谈一下JVM内存区域划分?哪部分是线程公有的,哪部分是私有的?
- final关键字的用法?
- 死锁是怎么导致的?如何定位死锁
- 数据库如何进行升级?SQLite增删改查的基础sql语句?
- Java内存模块分区和GC机制,GC算法有哪些
- HashMap的实现机制,怎么样HashMap线程安全
- Finalize机制
- 强引用 弱引用 软引用 虚引用的区别和使用场景
- 反射能反射私有方法以及静态方法嘛?
Broadcast
- Broadcast的分类?
- 广播中怎么进行网络请求
Activity
- Activity启动模式,allowReparent的特点和栈亲和性
- 异常生命周期
- 设备横竖屏切换的时候,接下来会发生什么?
- Activity A启动Activity B,这两个Activity生命周期变化顺序?
Service
- Service的两种启动模式?其生命周期各是什么?
- IntentService与普通Service的区别?
Android原理
- Android中的事件传递机制?
- ANR出现的情况有几种? 怎么分析解决ANR问题?
- 内存泄露的场景有哪些?内存泄漏分析工具使用方法?
- 如何实现启动优化,有什么工具可以使用?
- Android View绘制流程,当一个TextView的实例调用setText()方法后执行了什么
- Android dalvik虚拟机和Art虚拟机的优化升级点
- Android屏幕渲染机制
- 热修复的原理,你都了解过哪几种热修复框架
- OkHttp的原理
- Android 线程池的实现原理
- 从点击应用图标到进入应用,Android系统都做了哪些工作,期间涉及到的进程切换有哪些?
- Android事件传递流程和OnTouchListener的关系
- 双指缩放拖动大图
- RecyclerView绘制步骤和复用机制
- Activity遵循什么设计模式
- EventBus源码解析,遵循什么设计模式
- 系统的启动流程,从桌面点击图标开始。
- 自定义view的实现,以及注意事项
- MVC和MVP的区别,为什么要使用MVP?MVP有什么缺点嘛?
- 单例有哪几种?单例为什么要双重检查,优点? 那么双重检查就绝对是安全的嘛?
- 既然双重检查还不是绝对安全的,那么有没有办法完善呢?
- LRUCache原理
- Tinker热修复的原理
- 黄油刀(butterknife)实现原理
- rxjava是如何实现线程切换的
- 请介绍下AsyncTask的内部实现,适用的场景是?
- 如何把一个应用设置为系统应用?
进程间通信
- 说说你了解的IPC方法
- 说说Binder的大体实现
- 怎么控制另外一个进程的View显示
- Android中进程间通信有哪些实现方式?
网络
- HTTPS是怎么实现的?
- 客户端网络安全实现
- 对服务器众多错误码的处理(错误码有好几万个)
- HTTPS的组成是什么?
- tcp,udp的区别
- 为什么要三次握手
- tcp包过大怎么办?
- 网络传输你们是怎么加密的?
实际问题
- Android应用保活
- RemoteViews实现和使用场景
- LeakCanary的使用和实现原理
- 介绍一下你在开发过程中使用到的设计模式
- ClassLoader的双亲委托
- Android中的ClassLoader
- 各大图片框架之间的区别,如果让你自己实现,怎么实现?
- kotlin有什么优点,或者说你在使用它之前做了什么考虑?
- 如何实现一个bug统计框架(如bugly,友盟)
- 混淆的注意事项(反射不能混淆等),第三方框架能混淆嘛?
- 断点续传实现原理。怎么从断点处继续下载?下载完怎么确保文件是正确的?
基础
- 安卓的动画有哪几类,有什么区别
- 多个进程,会创建几个application实例?
- anr怎么定位
1.跨进程通信的几种方式
Intent,比如拨打电话
ContentProvider数据库存储数据
Broadcast广播通信
AIDL通信,通过接口共享数据
2.wait和sleep 的区别
wait是Object的方法,wait是对象锁,锁定方法不让继续执行,当执行notify方法后就会继续执行,sellp是Thread的方法,sellp是使线程睡眠,让出cpu,结束后自动继续执行
3.String,StringBuffer,StringBuilder的区别
String不可改变对象,一旦创建就不能修改
String str="aaa";
str="bbb";
以上代码虽然改变了str,但是执行过程是回收str,把值赋给一个新的str
StringBuffer创建之后,可以去修改
StringBuilder也可修改,执行效率高于StringBuffer,不安全
当字符赋值少使用String
字符赋值频繁使用StringBuilder
当多个线程同步操作数据,使用StringBuffer
4.View和SurfaceView的区别
View基于主线程刷新UI,SurfaceView子线程又可以刷新UI
5.View的绘制原理
View为所有图形控件的基类,View的绘制由3个函数完成
measure,计算视图的大小
layout,提供视图要显示的位置
draw,绘制
6.简述JNI
是java和c语言之间的桥梁,由于java是一种半解释语言,可以被反编译出来,一种重要涉及安全的代码就使用了C编程,再者很多底层功能调用C语言都实现了Java没必要重复造轮子,所以定义了JNI接口的实现
7.简述TCP,UDP,Socket
TCP是经过3次握手,4次挥手完成一串数据的传送
UDP是无连接的,知道IP地址和端口号,向其发送数据即可,不管数据是否发送成功
Socket是一种不同计算机,实时连接,比如说传送文件,即时通讯
8.音视频相关类
总体来说,分为几个类
视频录制方面,Camear摄像头录制视频类,MediaProjection屏幕录制视频类
编码方面,MediaCodec,MediaRecorder
预览方面,SurfaceView,GLSurfaceView,TextureView,VideoView
9.进程和线程的区别
概念:进程包括多个线程,一个程序一个进程,多线程的优点可以提高执行效率,提高资源利用率
创建:Thread类和Runnable接口,
常用方法有:
start()用于启动线程
run()调用线程对象中的run方法
join()合并插队到当前线程
sellp()睡眠释放cpu资源
setPriority()设置线程优先级
10.内存泄露如何查看和解决
概念:有些对象只有有限的生命周期,当他们的任务完成之后,它们将被垃圾回收,如果在对象的生命周期本该结束的时候,这个对象还被一系列的引用,着就会导致内存泄露。
解决方法:使用开源框架LeakCanary检测针对性解决
常见的内存泄露有:
单例造成的内存泄露,例如单例中的Context生命周期大于本身Context生命周期
线程使用Hander造成的内存卸扣,当activity已经结束,线程依然在运行更新UI
非静态类使用静态变量导致无法回收释放造成泄露
WebView网页过多造成内存泄露
资源未关闭造成泄露,例如数据库使用完之后关闭连接
11.View的分发机制,滑动冲突
View的事件传递顺序有3个重要的方法,dispatchTouchEvent()是否消耗了本次事件,onInterceptTouchEvent()是否拦截了本次事件,onTouchEvent()是否处理本次事件,滑动冲突分为同方向滑动冲突,例如ScrollView和ListView,同方向滑动冲突,可以计算ListView高度而动态设置ListView的高度,ScrollView高度可变。例如ViewPager和ListView,不同方向滑动冲突,一个是横向滑动一个是竖直滑动,不同方向滑动可以判断滑动的x,y轴是横向还是竖直滑动,如果判断得到是横向滑动,就拦截ListView的事件,竖则反之。
12.RecyclerView和ListView的区别
缓存上:前者缓存的是View+ViewHolder+flag,不用每次调用findViewById,后者则只是缓存View
刷新数据方面,前者提供了局部刷新,后者则全部刷新
13.recyclerView嵌套卡顿解决如何解决
设置预加载的数量LinearLayoutManager.setInitialPrefetchItemCount(4),默认是预加载2个,
设置子项缓存,
设置自带滑动冲突解决属性rv.setHasFixedSize(true); rv.setNestedScrollingEnabled(false);
可以完美解决,不过Google不推荐RecyClerView嵌套使用,需要嵌套尽量找类似于ExpandableListView 第三方控件来解决
14,谈MVC ,MVP,MVVM
MVC:View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些 业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,及View。所以,在MVC模型里,Model不依赖于View,但是 View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。
MVP:MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。
MVVM:数据双向绑定,通过数据驱动UI,M提供数据,V视图,VM即数据驱动层
15.dagger2
Dagger2是一个主要用于依赖注入的框架,减少初始化对象操作,降低耦合度
16Android性能优化
布局优化: 减少布局层级,使用ViewStub提高显示速度,布局服用,尽可能少使用warp_content,删除空间中无用的属性,避免过度绘制移除window默认背景,按需显示展位图,自定义View优化,使用canvas.clipRect()识别可见区域
启动速度:采用分布加载,异步加载,延期加载提高应用初始化速度,采用线程初始化数据等,合理的刷新机制
内存方面:防止内存泄露,使用一些第三方工具检测解决
代码优化:遵循Java生命周期
安装包优化:删除无用资源,优化图片,代码混淆,避免重复库存在,插件化
17.Hander原理
Handler,loop轮询检测发送消息到MessagerQuery,MessageQuery对Message入列,Handler回调方法处理消息,重写handMessage方法刷新ui
18.SharedPreference跨进程使用会怎么样?如何保证跨进程使用安全?
在两个应用的manifest配置中好相同的shartdUserId属性,A应用正常保存数据,B应用
createPackageContext("com.netease.nim.demo", CONTEXT_IGNORE_SECURITY)
获取context然后获取应用数据,为保证数据安全,使用加密存储
19.推送到达率如何提高
判手机系统,小米使用小米推送,华为使用华为推送,其他手机使用友盟推送
20.activity,fragment传值问题
通过Bundle传值,在activty定义变量传值,扩展fragment创建传值
21.activity与fragment区别
生命周期:
fragment从创建倒销毁整个生命周期依次为onAttach()→onCreate()→onCreateView()→onActivityCreated()→onStart()→onResume()→onPause()→onStop()→onDestroyView()→onDestroy()→onDetach()
与activity不同的方法有
onAttach():当Fragment和Activity建立关联的时候调用;
onCreateView():当Fragment创建视图调用;
onActivityCreated:与Fragment相关联的Activity完成onCreate()之后调用;
onDestoryView():在Fragment中的布局被移除时调用;
onDetach():当Fragment和Activity解除关联时调用;
activity常用的生命周期只有以下几个;
onCreate(): 表示 Activity 正在被创建,常用来 初始化工作,比如调用 setContentView 加载界面布局资源,初始化 Activity 所需数据等;
onRestart():表示 Activity 正在重新启动,一般情况下,当前Acitivty 从不可见重新变为可见时,OnRestart就会被调用;
onStart(): 表示 Activity 正在被启动,此时 Activity 可见但不在前台,还处于后台,无法与用户交互;
onResume(): 表示 Activity 获得焦点,此时 Activity 可见且在前台并开始活动,这是与 onStart 的区别所在;
onPause(): 表示 Activity 正在停止,此时可做一些 存储数据、停止动画等工作,但是不能太耗时,因为这会影响到新 Activity的显示,onPause 必须先执行完,新 Activity 的 onResume 才会执行;
onStop(): 表示 Activity 即将停止,可以做一些稍微重量级的回收工作,比如注销广播接收器、关闭网络连接等,同样不能太耗时;
onDestroy(): 表示 Activity 即将被销毁,这是 Activity 生命周期中的最后一个回调,常做 回收工作、资源释放;
区别:
Fragment比Activity多出四个回调周期,控制操作上更灵活;
Fragment可以在xml文件中直接写入,也可以在Activity中动态添加;
Fragment可以使用show()/hide()或者replace()对Fragment进行切换,切换的时候不会出现明显的效果,Activity切换的时候会有明显的翻页或其他效果;
22.Fragment中add与replace的区别?
add不会重新初始化fragment,replace每次都会;
添加相同的fragment时,replace不会有任何变化,add会报IllegalStateException 异常;
replace 先 remove 掉相同 id 的所有 fragment,然后在add 当前的这个 fragment,而 add 是覆盖前一个fragment。所以如果使用 add 一般会伴随 hide()和show(),避免布局重叠;
使用 add,如果应用放在后台,或以其他方式被系统销毁,再打开时,hide()中引用的 fragment 会销毁,所以依然会出现布局重叠 bug,可以使用 replace 或使用 add时,添加一个 tag 参数;
23.FragmentPagerAdapter 与 与 FragmentStatePagerAdapter 的区别与使用场景?
FragmentPagerAdapter 的每个 Fragment 会持久的保存在 FragmentManager 中,只要用户可以返回到页面中,它都不会被销毁。因此适用于那些数据 相对静态的页,Fragment 数量也比较少的那种;FragmentStatePagerAdapter 只保留当前页面,当页面不可见时,该 Fragment 就会被消除,释放其资源。因此适用于那些 数据动态性较大、 占用内存较多,多 Fragment 的情况;
24.说下Activity 的四种启动模式、应用场景 ?
standard 标准模式: 每次启动一个 Activity 都会重新创建一个新的实例,不管这个实例是否已经存在,此模式的 Activity 默认会进入启动它的 Activity 所属的任务栈中;
singleTop 栈顶复用模式: 如果新 Activity 已经位于任务栈的栈顶,那么此 Activity 不会被重新创建,同时会回调 onNewIntent方法,如果新 Activity 实例已经存在但不在栈顶,那么Activity 依然会被重新创建;
singleTask 栈内复用模式: 只要 Activity 在一个任务栈中存在,那么多次启动此 Activity 都不会重新创建实例,并回调onNewIntent 方法,此模式启动 Activity A,系统首先会寻找是否存在 A 想要的任务栈,如果不存在,就会重新创建一个任务栈,然后把创建好 A 的实例放到栈中;
singleInstance单实例模式: 这是一种加强的 singleTask 模式,具有此种模式的 Activity 只能单独地位于一个任务栈中,且此任务栈中只有唯一一个实例;
25.说下 Activity 跟 跟 window , view 之间的关系?
Activity 创建时通过 attach()初始化了一个 Window 也就是PhoneWindow,一个 PhoneWindow 持有一个DecorView 的实例,DecorView 本身是一个 FrameLayout,继承于 View,Activty 通过setContentView 将xml 布局控件不断 addView()添加到 View 中,最终显示到 Window 于我们交互;
26.横竖屏切换的Activity 生命周期变化?
不设置 Activity 的 android:configChanges 时,切屏会销毁当前Activity,然后重新加载调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次;onPause()→onStop()→onDestory()→onCreate()→onStart()→onResume()
设置 Activity 的 android:configChanges=" orientation",经过机型测试
在 Android5.1 即 即 API 3 23 级别下,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
在 Android9 即 即 API 8 28 级别下,切屏不会重新调用各个生命周期,只会执行 onConfigurationChanged方法
官方纠正后,原话如下
如果您的应用面向 Android 2 3.2 即 即 API 级别 3 13 或更
高级别(按照 minSdkVersion 和 targetSdkVersion)