这些年我踩过的坑——Android

  • PD如果经常要求改入口,使用Adapter + ViewHolder来实现解耦:
    • 这两个配合模拟FragmentManager + Fragment的逻辑
    • Adapter只负责管理View、对ViewHolder中的生命周期函数进行回调
    • ViewHolder不仅保存View的引用,还完整包含与该View有关的所有逻辑,对外暴露相同的生命周期回调函数,例如onViewCreated、onBindView等
    • 调整入口仅仅需要在Activity中调整Adapter的Data
    • 切记要将ViewHolder与View绑定,如果不绑定就不要复用之前的View,否则空指针
  • Json是弱类型,子类Json串填充父类对象将会出现Member丢失的情况
  • getSystemService获得Inflater的时候,一定要用Activity的Context,不能用Application Context
  • ListView跳转到item的某个位置,需要用setSelectoinFromTop,不能setSelection再scroll。ListView直接scroll会导致跳动和空白item
  • ListView中传递的所有关于Position的数据都是包括Header、Footer的,算数要小心
  • 在Inflate时,一定要传入parent参数,否则一些依赖父节点的layout参数是不能解析的,详见:这里
  • merge节点在inflate时,必须attachToRoot传true,否则crash
  • LaunchMode以及ApplicationContext+ActivityContext引发的Task栈混乱问题
  • Android/Linux系统是不保存文件创建时间的,如果想拿到文件创建时间,需要用比较tricky的办法。文件名由两部分组成:原始文件名+分隔符+创建时间(1970毫秒).扩展名。原始文件名开头比较容易写Filter
  • 反射在Android上真的很慢,ormlite比直接使用sql要慢一倍!
  • Activity.runOnUiThread()使用的Handler虽然是Activity的成员变量,其对应的Looper却是Looper.myLooper()。所有runOnUiThread的Runnable即使Activity已经被finish仍然会被执行
  • SqliteDatabase.beginTransaction一定要setTransactionSuccessful,否则所有的操作都会取消!!!
  • 基本所有使用回调的地方都可以通过KVO来实现,而且直接使用LocalBroadcast能够避免很多内存泄露啊、监听器管理之类的麻烦。
  • 应对软键盘遮挡的问题,可以处理四个不同的事件,事件和调用顺序如下:
    1. onSizeChanged(Activity需要是AdjustResize的)
    2. onLayout(不用监听onMeasure,回调的位置太多了)
    3. addOnLayoutChangeListener监听layout的回调事件
    4. getViewTreeObserver().addOnGlobalLayoutListener监听全局的layout事件
  • 据说在App被卸载/停止的时候,jni里fork出来的子线程是不会被停止的。这样就可以干很多流氓的事情了,比如保活之类的
  • 有一个很赞的hook,LayoutInflater.Factory提供在原生View的xml里增加新的attribute。例子
  • 关于软键盘的问题:

    • 调起来讲,((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).
      showSoftInput(view, 0);
      tag为0是默认,SHOW_FORCED在某些rom上会要求用户主动点back才能收起键盘,使用任何一种代码上的hide都不生效,压后台也不生效。理论上是tag越大,show的动作越强

    • 收起来讲,((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).
      hideSoftInputFromWindow(editText.getWindowToken(), 0);
      tag为0是默认的,最强的是HIDE_NOT_ALWAYS,却仍然不能hide用SHOW_FORCED调起的键盘

  • Activity上的Theme之类的都是给Window的DecorView设置的,生效的面积大于Activity的面积(在键盘动画的情况下)

  • 设计的时候,各种码、状态类型要统一,尽量使用int,打印也别非转换一下。码类型转换、字符串拼接这种非常耗内存也会增加apk大小

  • 使用ValueAnimator做颜色动画时,一定要用ValueAnimator.ofObject(new ArgbEvaluator(), colors),不能用ValueAnimator.ofInt(colors);。后者会闪,各种闪

  • Fragment因为在切换过程中会有各种post,会有不可解的crash。可以自己实现简单的fragment
  • View的Animation和setXXX是不一样的,Animation都是作用在Transform上的,所以所有的结果不能通过setXXX恢复
  • View在add到Window之前post的runnable可能会在add之后不被执行(因为对应的消息队列变了)
  • 获取当前进程名,反射调用android.ddm.DdmHandleAppName.getAppName(),或者使用pid反查
  • 进程的启动原因会在MainLooper中Message的obj中存储,对象不同区分原因
  • SP每次get的时候都会读文件,如果SP数据不大的话,还是在内存中保存一份效率高
  • 一个设计合理的埋点应该包括这几方面,其中的大部分信息都是固定的,可以参考Android中xml压缩的方法,在多个埋点中重用相同内容:
    • 固定上下文:用户信息、设备信息、时间、App信息
    • 交互上下文:Session、网络
    • 当前用户操作的信息:类型,所在的模块、页面、View,referer(http_referer),url
    • 其他:数据分析串连埋点用的埋点session、埋点起止标识位
  • 可以通过WindowFocus判断Activity是否在前台(isResumed),包括了是否有弹框、是否被其他view遮挡了。toast这种不能获取焦点的window不会影响。非常敞亮的方法
  • 据说.9做selector的时候,padding会失效。源码上看,padding的计算会受背景的大小影响
  • 想捕获native异常,使用的是POSIX的sigaction方法。这个介绍很好
  • java8 的方法引用不能作为 listener,因为在实际执行的过程中会生成一个 object a -> fun(a) {},所以会导致 add 和 remove 的时候方法引用不是一个实例
  • APT使用的annotation必须在android library module中才会有自动完成…神问题,只能用一个空interface module解决
  • 有一些超神手机上,Log打日志会丢失。看不懂C代码,从现象看是如果日志内容完全一致,间隔又极小(nano second级别)会出现
  • CookieManager 想删除某个 host 下的某个 key,需要用 setCookie + 一个已经过期的 expireTime。官方文档说是会忽略,实际上是会删掉对应的 cookie 项

你可能感兴趣的:(学基础,代码段)