Snackbar
https://www.jianshu.com/p/e023bfb6466b
**首先,与 Dialog不同,Toast 和 Snackbar 都不属于模态。**这意味这它们不获取当前屏幕焦点,用户依然可以操作屏幕中的其他内容,这也正是所谓的“轻量化信息和反馈”。当设计者不希望用户任务被打断时,使用它们比 Dialog 更轻量。
**其次,Toast 默认是展示在当前屏幕内所有控件之外,Snackbar 则是在控件的最顶层。**从我的角度来看,似乎 Snackbar 更像应用的一部分而 Toast 则更接近系统消息。这可能就是官方所谓的“Toast are primarily used for system messaging”。
实际效果上,Toast 不会改变已有控件的布局,而 Snackbar 常常把悬浮按钮往上推。
Activity和Fragment的对比分析
https://blog.csdn.net/weixin_34161064/article/details/91931505
ANDROIDAUTOSIZE今日头条适配方案
https://www.freesion.com/article/1120735383/
DSBridge vs WebViewJavascriptBridge
https://www.jianshu.com/p/d967b0d85b97
通过各方面对比,DSBridge几乎完爆WebViewJavascriptBridge,当然,由于WebViewJavascriptBridge诞生的年代比较早,到现在积累的用户非常多(事实上是世界上目前使用最多的),但是时间在流逝,有些东西必将成为历史,DSBridge的出现也注定着WebViewJavascriptBridge将成为历史,如果DSBridge没有实现这个目标,那只有一个可能,那就是DSBridge的作者对其推广不够
新项目可以直接用DSBridge,旧项目,已经使用了JavascriptBridge的,如果要使用DSBridge ,要做好兼容
SobotApi //客服sdk
GrowingIO//一站式数字化增长整体方案服务商
屏幕适配
https://juejin.cn/post/6921707764234502151
implementation ‘com.zhy:autolayout:1.4.5’//最大幅度解决适配问题,并且最大化方便开发者。
款适配,来自鸿洋大神之手的工具AutoLayout
https://blog.csdn.net/lmj623565791/article/details/49990941
implementation 'com.jph.takephoto:takephoto_library:4.0.3'//从相册获取图片
implementation 'com.youth.banner:banner:1.4.10'//轮播图
implementation 'com.yanzhenjie:permission:2.0.0-rc10'//动态权限申请
implementation 'com.umeng.umsdk:common:9.1.0' // (必选)版本号//友盟推送sdk
再学一次ConstraintLayout 一些新特性
https://blog.csdn.net/weixin_44339238/article/details/100043825
Android布局
https://blog.csdn.net/weixin_44339238/article/details/103294521
Android自定义View—布局过程的自定义
https://blog.csdn.net/weixin_44339238/article/details/103074281
Android布局优化:include 、merge、ViewStub的详细总结
https://blog.csdn.net/weixin_44339238/article/details/103056947
Android输入法开发微信斗图APP
https://blog.csdn.net/weixin_44339238/article/details/103461700
说说 Applink 的使用以及原理//scheme
https://blog.csdn.net/weixin_44339238/article/details/103702046
AsyncLayoutInflater布局异步加载
https://blog.csdn.net/weixin_44339238/article/details/103985603
面试题+答案
https://blog.csdn.net/weixin_44339238/article/details/102627325
https://blog.csdn.net/weixin_44339238/article/details/102666095
https://blog.csdn.net/weixin_44339238/article/details/102727748
https://blog.csdn.net/weixin_44339238/article/details/102745352
https://blog.csdn.net/weixin_44339238/article/details/102802948
https://blog.csdn.net/weixin_44339238/article/details/102820716
https://blog.csdn.net/weixin_44339238/article/details/102464319
https://blog.csdn.net/weixin_44339238/article/details/102939832
https://blog.csdn.net/weixin_44339238/article/details/102977486
https://blog.csdn.net/weixin_44339238/article/details/103091855
https://blog.csdn.net/weixin_44339238/article/details/103117884
https://blog.csdn.net/weixin_44339238/article/details/103123748
https://blog.csdn.net/weixin_44339238/article/details/103147755
https://blog.csdn.net/weixin_44339238/article/details/103165489
https://blog.csdn.net/weixin_44339238/article/details/103201634
https://blog.csdn.net/weixin_44339238/article/details/103241438
https://blog.csdn.net/weixin_44339238/article/details/104255246
https://blog.csdn.net/weixin_44339238/article/details/105736700
https://blog.csdn.net/weixin_44339238/article/details/109473716
参考回答:接口回调、广播
https://blog.csdn.net/jun5753/article/details/105670683
这个问题的解答,各位可以百度一下。一般我的解决方式是自定义一个带泛型和不指定参数个数的adapter。然后再定义一些方法,这样就不需要再adapter里面做太多的操作。具体自定义封装的会在后面的博文中详细说明这里的自定义封装方式和应用方式。当然鼓励大家自己发掘,并且给我留言,我好补充完整这个问题。
View是Android中所有控件的基类
View适用于主动更新的情况,而SurfaceView则适用于被动更新的情况,比如频繁刷新界面。
View在主线程中对页面进行刷新,而SurfaceView则开启一个子线程来对页面进行刷新。
View在绘图时没有实现双缓冲机制,SurfaceView在底层机制中就实现了双缓冲机制
SharedPreferences: 小东西,最终是xml文件中,key-value的形式存储的.
文件
数据库
ContentProvider
网络
重新设置LayoutInflater的Factory2,从而拦截创建View的过程,然后搞成自己的控件,想怎么换肤就怎么换肤.
有个异步的回调,建议用这个
深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用
修改堆内存中的同一个值
修改堆内存中的不同的值
深拷贝的实现方式,项目中有没有遇到这个问题
1、递归去复制所有层级属性
2、JSON对象的parse和stringify
https://blog.csdn.net/csdn_aiyang/article/details/108077254
https://www.cnblogs.com/guopengju/articles/11478645.html
简单、效率高和便利
FlatBuffers其实就是一个保存了一系列标量和矢量的缓冲区。这个缓冲区中的标量和矢量可以被直接访问。
缓冲区的数据一旦构造成功,里面的矢量数据一般不能变更,除非矢量的长度不大于构造时的长度,且矢量保存的不是偏移量,否则会产生错误。
https://blog.csdn.net/linuxheik/article/details/77835663
https://blog.csdn.net/chadzhaoleovation/article/details/51965214
FlatBuffers vs JSON
我尝试使用FlatBuffers和JSON解析4mb的JSON文件。
FlatBuffers花了1-5ms,JSON花了大约2000ms。在使用FlatBuffers期间Android App中没有GC,而在使用JSON时发生了很多次GC。在使用JSON时UI完全卡住,所以真实使用时只能在后台线程进行解析
https://github.com/amitshekhariitbhu/FlatBuffer//使用demo
如果让你实现一个调试器,你会怎么设计?静态调试?动态调试呢?
当我们谈Debug时,我们在谈什么(Debug实现原理)
https://blog.csdn.net/qq_36838191/article/details/85551836
debug 调试原理理解
https://blog.csdn.net/weixin_34161032/article/details/93497292
Debug使用详解
https://www.jianshu.com/p/9fbf316582e3
getFragmentManager、getSupportFragmentManager 、getChildFragmentManager之间的区别?
而getChildFragmentManager 是针对fragment嵌套fragment。
getFragmentManager()所得到的是所在fragment 的父容器的管理器(此处重点在父容器),
getChildFragmentManager()所得到的是在fragment 里面子容器的管理器(此处重点在子容器
getSupportFragmentManager,用于支持3.0以下的安卓系统API版本
直播中 网速比较差的条件下,如何使画面保证流畅的效果
https://blog.csdn.net/weixin_44339238/article/details/99679872
singleTask启动时候的回调onNewIntent以及不同栈之间的Activity如何跳转
sdk冲突解决办法
然而对于一个大型项目而言,如上方式并不一定可以轻而易举的找到冲突。
因此我们可以尝试在app的build.gradle中进行如下配置
configurations.all {
resolutionStrategy {
force 'com.squareup.okhttp3:okhttp:3.11.0'
force 'com.squareup.okio:okio:1.14.0'
force 'com.android.support.constraint:constraint-layout:1.1.1'
force 'com.google.code.gson:gson:2.8.5'
force 'com.android.support:appcompat-v7:27.1.1'
...
}
}
configurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}
相信resolutionStrategy大部分人都用过,专门为gradle设置编译的策略,ResolutionStrategy接口中提供了一系列策略方法,我们可以查看源码根据需要选择配置。对于一些冲突的场景,特别是集成了一些第三方的sdk后导致项目因为冲突报错无法编译的场景。我们可以选择直接设置failOnVersionConflict(),目的是在编译时假如有冲突发生,则直接编译失败在控制台打印报错信息,具体的可以查看我项目中的报错
这样一下子就知道项目中有哪些依赖冲突了,然后将冲突的依赖选择号版本添加到如下的配置中强制指定即可。
configurations.all {
resolutionStrategy {
force 'com.squareup.okhttp3:okhttp:3.11.0'
...
}
}
https://blog.csdn.net/yyanjun/article/details/95035908
android软键盘与沉浸式的冲突-AndroidBug5497Workaround
https://www.jianshu.com/p/01e36d5e2662
沉浸式状态栏
https://blog.csdn.net/qq_34681580/article/details/103955191
只在编译时有效,不会参与打包
compileOnly
请介绍下 AsyncTask的内部实现,适用的场景是
AsyncTask 内部也是 Handler 机制来完成的,只不过 Android 提供了执行框架来提供线程池来
执行相应地任务,因为线程池的大小问题,所以 AsyncTask 只应该用来执行耗时时间较短的任务,
比如 HTTP 请求,大规模的下载和数据库的更改不适用于 AsyncTask,因为会导致线程池堵塞,没有
线程来执行其他的任务,导致的情形是会发生 AsyncTask 根本执行不了的问题
android的权限机制
Apk必须签名
权限在manifest注册
userid
Apk数据不对外
如何实现单击事件和长按事件的判定
https://www.yuque.com/narkang/android/gmgckb
TagLayout(FlowLayout)怎么写?
https://blog.csdn.net/lmj623565791/article/details/38352503
俩线程分别持续打印奇数和偶数,实现俩线程的交替打印(从小到大)
场景一中,线程A和线程B交替打印奇数和偶数,使用对象监视器实现,通俗来说:线程A或线程B只要有一者竞争锁成功,就打印++i,通知其他线程从等待集合中释放,然后自身线程加入等待集合并且释放锁即可。
https://blog.csdn.net/weixin_30823001/article/details/97924442
用MultiDex解决何事?
解决方法数65535问题,进行dex分包
其根本原因在于?Dex如何优化?
主Dex放哪些东西?
主Dex和其他Dex调用、关联?
Odex优化点在于啥?Dalvik和Art虚拟机区别?多渠道打包如何实现(Flavor、Dimension应用)?从母包生出渠道包实现方法?渠道标识替换原理?
MultiDex解决方法数65535的限制问题,即方法数不能超过65535个;方法id是short类型4个字节来存储的,
所以数目范围在0-2的32次方即0-65535;MultiDex工作原理分析和优化方法;主dex中,应用启动必须加载的
类,有一个keep文件来控制,其他dex文件都是通过主dex加载进来的,odex优化点:预加载
RecyclerView和ListViewqub
1、缓存层级不同
2、局部刷新
3、功能更强大
计算View树上所有view的数量
public int getCount(ViewGroup viewGroup) {
int count = viewGroup.getChildCount();
for (int i = 0; i < count; i++) {
View child = viewGroup.getChildAt(i);
if (child instanceof ViewGroup){
int childCount = getCount((ViewGroup) child);
count += childCount;
} else {
count++;
}
}
return count;
}
说说 Applink 的使用以及原理
scheme
传统日志打印有两个性能问题,一个是反复操作文件描述符表,一个是反复进入内核态。
所以需要使用mmap的方式去直接读写内存。
Error、OOM,StackOverFlowError、Runtime,比如说空指针异常
解决的办法:
注意内存的使用和管理
使用Thread.UncaughtExceptionHandler接口,拿到crash日志,解决exception
这是因为在客户端中,加载H5页面之前,需要先初始化WebView,在WebView完全初始化完成之前,后续的界面加载过程都是被阻塞的。
优化手段围绕着以下两个点进行:
预加载WebView。
加载WebView的同时,请求H5页面数据。
因此常见的方法是:
全局WebView。
客户端代理页面请求。WebView初始化完成后向客户端请求数据。
asset存放离线包。
除此之外还有一些其他的优化手段:
脚本执行慢,可以让脚本最后运行,不阻塞页面解析。
DNS链接慢,可以让客户端复用使用的域名与链接。
React框架代码执行慢,可以将这部分代码拆分出来,提前进行解析。
https://blog.csdn.net/weixin_40129263/article/details/80983858
https://www.cnblogs.com/Android-Alvin/p/12759426.html
adb shell monkey -v 500
提前加载到内存currenthashmap,使用apply
有的手机有时候会偶现,可以试试重启看能不能好
华为手机,可以去应用市场-管理里面创建快捷方式
1、清除缓存:
反射调用接口:PackageManager.deleteApplicationCacheFiles**
它会清除以下项目:
A)清除data/data/{package_name}/cache/下的所有文件
B)清除data/data/{package_name}/code_cache/下的所有文件
C)清除mnt/sdcard/Android/data/{package_name}/下的cache文件夹
2、清除数据:
反射调用接口:ActivityManager.clearApplicationUserData
它会清除以下项目:
A)清除data/data/{package_name}/下的所有文件和文件夹(包括lib文件夹,PS:网上有人说lib文件夹和里面的内容不会被清除,经过验证,实际上也会清除)
B)清除mnt/sdcard/Android/data/下当前包名的文件夹
C)清除mnt/sdcard/Android/media/下当前包名的文件夹
D)清除{package_name}对应的app所有运行时权限的授权
E)清除所有通知,和该应用相关的所有URI授权(此项目为接口描述内容,未实际验证)
#但不会清除mnt/sdcard/Android/obb/{package_name}/下的内容
怎么实现View悬停?
Instant Run原理
Android与iOS相比有什么差别
Android与iOS系统内存管理机制了解吗?
《Android 开发艺术探索》
Framework 部分《Android 内核剖析》、《Android 源码情景解析》、
《深入理解 Android》系列等都是很不错的书籍。
Android 线程间通讯方式有哪些
handler
view.post
runOnUIThread
System.currentTimeMillis():获取的是系统时间,是距离1970年1月1日开始计算的一个值,如果用户修改了系统时间,延后几年,就不准了
SystemClock.elapsedRealtime():获取从设备boot后经历的时间值
asset:打包进apk就是原文件,不会有id,大小不能超过1M
res:都有R.id,
https://www.jianshu.com/p/9fa531331659
依赖Handler,需要Looper.prepare,Looper.loop
R.id的过程
Debug:调试版本,包含调试信息,所以容量比Release大很多,并且不进行任何优化(优化会使调试复杂化,因为源代码和生成的指令间关系会更复杂),便于程序员调试。Debug模式下生成两个文件,除了.exe或.dll文件外,还有一个.pdb文件,该文件记录了代码中断点等调试信息
Release:发布版本,不对源代码进行调试,编译时对应用程序的速度进行优化,使得程序在代码大小和运行速度上都是最优的。(调试信息可在单独的PDB文件中生成)。Release模式下生成一个文件.exe或.dll文件
混淆
https://blog.csdn.net/hdhhd/article/details/81077659
JavascriptInterface
loadUrl
不同厂商会有不同的定制
[dalvik.vm.heapstartsize]: [8m]:给进程分配的起始heap=8m
[dalvik.vm.heapgrowthlimit]: [64m]:进程最大可分配到64m
[dalvik.vm.heapsize]: [256m]:单个虚拟机可分配的最大内存=256m
不会
开子线程自己绘制
缺点是,会触摸点击时间要特别处理
SurfaceView是在一个新起的单独线程中可以重新绘制画面,而view必须在UI的主线程中更新画面。
在UI的主线程中更新画面可能会引发问题,比如你更新的时间过长,那么你的主UI线程就会被你正在画的函数阻塞。那么将无法响应按键、触屏等消息。当使用SurfaceView由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要在SurfaceView中的thread处理,一般就需要有一个event queue的设计来保存touchevent,这会稍稍复杂一点,因为涉及到线程安全
事实上很多的log机制都是直接使用APPEND模式+write来实现写日志行为,而不需要外部行为来保证日志的同步,操作系统本身的write系统调用就能保证不同的logger写入log文件的原子性
https://www.jianshu.com/p/1bee0dc5d0d9
在LINUX中我们可以使用mmap用来在进程虚拟内存地址空间中分配地址空间,创建和物理内存的映射关系
https://blog.csdn.net/u014602917/article/details/105390368
优点如下:
1、对文件的读取操作跨过了页缓存,减少了数据的拷贝次数,用内存读写取代I/O读写,提高了文件读取效率。
2、实现了用户空间和内核空间的高效交互方式。两空间的各自修改操作可以直接反映在映射的区域内,从而被对方空间及时捕捉。
3、提供进程间共享内存及相互通信的方式。不管是父子进程还是无亲缘关系的进程,都可以将自身用户空间映射到同一个文件或匿名映射到同一片区域。从而通过各自对映射区域的改动,达到进程间通信和进程间共享的目的。同时,如果进程A和进程B都映射了区域C,当A第一次读取C时通过缺页从磁盘复制文件页到内存中;但当B再读C的相同页面时,虽然也会产生缺页异常,但是不再需要从磁盘中复制文件过来,而可直接使用已经保存在内存中的文件数据。
4、可用于实现高效的大规模数据传输。内存空间不足,是制约大数据操作的一个方面,解决方案往往是借助硬盘空间协助操作,补充内存的不足。但是进一步会造成大量的文件I/O操作,极大影响效率。这个问题可以通过mmap映射很好的解决。换句话说,但凡是需要用磁盘空间代替内存的时候,mmap都可以发挥其功效。
缺点如下:
1.文件如果很小,是小于4096字节的,比如10字节,由于内存的最小粒度是页,而进程虚拟地址空间和内存的映射也是以页为单位。虽然被映射的文件只有10字节,但是对应到进程虚拟地址区域的大小需要满足整页大小,因此mmap函数执行后,实际映射到虚拟内存区域的是4096个字节,11~4096的字节部分用零填充。因此如果连续mmap小文件,会浪费内存空间。
对变长文件不适合,文件无法完成拓展,因为mmap到内存的时候,你所能够操作的范围就确定了。
3.如果更新文件的操作很多,会触发大量的脏页回写及由此引发的随机IO上。所以在随机写很多的情况下,mmap方式在效率上不一定会比带缓冲区的一般写快
限制一些没有被文档提及的非公开 APIs 的调用,例如被标记为 @hide 的 APIs,不能使用反射,会出现"Accessing hidden …警告
.对我们APP开发者来说,有3种做法会处触发API检查:a.java层反射; b.jni调用
通过Hook GetHiddenApiEnforcementPolicy()来绕过non-sdk API检查
https://blog.csdn.net/XXOOYC/article/details/81585655
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
paint.setColorFilter(new ColorMatrixColorFilter(cm));
getWindow().getDecorView().setLayerType(View.LAYER_TYPE_HARDWARE, paint);
滑动逻辑主要是利用View的scrollBy() 方法, scrollTo()方法和Scroller类来实现的,当手指拖动视图的时候,我们监听手指在屏幕上滑动的距离利用View的scrollBy() 方法使得View随着手指的滑动而滑动,而当手指离开屏幕,我们在根据逻辑使用Scroller类startScroll()方法设置滑动的参数,然后再根据View的scrollTo进行滚动
remoteView的使用
https://www.jianshu.com/p/18345b839e0c
1、Linux 文件系统权限。不同的用户对文件有不同的读写执行权限。在android系统中,system和应用程序是分开的,system里的数据是不可更改的。
2、Android中有3种权限,进程权限UserID,签名,应用申明权限。每次安装时,系统根据包名为应用分配唯一的userID,不同的userID运行在不同的进程里,进程间的内存是独立的,不可以相互访问,除非通过特定的Binder机制。
Android提供了如下的一种机制,可以使两个apk打破前面讲的这种壁垒。
在AndroidManifest.xml中利用sharedUserId属性给不同的package分配相同的userID,通过这样做,两个package可以被当做同一个程序,系统会分配给两个程序相同的UserID。当然,基于安全考虑,两个package需要有相同的签名,否则没有验证也就没有意义了
数据传递只能传字节流
在使用内存的时候,Parcelable 类比 Serializable 性能高,所以推荐使用 Parcelable 类。
Serializable 在序列化的时候会产生大量的临时变量,从而引起频繁的 GC。
Parcelable 不能使用在要将数据存储在磁盘上的情况。尽管 Serializable 效率低点,但在这种情况下,还是建议你用 Serializable
parcelable原理把对象拆解成基本数据类型
存储媒介的不同,Serializable 使用 I/O 读写存储在硬盘上,而 Parcelable 是直接 在内存中读写
使用多进程通信会造成如下几方面的问题:
• 静态成员和单例模式完全失效:独立的虚拟机造成。
• 线程同步机制完全失效:独立的虚拟机造成。
• SharedPreferences的可靠性下降:这是因为Sp不支持两个进程并发进行读写,有一定几率导致数据丢失。
• Application会多次创建:Android系统在创建新的进程时会分配独立的虚拟机,所以这个过程其实就是启动一个应用的过程,自然也会创建新的Application
Serializable与Parcable的区别。 在什么情况下需要用到序列化和反序列化,Serializable中为什么要设置UID,设置UID与不设置UID值的区别和影响
targetSdk低于28的app,会在onStop之前回调onSaveInstanceState,从targetSdk 28开始,onSaveInstanceState在onStop回调之后才回调,而低于11的app,永远都会在onPause之前回调
context相关
创建对话框时不可以用Application的context,只能用Activity的context
可以肯定的是,两者都是支持序列化和反序列化的操作。
两者最大的区别在于 存储媒介的不同,Serializable 使用 I/O 读写存储在硬盘上,而 Parcelable 是直接 在内存中读写。很明显,内存的读写速度通常大于 IO 读写,
所以在 Android 中传递数据优先选择 Parcelable。
Serializable 会使用反射,序列化和反序列化过程需要大量 I/O 操作, Parcelable 自已实现封送和解封(marshalled &unmarshalled)操作不需要用反射,
数据也存放在 Native 内存中,效率要快很多。
Gson jar
‘com.wiseapm.agent.android:wiseapm:3.9.9’
Bundle传递数据为什么需要序列化?
序列化,表示将一个对象转换成可存储或可传输的状态。序列化的原因基本三种情况:
1.永久性保存对象,保存对象的字节序列到本地文件中;
2.对象在网络中传递;
3.对象在IPC间传递。
Intent在传递数据时是有大小限制的,大约限制在1MB之内,你用Intent传递数据,实际上走的是跨进程通信(IPC),
跨进程通信需要把数据从内核copy到进程中,每一个进程有一个接收内核数据的缓冲区,默认是1M;如果一次传递的数据超过限制,就会出现异常。
不同厂商表现不一样有可能是厂商修改了此限制的大小,也可能同样的对象在不同的机器上大小不一样。
传递大数据,不应该用Intent;考虑使用ContentProvider或者直接匿名共享内存。简单情况下可以考虑分段传输。
Android中的scheme是一种页面内跳转协议,通过定义自己的scheme协议,可以跳转到app中的各个页面
服务器可以定制化告诉app跳转哪个页面
App可以通过跳转到另一个App页面
可以通过H5页面跳转页面
在onCreate里面调用finish方法,这样系统会直接调用onDestory,跳过生命周期中的其他方法
http://blog.csdn.net/geekerhw/article/details/48749935
Rect outRect
Left right. 都算子view宽高