- 博客(204)
- 资源 (16)
- 收藏
- 关注

原创 技术栈
作为面试官见过很多候选人,包括阿里p7、百度t6、美团资深等大厂的;在聊到技术宽度和深度时,有些人并没有清晰的认识。 是时候总结一下技术栈了, 就像照镜子一样找出自己掌握了哪些能力,还欠缺哪些知识....
2018-10-19 12:07:13
856
原创 数字转换为合法IP地址
算法题目:给定一串数字, 返回所有合法的ipv4地址集合。例如: 给出数字12345, 返回1.2.3.45、1.2.34.5、1.23.4.5等等。思路:ip地址是*...*格式。 每个ip段合法值是0~255, 即合法的ip地址格式应该是[0,255].[0,255].[0,255].[0,255]。 可以通过递归实现, 顺序遍历数字添加数字到当前ip段或者下一段, 当数字遍历到末尾且存在4个ip段则找到了合法的地址。边界条件:1、ip段位空, 添加当前数字到第一段;2、每次获取最后一个i
2020-11-21 20:55:15
1182
原创 冷启动治理-启动框架原理
一、背景从点击桌面图标到首页渲染完成的平均时间应在3秒以内。 为什么是3秒? 统计数据表明超过3秒后用户跳失率陡增。冷启动优化有很多技术手段, 百度上都能查到,不再赘述。二、启动框架简介启动框架的作用是充分利用前3秒的CPU, 即打满CPU.为什么出现“bad case”的情况呢? 这是本文要解决的问题。 通常因为在进程启动阶段出现各种锁和信号量, 导致线程间的相互等待。上图Wall Duration是142.421ms,但self time是4.251ms。该函数等待时间远远超过自身的执行
2020-06-21 11:25:28
947
原创 再看一遍Retrofit
说起来Retrofit是Android App常用的轮子, 原理比较简单; 就是通过动态代理解决函数注解, 从而方便实现http请求逻辑;从架构角度, 我们能从Retrofit源码里学到什么呢?1、深入理解动态代理的应用范围, 这是retrofit的核心逻辑;2、声明各种注解表示不同的作用; 是不是感觉有点像枚举的作用?3、retrofit不实现网络交互, 只是对Okhttp的封装;4、...
2019-11-10 21:47:59
279
原创 Kotlin object关键字详解
一、object用途1、用户标识匿名内部类; 2、对象说明(编译时生成静态实例)。二、修饰内部类对象 btn.setOnClickListener(object: OnClickListener { override fun onClick(p0: View?) { } ...... })三、object修饰的类为静态类以object关键字修...
2019-10-27 14:35:34
4022
原创 Android性能优化系列-监听View inflate周期并动态替换
LayoutInflater hook点在Activity里执行setContentView或者inflate布局文件最终都会走到如下代码:LayoutInflater.java View createViewFromTag(View parent, String name, Context context, AttributeSet attrs, boolea...
2019-10-13 16:20:15
1122
原创 ButterKnife R2作用和删除
在使用ButterKnife时library工程的注解会使用R2, 为什么使用R2而不是R呢?如上图所示R.class中参数定义使用了final关键字, 即R.class里全部是常量; 而R2.class里全部是变量。PS:Java语言在编译时常量内联, 即使用常量值替换参数;Java 注解的属性和 switch-case 中的 case 表达式,必须使用常量或者值,否则会报语法错误。...
2019-10-06 20:02:49
3417
原创 sqlitedatabase is locked
在操作Orm数据库sqlite时, 当存在多线程/多进程并行写时报错。 支持同一时刻多个读, 但同一时刻只能有一个写(不能有读); 简单记: 读写、写写是互斥的, 读读是可以并发的。 因为多线程、多进程可以通过数据库名称操作同一个数据库, 建议只在一个进程中实例单例访问同一个数据库, 从而实现互斥判断逻辑; 什么是写? 增加insert、删除delete、更新up...
2019-09-25 19:49:52
470
原创 Activity渲染完成第一帧时机
Activity第一帧渲染涉及知识点setContentView流程、帧绘制流程和帧率监听等。开始时间:hook ActivityThread的Instrumentation, 得到Activity各个生命周期的开始、结束时间; 参考: Activity的生命周期是谁调用的?注意: ActivityLifecycleCallbacks的回调函数是执行结束后触发的, 无法得到开始执行时间...
2019-09-22 10:25:53
3863
原创 安卓View点击/曝光的监听方式
Android点击、曝光事件的监听分散在代码的各个角落, 不利于开发维护。其实可以将这2种行为收敛到一起, 运行时监听Activity的生命周期,即ActivityLifeCallBack回调; 在onResume或onStart函数里判断当前acitivity是否添加了自定义ViewGroup(暂且命名为TrackerViewGroup), 如果未添加则添加;在onDestory函数中移除...
2019-09-15 19:12:39
2120
原创 安卓9启动Activity流程分析和优化建议
Android在从9.0版本开始修改了启动Activity流程, 跟以往版本的主要区别在于使用了Translation。Android9.0代码:clientTransaction.addCallback函数传入了LaunchActivityItem。final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord a...
2019-08-24 18:05:03
900
原创 Android性能优化系列-IdleHandler
IdleHandler是在主线程空闲时执行同步任务, 即可以做优先级低的业务逻辑。对于启动新Activity可以在cmd窗口执行adb logcat -s ActivityManager | grep “Displayed” 得到时长。用法:public DemoActivity extends Activity { IdleHandler mHandler1 ; IdleHand...
2019-08-19 21:08:56
1989
1
原创 Android Drawable缓存
Android获取Drawable对象方式为getResources().getDrawable(@DrawableResId int res), 只可能返回ColorDrawable、BitmapDrawable对象, 当然id不存在会抛异常。public abstract class Drawable { ... }在/framework/base/graphics/java/an...
2019-08-02 10:39:20
1485
原创 Android View座标
手机屏幕左上角座标是(0, 0), 右下角座标是(w,h)即屏幕宽和搞。获取View位置:View方法说明getLocationOnScreen获取View左上角距离屏幕左上角的距离x和ygetLocationInWindow获取View左上角距离PhoneWindow左上角的距离x和y,只有Dialog模式activity时有区别, 其它情况下返回值与get...
2019-07-22 07:46:43
468
原创 Live Template撸码利器
参考:https://www.jianshu.com/p/488f2d73e71d手动输入代码太辛苦, 拼敲键盘速度? 赶快试用代码补全功能吧。IntelliJ idea和Android Studio都支持代码自动补全功能, 如上面所示的几个场景。 在工作中可以把常用的代码块总结到模板里, 输入几个字符自动生成代码,从而提高撸码效率;例如在创建dart文件后, 文件内容是空的。 这时有代码...
2019-07-20 18:13:06
2168
原创 Java调用Kotlin函数的坑
看下这段代码执行main函数结果如何, 会打印"执行了method函数"么?class DemoClass { fun method(str: String) { System.out.println("执行了method函数") System.out.println(str) }}public class HelloJava { p...
2019-07-20 17:46:21
3282
原创 可拖拽的ListView
长按拖拽item并实现变更排序;说明: WindowManager在addView时尚未测量完成, 获取宽高都是0。 可以这样测量: view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);int width = view.getMeasuredWidth();使用getViewTreeOb...
2019-07-05 20:28:49
1562
1
原创 地图类业务优化方法
一、背景在百度地图、高德地图上显示Marker, 如果显示数量很多时,滑动地图会出现卡顿的现象。 根本原因是地图是个耗内存的功能, 我们看到的地图和marker都是Bitmap。 想想在手机屏幕上添加100个小的Bitmap和背景的大Bitmap需要多少内存? 这些图片没有复用机制,都是储存在Java堆里,显示的Marker越多占用的内存越多。滑动地图时可能出现卡顿甚至ANR的现象, 其实就...
2019-06-16 18:31:19
589
原创 ByPhoto-秒开的安卓图片选择库
一、背景ByPhoto是个安卓图片选择库, 在启动渲染速度上做了很多优化; 荣耀8真机测试,图库里有3000多张图片。 冷启动图片选择页渲染完成需800ms左右, 热启动(即第二次打开Activity)渲染需要300ms。 真正实现了秒开的用户体验。二、需求1、支持图片预加载, 即将图库的前几张图片加载到内存中; 使用了Glide的preload;2、数据库分段回调, 即图片有几千张...
2019-06-12 19:43:32
1315
原创 Android根据座标找到对应的View
在界面上点击按钮时,想想安卓是如何找到能响应事件的顶层View的?如果给你坐标x、y, 你能找到对应的顶层View么?首先安卓布局根节点是DecorView,并呈现为多叉树结构; 每个顶层View都是一个页节点;需求:手指在界面上滑动时显示对应的顶层View。<?xml version="1.0" encoding="utf-8"?><LinearLayout xml...
2019-05-30 09:50:46
1794
原创 Java和Kotlin编译基础知识
Java和Kotlin都是跨平台语言, 归功于在编译时生成的字节码与平台无关, jvm在装载字节码后即可运行。JavaKotlin编译javackotlinc运行javakotlinJava语言使用javac编译为字节码, Kotlin使用kotlinc编译为字节码;在Android Studio的安装目录下保存着Kotlin插件, Kotlin目...
2019-05-27 15:47:52
1427
原创 Long monitor contention with owner
安卓Activity在finish后出现黑屏, 大概率是因为主线程卡死。 抓trace和logcat。04-16 16:18:17.359 W/m.lianjia.beik(30714): Long monitor contention with owner Binder:30714_6 (32307) at void java.lang.Object.wait(long, int)(Obje...
2019-04-16 17:27:56
18802
1
原创 Glide preload和into的区别
一、背景 贝壳2.6.0版本使用Glide preload方法替换了部分显示图片的方式, 在灰度期间发现控件显示了错误的图片或者崩溃问题。Fatal Exception: java.lang.RuntimeException:Canvas: trying to use a recycled bitmap android.graphics.Bitmap@25e89bf at android...
2019-04-08 18:17:19
1274
原创 Flutter开发Feed流笔记二
仿照贝壳找房app看点页实现feed流功能。UI使用了:tabbar+tabbarview+ListViewhttp通讯:Diojson:json_serializable下载刷新/加载更多:flutter_refresh遇到问题:1、 tabbarview在切换标签页后, 前一个标签页的状态会丢失。每次打开标签页都会重新创建widget树。2、 tabbar不支持设置间距, 例如...
2019-03-24 09:37:38
713
原创 Flutter开发Feed流笔记一
第一个知识点: 如何隐藏AppBar?包一层宽高等于0的父容器就可以了。 return new Scaffold( appBar: PreferredSize( child: AppBar( ), preferredSize: Size(0, 0)),第二个知识点: Column/Row容器里直接添加ListVi...
2019-03-17 17:53:27
740
原创 HTTP302丢Session
安卓app在打开第一个H5页面时app设置了Session, H5返回302跳转到相同域下的另一个H5, 这时丢了Session。public class MainActivity extends Activity { private WebView mWebView; @Override protected void onCreate(Bundle savedInstanceSt...
2019-03-17 10:08:11
961
原创 Arrays.asList的坑
问题:直接原因: public void add(int index, E element) { throw new UnsupportedOperationException(); }举个例子:下面2种方式有什么区别?第一种第二种第二种运行时会崩溃!!!/** * Returns a fixed-size list backed by the...
2019-03-13 21:19:43
294
原创 贝壳找房APP安装包瘦身
一、背景在满足产品、UI要求的前提下,尽量减少安装包体积。以customer插件为例:插件大小为5MB, 其中1MB是dex,而bkbase占了dex的580KB;3.1MB是图片。 减少res目录体积效果会更明显。二、方法1、删除冗余代码、资源文件, 可使用lint扫描; 安卓端在编译release包时设置shrinkResources为true, 即不会打包冗余资源到输出物;...
2019-03-12 19:41:42
531
原创 删除TextView上下内边距
原理参考: https://blog.youkuaiyun.com/harvic880925/article/details/50423762通过自定义控件删除上下内边距, UI走查时就不用担心间距不对了。代码:public class MyTextView extends TextView { public MyTextView(Context context) { super(con...
2019-03-08 16:55:55
2378
原创 一个小Demo带你理解安卓事件分发
安卓事件分发是个老生常谈的话题, 在ScrollView高度测量原理介绍Android View测量原理, 现在再用个实例讲解事件分发原理。 本文要搞懂2个问题。1、 事件是怎么产生的?2、事件是怎么传递的? 手指在屏幕上一滑, framework层的ViewRootImpl中广播监听WindowInputEventRecevier最先收到事件, 将native层传...
2019-02-17 10:04:14
551
原创 贝壳找房FEED流曝光策略
摘要:目前贝壳找房的曝光策略边界条件比较单一, 都是APP端写死的逻辑;对标一线公司解决方案, 是由API下发每种卡片/Feed的门限条件, 从而得到更精准的数据。一、背景目前贝壳找房APP端的曝光时机是写死的, 触发条件:卡片必须要完整展示在界面上; 在列表界面上下/左右滑动时单次/多次曝光同一个卡片。现有方案的不足:1、门限条件应改为API下发的; 2、缺少卡片在界面上显示的时长;...
2019-02-16 22:29:19
1770
原创 ScrollView高度测量原理
在使用Lint扫描工程时,看到这个提示。 Google推荐将ScrollView的子View高度设置为wrap_content, 但实际业务开发时可能根节点是LinearLayout(layout_height="match_parent"), 然后发现屏幕显不下就包了一层ScrollView。 运行看到ScrollView能正常上下滑动,就没改LinearLayout的layou...
2019-02-14 14:18:59
3470
1
原创 Flutter事件分发
大道同源, 其实Flutter的事件分发跟安卓类似。 下面就详细介绍下Flutter的事件分发体系:1、 Flutter所有事件源头是 hooks.dart文件的_dispatchPointerDataPacket函数, 接收屏幕的点击、滑动等等各种事件。 类似于安卓的ViewRootImpl.java接收native层的数据。2、gestures/binding.dart中的Ges...
2019-02-12 11:24:18
2769
原创 理解Future执行时序原理
在Flutter开发中,一般使用Future、Stream、async/wait使用异步操作。 Future类用于异步任务、Stream类主要用文件IO, 而async/wait是关键字。 官方介绍:Dart消息循环 https://webdev.dartlang.org/articles/performance/event-loop 打开future.dart可以...
2019-01-31 14:42:50
2432
原创 Dart事件总线
因为Flutter不支持反射, 所以无法实现像EventBus那样通过注解添加观察者并反射执行对应函数。 在Flutter开发中, 可以通过单例模式和观察者模式实现事件总线, 参考Flutter事件分发原理支持发同步、异步消息。 暂时不支持黏性事件, 后续有需要的话再完善, 把EventBus.java翻译成Dart就成了。 DashPad不支持json,示例代码就没做json序...
2019-01-29 11:18:58
1020
原创 Flutter生命周期
Flutter跟安卓的Activity、iOS的ViewController一样拥有自己的生命周期, Flutter中一切都是Widget,渲染方式有点像H5的DOM树。 先看生命周期图:Flutter生命周期可以分为3个阶段:1、实例化组件并添加到树, 即Navigator.push;2、状态变化,即打开新的widget或者依赖的上级widget...
2019-01-21 20:06:15
7564
4
原创 自定义lint规则解决开发中的问题
一、背景在发贝壳2.1.1版本第一次灰度时遇到了一个崩溃(崩溃在租房),第二次灰度版本时发生了相同原因的崩溃(崩在了二手)。 当时的做法是发现一处解决一处, 但没发现的隐藏问题是个定时炸弹。日志:java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = ...
2019-01-08 19:30:22
1686
1
原创 红黑树TreeMap总结
红黑树是自平衡的二叉查找树,又称二叉B树。它可以在O(logN)时间复杂度内完成查找、增加、删除操作。红黑树是在二叉查找树基础上增加了着色和左右旋转使得红黑树相对平衡, 与AVL树相比,红黑树并不追求所有子树的高度差不超过1,而是保证从根节点到叶子节点的最长路径不超过最短路径的2倍。红黑树通过如下性质实现了自平衡:1. 节点必须是黑色或红色;2.根节点必须是黑色;3.所有NIL节...
2018-12-30 16:07:16
565
原创 安卓适配动态权限说明
一、背景: 从Android6.0版本开始google将权限分为普通权限和特殊权限,app必须在AndroidManifest.xml添加引用权限的语句。 在安装apk时安卓会将普通权限授予该app,但特殊权限需要运行时申请。 安卓按照权限类别分为权限组和权限, 每个权限都隶属于一个权限组。 当安卓系统授权一个权限时, 那么该权限所属权限组的权限都会自动被授权。 ...
2018-11-26 22:12:25
1143
SpringCloud接收文件
2017-12-14
Swift自定义UIView动画
2016-12-23
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人