https://blog.csdn.net/u014644594/article/details/112861591
Handler Thread Java
ThreadLocalMap的key是ThreadLocal的对象,value是独享数据。
ThreadLocal
ThreadLocal
67、ThreadLocal的原理
ThreadLocal
实现单个线程单例以及单个线程上下文信息存储,比如交易id等。
实现线程安全,非线程安全的对象使用ThreadLocal之后就会变得线程安全,因为每个线程都会有一个对应的实例。
ThreadLocal ThreadLocal
承载一些线程相关的数据,避免在方法中来回传递参数。
synchronized synchronized
synchronized
ThreadLocal可以让线程独占资源,存储于线程内部,避免线程堵塞造成CPU吞吐下降。
synchronized
synchronized()
ThreadLocal可以让线程独占资源,存储于线程内部,避免线程堵塞造成CPU吞吐下降。
ThreadLocal
在每个Thread中包含一个ThreadLocalMap,ThreadLocalMap的key是ThreadLocal的对象,value是独享数据。
value=是独享数据。 key = ThreadLocal
68、计算一个view的嵌套层级
Model
getParents ViewParents view
ViewParents
view.getParents()
69、MVP,MVVM,MVC解释和实践
MVC View Controller 控制层
MVC中Android的控制层是由Activity来承担的,
MVC中Android的控制层是由Activity来承担的, Android
Activity MVC
模型层(Model)
具有一定的分层,model彻底解耦,controller和view并没有解耦
model彻底解耦,controller和view并没有解耦
controller和view在android中无法做到彻底分离,但在代码逻辑层面一定要分清
view
MVP
通过引入接口BaseView,让相应的视图组件如Activity,Fragment去实现BaseView,实现了视图层的
MVP BaseView
BaseView
//
MVVM
MVP中我们说过随着业务逻辑的增加,UI的改变多的情况下,会有非常多的跟UI相关的case,
这样就会造成View的接口会很庞大
通过双向绑定的机制
MVVM与DataBinding的关系?
MVVM DataBinding去实现MVVM。
DataBinding去实现MVVM。
用MVVM的话可以考虑使用官方的架构组件ViewModel、LiveData、DataBinding去实现MVVM。
ViewModel LiveData、DataBinding去实现MVVM。
ViewModel LiveData、DataBinding去实现MVVM。
可以考虑使用官方的架构组件ViewModel、LiveData、DataBinding去实现MVVM。
SharedPrefrences的apply和commit有什么区别?
apply方法不会提示任何失败的提示。(commit)
apply() commit
https://blog.csdn.net/u014644594/article/details/112861591
apply
apply commit
sharedPreference
71、Base64、MD5是加密方法么?
Base64、MD5是加密方法么? 45
Base64是用文本表示二进制的编码方式,它使用4个字节的文本来表示3个字节的原始二进制数据。
它将二进制数据转换成一个由64个可打印的字符组成的序列:A-Za-z0-9+/
Base64 64
Base64 MD5
Base64是用文本表示二进制的编码方式,它使用4个字节的文本来表示3个字节的原始二进制数据。
它将二进制数据转换成一个由64个可打印的字符组成的序列:A-Za-z0-9+/
Base64 MD5
67md5 md5 128位(16字节)
Base64也不是加密算法,它是一种数据编码方式
MD5 MD5
72、HttpClient和HttpConnection的区别?
HttpClient和HttpConnection的区别?
。(并在Android 6.0中抛弃了Http Client,替换成OkHttp)
Android 6.0 HttpClient和HttpConnection的区别? OkHttp
且在Android 4.0中增加了response cache
response cache
response cache response cache HttpResponseCache的install()方法
HttpResponseCache的install install
HttpResponseCache的install install
304 Not Modified Not Modified
HttpURLConnection
ActivityA跳转ActivityB然后B按back返回A,各自的生命周期顺序,A与B均不透明。
Activity A:onPause
Activity B:onCreate
Activity B:onStart
Activity B:onResume
Activity A:onStop
Activity B:onPause
Activity A:onRestart
Activity A:onStart
Activity A:onResume
Activity B:onStop
Activity B:onDestroy
onPause
74、如何通过广播拦截和abort一条短信?
abort abort
75、BroadcastReceiver,LocalBroadcastReceiver 区别?
BroadcastReceiver LocalBroadcastManager
LocalBroadcastManager LocalBroadcastManager
1) 与BroadcastReceiver是以 Binder 通讯方式为底层实现的机制不同,LocalBroadcastManager 的核心实现实际还是 Handler,
只是利用到了 IntentFilter 的 match 功能,
IntentFilter match
IntentFilter match
https://blog.csdn.net/u014644594/article/details/112861591
(1) 与BroadcastReceiver是以 Binder 通讯方式为底层实现的机制不同,
LocalBroadcastManager 的核心实现实际还是 Handler,只是利用到了 IntentFilter 的 match 功能,至于 BroadcastReceiver 换成其他接口也无所谓,顺便利用了现成的类和概念而已。
背景,该开源库由谁推出,由哪个公司推出来的。
77、简单说下接入支付的流程,是否自己接入过支付功能?
Alipay支付功能:
2.签约成功后,需要配置秘钥。使用支付宝提供的工具生成RSA公钥和私钥,公钥需要设置到管理后台。
Alipay支付功能:
RSA RSA
apply
78、单例实现线程的同步的要求:
copy jar包;
https://blog.csdn.net/liboxiu/article/details/99933392
Wiegand(韦根)--26bit数据格式
79、如何保证Service不被杀死?
Android 进程不死从3个层面入手:
方法二:启动前台service。
方法三:提升service优先级:
在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"
intent-filter可以通过android:priority = "1000"
onDestroy方法里重启service:service + broadcast 方式,就是当service走ondestory的时
onDestroy service service + broadcast
service + broadcast onDestroy
A/B test
接入腾讯信鸽或极光推送与小米推送做 A/B Test。
80、说说ContentProvider、ContentResolver、ContentObserver 之间的关系?
ContentProvider:管理数据,提供数据的增删改查操作,数据源可以是数据库、文件、XML、网络等,ContentProvider为这些数据的访问提供了统一的接口,可以用来做进程间数据共享。
ContentResolver、ContentObserver
ContentProvider:管理数据,提供数据的增删改查操作,数据源可以是数据库、文件、XML、网络等,ContentProvider为这些数据的访问提供了统一的接口,可以用来做进程间数据共享。
ContentResolver、ContentObserver ContentObserver:观察ContentProvider中的数据变化,并将变化通知给外界。
81、如何导入外部数据库?
把原数据库包括在项目源码的 res/raw。
res/raw。
android系统下数据库应该存放在 /data/data/com.(package name)/ 目录下,
/data/data/com .(package name)/)
FileInputStream FileInputStream FileOutputStream
FileOutputStream
82、LinearLayout、FrameLayout、RelativeLayout性能对比,为什么?
LinearLayout, FrameLayout、RelativeLayout性能对比,为什么?
RelativeLayout性能对比,为什么?
LinearLayout、FrameLayout、RelativeLayout性能对比,为什么?
RelativeLayout会让子View调用2次onMeasure,LinearLayout
2 onMeasure
为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout?
RelativeLayout会让子View调用2次onMeasure,LinearLayout
onMeasure
https://blog.csdn.net/u014644594/article/details/112861591
为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout?
RelativeLayout会让子View调用2次onMeasure,LinearLayout
DecorView LinearLayout DecorView
因为复杂的View嵌套对性能的影响会更大一些。
ViewModel 83、scheme跳转协议
scheme跳转协议()
84、HandlerThread
1、HandlerThread原理
HandlerThread
创建HandlerThread后必须先调用HandlerThread.start()方法
创建HandlerThread后必须先调用HandlerThread.start()方法
它在Android中的一个具体的使用场景是IntentService
IntentService quit quitSafely
quitSafely
HandlerThread优点是异步不会堵塞,减少对性能的消耗。
HandlerThread与线程池不同,
HandlerThread是一个串队列,背后只有一个线程。
85、IntentService
IntentService是一种特殊的Service,它继承了Service并且它是一个抽象类,
因此必须创建它的子类才能使用IntentService。
IntentService
,onCreat()方法会创建一个HandlerThread,然后使用它的Looper来构造一个Handler对象mServiceHandler,
onCreat
生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至onStartCommand()方法的Intetnt。
onStartCommand
onHandleIntent((Intent)msg.obj);
onHandleIntent msg.obj
onHandleIntent
86、如何将一个Activity设置成窗口的样式。
android:theme="@android:style/Theme.Dialog"
theme android:theme = @android:style/Theme.Dialog
android:theme="@android:style/Theme.Translucnt"
Translucnt
Intent intent = callIntent
Intent callIntent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
startActivity(callIntent);
2:Content Provider 如访问系统相册
3:广播(Broadcast) 如显示系统时间
4:AIDL服务 AIDL服务 BroadcastReceiver
88、显示Intent与隐式Intent的区别
显示Intent与隐式Intent的区别 Intent
对于隐式意图,在定义Activity时,指定一个intent-filter,当一个隐式意图对象被一个意图过滤器进行匹配时,将有三个方面会被参考到:
intent-filter可以通过android
动作(Action)
类别(Category ['kætɪg(ə)rɪ] )
数据(Data )
ANR
Android BroadCastReceiver是10秒,Service是20秒(均为前台)。
ANR
Android BroadCastReceiver是10秒,Service是20秒(均为前台)。
data/anr/traces.txt即可,最新的ANR信息在最开始部分。
android -android-android
https://www.it610.com/article/1344194310530215936.htm
Thread.34.sleep
AsyncTask(AsynTask会一直执行,直到doInBackground)
、使用Handler处理工作线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。
4、Activity的onCreate和onResume回调中尽量避免耗时的代码。
BroadcastReceiver中onReceive代码也要尽量减少耗时,建议使用IntentService处理。
Activity onCreate onResume
BroadCastReceiver是10秒,Service是20秒(均为前台)。 onReceive
handler.sendMessage、runonUIThread、AsyncTask、RxJava等方式更新UI
runonUIThread、AsyncTask、RxJava等方式更新UI AsyncTask RxJava等方式更新UI
深入回答
2、Activity和Fragment生命周期有哪些?
Activity 和 Fragment
android:configChanges
android:configChanges=“orientation” keyboardHidden
onConfigurationChanges
4、AsyncTask的缺陷和问题,说说他的原理。
AsyncTask是什么?
AsyncTask
android
https://blog.csdn.net/u014644594/article/details/112861591
Params Process Result
ThreadPoolExecutor
AsyncTask 可以尝试自定义线程池,配合Asynctask使用。
ThreadPoolExecutor
AsyncTask里面线程池是一个核心线程数为CPU + 1,最大线程数为CPU * 2 + 1,
工作队列长度为128的线程池,线程等待队列的最大等待数为28,但是可以自定义线程池。线程池是由AsyncTask来处理的,线程池允许tasks并行运行,需要注意的是并发情况下数据的一致性问题,新数据可能会被老数据覆盖掉。所以希望tasks能够串行运行的话,使用SERIAL_EXECUTOR。
SERIAL_EXCUTOR tasks
从1.6开始,AsyncTask引入了线程池
每次只启动一个线程执行一个任务,完了之后再执行第二个任务,也就是相当于只有一个后台线程在执行所提交的任务。
doInBackground
onPostExecute(Result result)
onCancelled(Result result)
onPostExecute(Result result)
onPostExecute Result result
所以,我们是必须确保在销毁活动之前取消任务
2.内存泄漏
如果AsyncTask被声明为Activity的非静态内部类,那么AsyncTask会保留一个对Activity的引用。
AsyncTask
onPostExecute Result result
execute
executeOnExecutor
SerialExecutor用于排队,THREAD_POOL_EXECUTOR为真正的执行任务,Handler将工作线程切换到主线程),其必须在
ThreadPoolExecutor
onSaveInstanceState onRestoreInstanceState
onCreate Bunder传递对象为什么需要序列化?Serialzable和Parcelable的区别?
深入理解
6、android中进程的优先级?
1. 前台进程:
即与用户正在交互的Activity或者Activity用到的Service等,如果系统内存不足时前台进程是最晚被杀死的
2. 可见进程:
可以是处于暂停状态(onPause)的Activity或者绑定在其上的Service,即被用户可见,但由于失了焦点而不能与用户交互
3. 服务进程:
onPause startService onStop
7、Bunder传递对象为什么需要序列化?
Serialzable和Parcelable的区别?
SerialExecutor用于排队,THREAD_POOL_EXECUTOR为真正的执行任务,Handler将工作线程切换到主线程),其必须在
Serializable
Parcelable(android专用):
IPC(比如启动另一个进程的Activity、Service和Reciver)之间进行传输,也可以存储到本地。
Activity SerialExecutor用于排队,THREAD_POOL_EXECUTOR为真正的执行任务,Handler将工作线程切换到主线程),其必须在
Parcelable方式的实现原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这也就实现传递对象的功能了。
Parcelable(android专用):
tween View Rotate。tween
View
frame AnimationDrawable控制animation-list
Alpha Scale Translate Rotate。
frame 帧动画。AnimationDrawable控制animation-list.xml布局
PropertyAnimation 属性动画3.0引入,属性动画核心思想是对值的变化。
PropertyAnimation
evaluate
fraction
TypeEvaluator去计算运动中的属性值。
TimeInter
elapsed time/ duration
elapsed fragment
ValueAnimator
计算已完成动画分数 elapsed fraction。
elapsed fraction
计算插值(动画变化率)interpolated fraction
interpolated
interpolated fraction
interpolated
计算得到一个interpolated(插值)分数,在计算过程中,
已完成动画百分比会被加入到新的插值计算中。
计算属性值当插值分数计算完成后,Valu
两个概念:已完成动画分数(elapsed fraction)、插值分数( interpolated fraction )。
elapsed interpolated fraction
TypeEvaluator去计算运动中的属性值。
elapsed fraction interpolated fraction
TimeInterpolator interpolated
计算插值(动画变化率)interpolated fraction
TypeEvaluator去计算运动中的属性值。
1.属性动画:
插值器:作用是根据时间流逝的百分比来计算属性变化的百分比
AnimatonDrawable
AnimationDrawable控制animation-list
AnimationDrawable控制animation-list
repeatCount
repeatCount
为什么属性动画移动后仍可点击?
ViewGroup
9、Context相关
1、Activity和Service以及Application的Context是不一样的,Activity继承自ContextThemeWraper.其他的继承自ContextWrapper。
Activity Service Application
ContextImpl
ContextImpl
ContextThemeWraper
getApplication
BroadcastReceiver getApplicationContext Application
getApplicationContext Application
5、Context的数量等于Activity的个数 + Service的个数 +1,这个1为Application。
MaterialDesign
Dalvik JIT AOT AOT JIT
通知详情可以用户自己设计
Android6.0新特性
V2签名
Notification Channel
android::supportsPictureInPicture
Android9.0(P)新特性
室内WIFI定位
“刘海”屏幕支持
Q)目前曝光的新特性
Java Script
com.google.code
Gson
gson.fromJson int[].class
int [] ages=
int[].class
3、直接解析成List.
newTypeToke(){}.getType
List
轻量级的数据交换格式
读写更加容易
易于机器的解析和生成
DOM解析
XML中定义的几何形状
DOM解析器的API在使用上也相对比较简单
如果XML文档体积比较大时,将文档读入内存是非消耗系统资源的.
W3C XML中定义的几何形状 DOM解析
DOM 是以层次结构组织的节点的集合.
以层次结构
SAX解析
SAX 这种扩展能力得到了更好的体现.
Xmlpull解析 Stream dom
不会像dom那样要把所有节点以对象树的形式展现在内存中
xmlpull和sax类似
Jar Aar
Jar和Aar的区别 Android Library,我们可以直接引用
14、Android为每个应用程序分配的内存大小是多少
runonUIThread、AsyncTask、RxJava等方式更新UI
View.postDelay Handler AsynTask会一直执行,直到doInBackground
LiveData RxJava2
View.post Handler AsyncTask RxJava2 LiveData
ContentProvider使用方法。
getContentResolver
ContentProvider使用方法。
通过 Uri匹配进行数据的增删改查
17、Thread、AsyncTask、IntentService的使用场景与特点。
run
SerialExecutor用于排队,THREAD_POOL_EXECUTOR为真正的执行任务,Handler将工作线程切换到主线程),其必须在
Thread_POOL
IntentService的使用场景与特点。
onHandleIntent
onHandleIntent
Merge ViewStub
ViewStub
Merge
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ;
mContext.startActivity(intent);
setFlags FLAG_ACTIVITY_NEW_TASK
dialog.getWindow.setType
WindowManager.LayoutParams
TYPE_SYSTEM_ALERT
21、Asset目录与res目录的区别?
AssetManager
res/anim:存放动画资源。
res:会在 R 文件中生成 id 标记,
//
res/raw:和 asset
22、Android怎么加速启动Activity?
onCreate RxJava2 LiveData
AsyncTask Handler
dialog.getWindow.setType WindowManager.LayoutParams
.TYPE_SYSTEM_ALERT
res/raw:和 asset 会映射到 R 文件中
onCreate onResume
减少主线程阻塞时间。
Adapter AdapterView
优化布局文件。
ViewStub: 按需加载,减少内存使用量、加快渲染速度、不支持 merge 标签。
ViewStub TYPE_SYSTEM_ALERT
Adapter AdapterView
23、Handler机制 Handler
sendMessage、runonUIThread、AsyncTask、RxJava等方式更新UI
enqueueMessage
dispatchMessage
dispatchMessage
Target():Handler
Looper loop
Message Target Handler
Looper
MessageQueue loop
15万基金不动,
2月28号到期资金 做短期波段操作,因为每月月初会涨,月末会跌,中间为振荡期;
(每月必须)(月末最后一周的周五3点前) 买入(到期资金),
(每月最后期限)(月末倒数第二周的周五3点前) 卖出(到期资金),
MessageQueue Looper
MessageQueue:消息队列,负责消息的存储与管理
Handler Message
读取会自动删除消息,单链表维护,插入和删除上有优势。
next
Looper Looper:消息循环器 loop
Looper
Handler
Looper:消息循环器,负责关联线程以及消息的分发,
MessageQueue
loop->next
MessageQueue,调用loop()方法的时候消息循环开始,
其中会不断调用messageQueue的next()方法,
当有消息就处理,否则阻塞在messageQueue的next()方法中。
MessageQueue Message Handler
Looper.quit MessageQueue.quit
quit
handler:消息处理器,负责发送并处理消息
loop target handler
loop sendMessage、runonUIThread、AsyncTask、RxJava等方式更新UI
target handler handleMessage
MessageHandler
WeakMess
target handler
MessageQueue
Handler handleMessage
MessageQueue与Looper相关功能都通过MessageQueue的Native方法来完成,
Handler 发送的消息由 MessageQueue 存储管理,并由 Looper 负责回调消息到 handleMessage()。
线程的转换由 Looper 完成,handleMessage() 所在线程由 Looper.loop() 调用者所在线程决定。
Looper handleMessage Looper.loop
Handler 引起的内存泄露原因以及最佳解决方案
Activity
removeCallbacksAndMessages(null)
removeCallbacksAndMessages(null)
为什么我们能在主线程直接使用 Handler,而不需要创建 Looper ?
Handler Looper
handler.removeCallbacksAndMessages null
Looper.prepareMainLooper()
main
prepareMainLooper Callback Handler Hook
ActivityThread.mH ActivityThread.mH
主线程的 Looper 不允许退出
Callback(Handler)
Message.obtain() Dialog。Toast
妙用 Looper 机制
将 Runnable post 到主线程执行;
利用 Looper 判断当前线程是否是主线程
Runnable post Looper
Toast Handler DialogFragment
Runnable post
Looper Linux pipe/epoll机制
Linux pipe/epoll机制 MessageQueue
nativePoll epoll机制
handler postDelay
postDelay
所以说,主线程大多数时候都是处于休眠状态,并不会消耗大量CPU资源。hand
handler.postDelay MessageQueue
24、程序A能否接收到程序B的广播?
LocalBroadCastRecevier只限于本进程的广播间通信。
LocalBroadCastRecevier只限于本进程的广播间通信。
RecyclerView
26、通过google提供的Gson解析json时,定义JavaBean的规则是什么?
google javaBean Gson gson
Serializable
https://blog.csdn.net/u014644594/article/details/112861591
SDK提供JSONArray,JSONObject
FixThreadPool、CachedhreadPool、SingleThreadPool、ScheduleThreadExecutr.
FixThreadPool CachedThreadPool
ScheduledThreadExecutor
CachedThreadPool CachedThreadPool
SynchronousQuue CachedThreadPool
SynchronousQuue
ScheduledThreadPool
指定定时任务以及固定周期的重复任务
ScheduledThreadPool
29、内存泄露,怎样查找,怎么产生的内存泄露?
Cursor,File文件等
1.资源对象没关闭造成的内存泄漏
SQLiteCursor close null
Cursor,File文件等
2.构造Adapter时,没有使用缓存的convertView
context。这个context的生存周期和你的应用的生存周期一样长,而不是取决于activity的生存周期。如果你想保持一个长期生存的对象,并且这个对象需要一个context
Adapter
在BaseAdapter中提供了方法: public View getView(int position, ViewconvertView, ViewGroup parent) 来向ListView提供每一个item所需要的view对象。
ListView回收list BaseAdapter
。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的 view对象
list item item
getView
convertView
android.widget.AbsListView.java --> voidaddScrapView(View scrap)
AbsListView.java
voidaddScrapView()
view = convertView;
3.Bitmap对象不在使用时调用recycle()释放内存
4.试着使用关于application的context来替代和activity相关的context
这是一个很隐晦的内存泄漏的情况
Context.getApplicationContext() or Activity.getApplication()
Context.getApplicationContext Activity.
getApplication
5.注册没取消造成的内存泄漏
但是别的引用程序仍然还有对我们的Android程序的某个对象的引用
register unregister LockScreen
TelePhone TelePhone system_proces
6.集合中对象没清理造成的内存泄漏
查找内存泄漏可以使用Android Studio 自带的AndroidProfiler工具或MAT
Android
1、使用AndroidProfiler的MEMORY工具:And heap dumpsys
shell dumpsys meminfo .heap
hprof必须手动使用android-context。这个context的生存周期和你的应用的生存周期一样长,而不是取决于activity的生存周期。如果你想保持一个长期生存的对象,并且这个对象需要一个context
Histogram和Dominator Tree。
Dominator Thre Regex
Merge Shortest Paths to GC Root中的exclude all phantom/weak/soft etc.references
Merge shell Paths weak/soft etc.
Leakcanary
hprof必须手动使用android -conv
/weak/soft etc.references
weak/soft Regex Merge Shortest Parcelable
Root中的exclude all phantom/weak/soft etc.references选项来查看该类的GC强引用链。最后,通过引用链即可看到最终强引用该类的对象。
Histogram:直方图注重量的分析。使用方式与Dominator Tree类似。
Navigation History
查看引用关系或对象数量去进行分析即可。
hprof必须手动使用android
hprof必须手动使用android
navigation
ViewPager使用细节 ViewPager使用细节 Fragment
自定义一个 LazyLoadFragment 基类,利用 setUserVisibleHint 和 生命周期方法
LazyLoadFragment setUserVisibleHint requestData requestData
setUserVisibleHint requestData
setUserVisibleHint requestData isVisibleToUser
forceUpdate getUserVisibleHint
requestData();
isDataLoaded = true;
35、Android为什么引入Parcelable?
Serializable 使用 I/O 读写存储在硬盘上,而 Parcelable 是直接 在内存中读写
Serializable marshalled &unmarshalled
marshalled unmarshalled
marshalled unmarshalled
Android parent generator)进行实体类的序列化的实现。
使用Parcelable插件(Android Parcelable code generator)进行实体类的序列化的实现。
code generator)进行实体类的序列化的实现。
Bitmap 使用时候注意什么?
1、要选择合适的图片规格(bitmap类型):
ALPHA_8 每个像素占用1byte内存
ARGB_4444 每个像素占用2byte内存
ARGB_8888 每个像素占用4byte内存(默认)
RGB_565 每个像素占用2byte内存
bitmap 1byte
BitmapFactory.Options
//
BitmapFactory.Options inSampleSize
options.inJustDecodeBounds = true
inJustDecodeBounds = true
https://blog.csdn.net/u014644594/article/details/112861591
calculateSampleSize
2、降低采样率。
3、复用内存。即,通过软引用(内存不够的时候才会回收掉),复用内存块,
不需要再重新给这个bitmap申请一块新的内存,避免了一次内存的分配和回收,从而改善了运行效率。
bitmap
recycle bitmap
Java中管理内存除了显式地catch OOM之外还有更多有效的方法:
catch OOM之外还有更多有效的方法:
SoftReference WeakReference 硬盘缓存等。
在JVM用光内存之前,会多次触发GC,这些GC会降低程序运行的效率。
JVM GC Service
java heap
Canvas.recycle Canvas.save
40、Canvas.save()跟Canvas.restore()的调用时机
java heap
save 平移 缩放 旋转、错切、裁剪等操作。
restore Canvas
restore ->save
save-> Canvas
如果restore调用次数比save多,会引发Error
save
41、数据库升级增加表和删除表都不涉及数据迁移,
但是修改表涉及到对原有数据进行迁移。升级的方法如下所示:
case DBService DBService
create
integer primarykey,text
alter table book rename to
db.beginTransaction();
db.execSQL(CREATE_TEMP_BOOK);
db.execSQL(CREATE_BOOK);
db.execSQL(INSERT_DATA);
db.execSQL(DROP_BOOK);
db.setTransactionSuccessful();
db.endTransaction();
db.execSQL DROP_BOOK
42、编译期注解跟运行时注解
RunTime
@Retention(RetentionPolicy.RUNTIME)。
编译期(Compile time)注解,以及处理编译期注解的手段APT和Javapoet,对应
Compile time APT和Javapoet
ALPHA_8 APT
如EventBus3.0+,页面路由 ARout、Dagger、Retrofit等均有使用的身影,注解不仅仅是通过反射一种方式来使用,也可以使用APT在编译期处理
43、bitmap recycler 相关
recycle
44、强引用置为null,会不会被回收?
bitmap recycler
而 垃圾收集器是运行在后台的线程,
bitmap
45、Bundle传递数据为什么需要序列化?
序列化,表示将一个对象转换成可存储或可传输的状态。序列化的原因基本三种情况:
Bundle传递数据为什么需要序列化?
1.永久性保存对象,保存对象的字节序列到本地文件中;
2.对象在网络中传递;
3.对象在IPC间传递。
1.永久性保存对象,保存对象的字节序列到本地文件中;
传递大数据,不应该用Intent;考虑使用ContentProvider或者直接匿名共享内存。简单情况下可以考虑分段传输。
ContentProvider的权限管理
ContentProvider的权限管理
47、是否了解硬件加速?
对于自定义View的时候或者一些特殊的绘制函数就需要考虑是否需要关闭硬件加速
View
硬件加速的优势还有display list的设计
display list
CPU更擅长复杂逻辑控制,而GPU得益于大量ALU和并行结构设计,更擅长数学运算。
display list
48、ContentProvider的权限管理(读写分离,权限控制-精确到表级,URL控制)。
ContentProvider的权限管理
View
ContentProvider的权限管理
ContentProvider的权限管理
可以在AndroidManifest.xml文件中对节点的属性进行配置
AndroidManifest.xiaomi
android:grantUriPermssions:临时许可标志。
android:permission:Provider读写权限。
android:readPermission:Provider的读权限。
android:writePermission:Provider的写权限。
android:enabled:标记允许系统启动Provider。
android:exported:标记允许其他应用程序使用这个Provider。
android:multiProcess:标记允许系统启动Provider相同的进程中调用客户端。
gradlew exported enabled = true
android:multiProcess multiProcess productFlavors
Provider的写权限。multi
49、Fragment状态保存
Fragmengt和Fragmengt怎么通信?
onSaveInstanceState
saveFragmentInstanceState
Activity onSaveInstanceState FragmentManager的moveToState
saveAllState
onSaveInstanceState
saveAllState
saveFragmentInstanceState
moveToState
34
moveToState Activity_CREate
FragmentManager的moveToState moveToState
saveFragmentViewState
50、直接在Activity中创建一个thread跟在service中创建一个thread之间的区别?
thread
在Activity中被创建
Service thread
,比较常见的就是:在Service中保持与服务器端的长连接。
51、如何计算一个Bitmap占用内存的大小,怎么保证加载Bitmap不产生内存溢出?
Bitamp Bitamp(34)
Bitamp 不产生内存溢出
Bitamp 占用内存大小 = 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存
inTargetDensity = 23
Bitamp 占用内存大小 = 宽度像素 x (inTargetDensity / inDensity) x 高度像素 x (inTargetDensity / inDensity)x 一个像素所占的内存
Bitamp = inTargetDensity / inDensity)
inDensity)
注:这里inDensity表示目标图片的dpi(放在哪个资源文件夹下),
inTargetDensity表示目标屏幕的dpi,所以你可以发现inDensity和inTargetDensity会对Bitmap的宽高进行拉伸,
进而改变Bitmap占用内存的大小。
在Bitmap里有两个获取内存占用大小的方法。
Bitamp
getByteCount/45
getAllocationByteCount
getByteCount():API12 加入,代表存储 Bitmap 的像素需要的最少内存。
getAllocationByteCount():API19 加入,代表在内存中为 Bitmap 分配的内存大小,
代替了 getByteCount() 方法。 在不复用 Bitmap 时,getByteCount() 和 getAllocationByteCount
返回的结果是一样的。在通过复用 Bitmap 来解码图片时,
那么 getByteCount() 表示新解码图片占用内存的大 小,
getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小(即 mBuffer 的长度)。
getAllocationByteCount / getByteCount
Bitamp mBuffer
getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小(即 mBuffer 的长度)。
getAllocationByteCount
56
BitmapFactory()=
不复用 bitmap时
getByteCount = getAllocationByteCount
复用 bitmap时,
,那么 getByteCount() 表示新解码图片占用内存的大小,
getAllocationByteCount() 表示被复用 Bitmap 真实占用的内存大小(即 mBuffer 的长度)。
mBuffer的长度
BitmapFactory
为了保证在加载Bitmap的时候不产生内存溢出,可以使用BitmapFactory进行图片压缩
BitmapFactory.Options.inPreferredConfig:将ARGB_8888改为RGB_565,改变编码方式,节约内存。
改变编码方式 缩放比例
BitmapFactory.Options.inPurgeable:让系统可以内存不足时回收内存。
inPurgeable:让系统可以内存不足时回收内存。
52、对于应用更新这块是如何做的?(灰度,强制更新,分区域更新)\
52、对于应用更新这块是如何做的?灰度 强制更新 分区域更新
1、通过接口获取线上版本号,versionCode 2、比较线上的versionCode 和本地的versionCode,
弹出更新窗口
3、下载APK文件(文件下载) 4、安装APK
versionCode
bsdiff:二进制差分工具bsdiff是相应的补丁合成工具
bspatch
灰度: (1)找单一渠道投放特别版本。 (2)做升级平台的改造,允许针对部分用户推送升级通知甚至版本强制升级。 (3)开放单独的下载入口。
测试框架负责与服务器端api通信
app 由服务器端控制app上A/B版本的分布
灰度:
灰度,数据监控(常规数据、新特性数据、主要业务数据)还是要做到位
45哪种方法都需要做好版本管理工作,分配特别的版本号以示区别。
34 app bsdiff:二进制差分工具bsdiff是相应的补丁合成工具
bspatch .patch文件。通过bspatch使旧的apk文件与不定文件合成新的apk。
53、请解释安卓为啥要加签名机制。
bsdiff:二进制差分工具bsdiff是相应的补丁合成工具
bspatch
53、请解释安卓为啥要加签名机制。
Package Name Package Name
1、发送者的身份认证 由于开发商可能通过使用相同的 Package Name 来混淆替换已经安装的程序,
以此保证签名不同的包不被替换。
2、保证信息传输的完整性 签名对于包中的每个文件进行处理,以此确保包中内容不被替换778
3、防止交易中的抵赖发生, Market 对56的要求。Mar
Market
54、为什么bindService可以跟Activity生命周期联动?
bindService = Activity bindService Activity
ServiceConnection
bindService LoadedApk ServiceConnection(56)
1、bindService 方法执行时,LoadedApk 会记录 ServiceConnection 信息。
BroadcastReceiver 和 Service,
BroadcastReceiver 45
55、如何通过Gradle配置多渠道包?
Gradle Gradle
android {
productFlavors {
xiaomi {}
baidu {}
wandoujia {}
_360 {} // 或“"360"{}”,数字需下划线开头或加上双引号
}
}
android {56
productFlavors
productFlavors
xiaomi baidu{}
}
执行./gradlew assembleRelease ,将会打出所有渠道的release包;
./gradlew assembleRelease
因此,可以结合buildType和productFlavor生成不同的Build Variants,即类型与渠道不同的组合。
buildType productFlavors Build Variants,即类型与渠道不同的组合。
Build Variants,即类型与渠道不同的组合45
56、activty和Fragmengt之间怎么通信,Fragmengt和Fragmengt怎么通信?
(一)Handler
(二)广播
(三)事件总线:EventBus、RxBus、Otto
(四)接口回调
(五)Bundle和setArguments(bundle)
Bundle和setArguments(bundle)
57、自定义view效率高于xml定义吗?说明理由。
自定义view效率高于xml定义:view
view xml文件中对节点的属性进行配置 view
ViewGroup View
ViewGroup View();
58、广播注册一般有几种,各有什么优缺点?
第一种是常驻型(静态注册):当应用程序关闭后如果有信息广播来,程序也会被系统调用,自己运行。
第二种不常驻(动态注册):广播会跟随程序的生命周期。
动态注册67
android
59、服务启动一般有几种,服务和activty之间怎么通信,服务和服务之间怎么通信
activty和Fragmengt之间怎么通信,Fragmengt和Fragmengt怎么通信?
onCreate-> onStartCommand(67)
。 开启者不能调用服务里面的方法。
onDestory()
2、bindService:
onCreate() —>onBind()—>onunbind()—>onDestory()
bindService onCreate onBind onunbind onDestory
通信:
1、通过Binder对象。
2、通过broadcast(广播)。
Binder broadcast
60、ddms 和 traceView 的区别?
Binder broadcast
ddms traceView
60、ddms 和 traceView 的区别?
线程和堆栈ddms traceView
Traceview Android
hotspot(瓶颈)。Traceview
startMethodTracing
stopMethodTracing()
/mnt/sdcard/下的一个文件中。
这两个函数运行过程中将采集运行时间内该应用所有线程(注意,只能是 Java线程)
的函数执行情况, 并将采集数据保存到/mnt/sdcard/下的一个文件中。
开发者然后需要利用 SDK 中的 Traceview工具来分析这些数据。
SDK Traceview() Traceview() SDK
/mnt/sdcard/下的一个文件中。
61、ListView卡顿原因
ListView卡顿原因()
Adapter56
notifySetDataChanged()
ListView卡顿原因
Adapter getView convertView setTag getTag
Adapter
getView convertView
在getView方法里面ViewHolder初始化后的赋值或者是多个控件的显示状态和背景的显示没有优化好,
抑或是里面含有复杂的计算和耗时操作;
getView ViewHolder
getView ViewHolder
inflate的row
Adapter多余或者不合理的notifySetDataChanged
Adapter notifySetDataChanged(45)
listview 被多层嵌套,多次的onMessure导致卡顿,如果多层嵌套无法避免
,建议把listview的高和宽设置为match_parent.
如果是代码继承的listview,那么也请你别忘记为你的继承类添加上
match_parent
listview onMeasure
LayoutPrams
LayoutPrams match_parent
45 67
LayoutPrams match_parent
62、AndroidManifest的作用与理解
AndroidManifest
https://blog.csdn.net/u014644594/article/details/112861591
getView inflate的row()
Adapter多余或者不合理的notifySetDataChanged;
Adapter notifySetDataChanged
listview onMeasure
AndroidManifest.xml文件中对节点的属性进行配置
AndroidManifest.xml文件,也叫清单文件,
来获知应用中是否包含该组件,
如果有会直接启动该组件。
可以理解是一个应用的配置文件。
描述应用的各个组件,包括构成应用的 Activity、服务、广播接收器和内容提供程序。
诺安成长混合
国投瑞银沪深300金融等基金
为应用的 Java 软件包命名。软件包名称充当应用的唯一标识符。
Activity Service46
contentProvider contentProvider
确定托管应用组件的进程。
声明应用必须具备哪些权限才能访问 API 中受保护的部分并与其他应用交互。
还声明其他应用与该应用组件交互所需具备的权限
确定托管应用组件的进程。
列出 Instrumentation类,这些类可在应用运行时提供分析和其他信息。
Instrumentation类,这些类可在应用运行时提供分析和其他信息。
声明应用所需的最低 Android API 级别
Android API
63、LaunchMode应用场景
列出应用必须链接到的库
声明应用所需的最低 Android API 级别
列出应用必须链接到的库
LaunchMode应用场景
standard,创建一个新的Activity。
singleTop适合接收通知启动的内容显示页面。
singleTop,栈顶不是该类型的Activity,创建一个新的Activity。否则,onNewIntent。
onNewIntent
standard,创建一个新的Activity。
singleTask singleTop适合接收通知启动的内容显示页面。
onNewIntent+ClearTop
onNewIntent ClearTop
affinity =
它在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的Task存在
affinity =Taskaffinity Task
如果我们想要设置了"singleTask"启动模式的Activity在新的任务中启动,
就要为它设置一个独立的taskAffinity属性值。
singleTask
, 如果我们想要设置了"singleTask"启动模式的Activity在新的任务中启动,
就要为它设置一个独立的taskAffinity属性值。
taskAffinity taskAffinity
singleInstance,回退栈中,只有这一个Activity,没有其他Activity。
singleInstance应用场景:()
singleTask
singleInstance应用场景:
说说Activity、Intent、Service 是什么关系
https://blog.csdn.net/u014644594/article/details/112861591
Context ContextWrapper
Activity Service
65、ApplicationContext和ActivityContext的区别
在使用context的时候,小心内存泄露,防止内存泄露,注意一下几个方面:
OKHttp请求流程
网络请求缓存处理
连接池
OkHttpClient Builder build()
RealCall enqueue execute Dispatcher
RetryAndFollowUpInterceptor RetryAndFollowUpInterceptor
getResponseWithInterceptorChain
getResponseWithInterceptorChain() = response
originalRequest->response adapter pool
如下为使用OKHttp进行Get请求的步骤:
OkHttp Get
getResponseWithInterceptorChain = response
originalRequest->response adapter pool
Request url method header
CallServerInterceptor()
url = method header body
ConnectInterceptor
Response
CacheInterceptor Cachehit
Cache miss
code message headers body
connectionSpecs // 传输层版本和连接协议
ConnectionSpec
@Nullable CertificateChainCleaner certificateChainCleaner;// 验证确认响应证书 适用 HTTPS 请求连接的主机名。
CertificateChainCleaner certificateChainCleaner;
@Nullable CertificateChainCleaner certificateChainCleaner;
HostnameVerifier hostnameVerifier;// 验证确认响应证书 适用 HTTPS 请求连接的主机名。
HostnameVerifier hostnameVerifier;
followRedirects() = followSslRedirects
@Nullable InternalCache internalCache;// 内部缓存
EventListener.Factory eventListenerFactory;
EventListener.Factory eventListenerFactory;
Authenticator
https://juejin.cn/post/6844903631909552135
followRedirects followRedirects
Dispatcher() Dispatcher
connectionSpecs = DEFAULT_CONNECTION_SPECS;
connectionSpecs
Response response = client.newCall(request).execute();
client.newCall request.execute
Response result = getResponseWithInterceptorChain();
interceptors.addAll client.interceptors
retryAndFollowUpInterceptor
retryAndFollowUpInterceptor
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(BridgeInterceptor client.cookieJar);
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add CacheInterceptor client.internalCache();
client.internalCache
client.internalCache
interceptors.addAll(client.networkInterceptors());
interceptors.addAll client.networkInterceptors();
// 使用责任链模式开启链式调用
return chain.proceed(originalRequest);
chain.proceed originalRequest
https://juejin.cn/post/6844903631909552135
RealInterceptorChain eventListener
//使用责任链模式开启链式调用
chain.proceed originalRequest
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
Response proceed
RealInterceptorChain Interceptor interceptors;.get index
eventListener
AA00110002
Deque <AsyncCall> readyAsyncCalls = new ArrayDeque<>();
readyAsyncCalls AsyncCall = new ArrayDeque
onFailure onResponse
Deque RealCall runningAsyncCalls
AsyncCall Deque<RealCall> runningSyncCalls
Deque RealCallRealCall
promoteAndExecute
readyAsyncCalls
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
runningCallsForHost asyncCall
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
asyncCall.executeOn
executorService
runningAsyncCalls
executableCalls.add asyncCall
runningAsyncCalls.add asyncCall
return originalRequest.url().host();
originalRequest
executorService
AsyncCall NamedRunnable
Callback responseCallback
client.dispatcher().finished(this); // This call is no longer running!
client.dispatcher.finished
signalledCallback = false
getResponseWithInterceptorChain
responseCallback.onResponse(RealCall.this, response);
responseCallback.onResponse RealCall.this, response
signalledCallback = true;
signalledCallback = true;
client.dispatcher().finished(this);
二、网络请求缓存处理之CacheInterceptor
CacheInterceptor
二、网络请求缓存处理之CacheInterceptor
cache.get chain.request
request->cache->response
Android 自定义UI-垂直方向的SeekBar
https://blog.csdn.net/wangjinyu501/article/details/20456761
strategy.networkRequest
strategy.cacheResponse
if (cache != null) {
cache.trackResponse(strategy);
}
cache.trackResponse strategy
closeQuietly cacheCandidate.body
closeQuietly();
https://juejin.cn/post/6844903631909552135
closeQuietly();
.body Util.EMPTY_RESPONSE
receivedResponseAtMillis System.currentTimeMillis
if (networkRequest == null) {
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse))
.build();
// 调用下一个拦截器,决定从网络上来得到response
networkResponse = chain.proceed(networkRequest);
networkResponse =
chain.proceed networkRequest
cacheResponse
CacheStrategy.isCacheable response,networkRequest
cacheWritingResponse
HttpMethod.invalidatesCache networkRequest,response
.cacheResponse stripBody cacheResponse
cache.trackConditionalCacheHit();
cache.update(cacheResponse, response);
cache.trackConditionalCacheHit
cache.update
trackConditionalCacheHit
.cacheResponse .networkResponse
cacheWritingResponse
HttpMethod.
invalidatesCache
if (HttpMethod.invalidatesCache(networkRequest.method())) {
HttpMethod.invalidatesCache
cache.remove(networkRequest);
缓存拦截器会根据请求的信息和缓存的响应的信息来判断是否存在缓存可用,
如果有可以使用的缓存,那么就返回该缓存给用户,
否则就继续使用责任链模式来从服务器中获取响应。当获取到响应的时候,又会把响应缓存到磁盘上面。
三、ConnectInterceptor之连接池
ConnectInterceptor
ConnectInterceptor
doExtensive
RealConnection connection = streamAllocation.connection
onCardResponse
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();
StreamAllocation streamAllocation = realChain
realChain.proceed request,streamAllocation,httpCodec,connectTimeout
45
调用 streamAllocation 的 newStream() 方法的时候,最终会经过一系列
pingInterval,
toClose
releaseIf
toClose
reportedAcquired
()
https://juejin.cn/post/6844903631909552135
if (foundPooledConnection) {
eventListener.connectionAcquired(call, result);
foundPooledConnection
synchronized (connectionPool) {
com.lzy.imagepicker
com.xys.libzxing
com.jeremyfeinstein.slidingmenu.lib
SlidingMenu_library
pingIntervalMillis,
result.connectionSpecs
connectionRetryEnabled,call,eventListener
connectionRetryEnabled
connection != null
foundPooledConnection = true
this.route = route;
call eventListener
connected result.route
routeDatabase().connected(result.route());
reportedAcquired = true;
connectionPool,result
// 如果同时创建了另一个到同一地址的多路复用连接,
释放这个连接并获取那个连接
if (result.isMultiplexed()) {
connectionPool,address,this
eventListener.connectionAcquired call, result
Internal.instance.get(
ConnectionPool,address);
ConnectionPool,address);
ConnectionPool.add();
result.isMultiplexed
socket =Internal.instance.deduplicate
result = connection;
Internal.instance.deduplicate
private final Deque<RealConnection> connections = new ArrayDeque<>();
Deque<RealConnection> connections =
RealConnection
assert(Thread.holdsLock(this)) {
}
com.bigkoo.pickerview_new
pickerview
https://juejin.cn/post/6844903631909552135
JsonChao 的 2020 年终总结 | 掘金年度征文
https://juejin.cn/post/6911091834219397134
https://juejin.cn/post/6844903972587716621--深入探索Android稳定性优化
signal信号
PM(Application Performance Manange)