基础
- 依赖倒置原则:抽象不依赖于实现、让具体实现依赖于抽象。其实就是基本的编程想法,但是在设计
- activity的切换,A.pause→B.onCreate→B.onStart→B.onResume→A.onStop
所以别在pause做耗时操作,会影响下个页面的启动速度。 - Filter实现数据过滤,在Adapter里面写一个内部类,然后继承接口。这不仅可以实现搜索,在数据较大且很恶心人还要分类的时候特别有用。
- 双重Viewpager的嵌套、在supportV4包下的viewpager不存在滑动冲突,但是层叠Viewpager的时候,subViewPager的适配器要用getChildFragmentManager(),不然会造成页面滑动缓慢,和fragment丢失的问题。
- viewpager嵌套swiperefresh嵌套listView里面的N个seekbar,通过监控seekbar的触摸事件,决定viewpager是否分发触摸事件。解决横向滑动冲突。
- CustomView 在onMeasure之后再获取宽高尺寸API,一般放在onLayout初始化就可以了。
- 包装Vector颜色
Drawable drawable = getDrawable; drawable = DrawableCompat.wrap(drawable); DrawableCompat.setTint(drawable, Color.GREEN); DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN); // 恢复颜色: DrawableCompat.unwrap(Drawable drawable); - 透明度分为256阶(0-255),计算机上用16进制表示为(00-ff)
- 公司新项目还是多用Fragment,移植,合并模块的快,Activity不方便移动。
- 项目开始的时候写个Python脚本解决机型尺寸适配问题,毕竟设计师给的都是px。
- System.exit(0); 真的会把application搞退出来。android.os.Process.killProcess(android.os.Process.myPid());也是可以的
- 不要把Int型变量直接放在setText();里面,会被当成资源ID去查找,然后极有可能就出现找不到资源的错误。
- Custom view 在定义属性的时候,注意static的应用,如果是开放设置的属性别设static,不然会联动到所有的控件里面。
- 开发过程中有时候空指针,数组越界等问题导致了activity销毁重启,然而里面的旧fragment还在,activity重启带来了一个新的fragment,导致新旧fragment就重叠了,怎么避免?在activity里面检查savedInstanceState是否为空,不为空可以直接用FragmentManager把它找出来,避免重复创建。
- 对于第三方的回调的数据,判空后再使用。
- 适配器里面有用到context,传递的最好是activity/fragment,为什么呢,因为适配器里面时常更新UI,这么做就是把数据绑定到UI的生命周期上,防止更新页面的时候页面已经销毁
- 注意检查activity/fragment结束的时候,popupWin/dialog等弹窗是否关闭。
- 一个比较方便的屏幕截图:
View viewRoot = getWindow().getDecorView().getRootView(); viewRoot.setDrawingCacheEnabled(true); Bitmap screenShotAsBitmap = Bitmap.createBitmap(viewRoot.getDrawingCache()); viewRoot.setDrawingCacheEnabled(false);
- API19开始原生支持 PDF文件加载。PdfDocument
- 事件分发,这是我自己的一点总结,和项目相关,理解方式可能和别人不同:
dispatchTouchEvent | onInterceptTouchEvent | onTouchEvent |
---|---|---|
调度 | 拦截(ViewGroup) | 触摸 |
这玩意儿相当成功的避免了 | true 拦截,发给自己的onTouchEvent | true 拦截 |
onInterceptTouchEvent 的多次调用 | false 不拦截,发给child的dispatchTouchEvent | false 不拦截,发给parent的onTouch |
- 需要协调一连串的动画 用属性动画的playwith after together 联动。
- 属性动画+事件分发+尺寸+布局 custom viewgroup
- 唯一约束是一个比较简单直接的控制数据唯一性的方法。
- 把SQL语句和数据库字段分离,多线程操作数据库的时候容易发生死锁,注意实现线程的同步和互斥。
- Vysor用来演示不错
-
KMP用来做字符匹配搜索很中肯,特别是在解析长数据的时候。当然不排除其他模型树有更好的解法。
-
Gradle Console里面的构建信息真心可以查出好多问题。
- adapter必须封装好,不然写死你,
- listview的addHeadView会导致页面position +1完全没必要搞这玩意儿导致数据紊乱,在布局里面的头部自己加就可以。
- listview的notifyDataSetChanged()是检查指定的list的堆地址,通过list.add把数据加在堆地址,可以实现数据更新,但是如果通过list = changelist 是改变了 list 的引用地址到changelist的堆地址,notifyDataSetChanged()会去检查原来的list的内存地址,起不到更新数据的效果。可以通过list.clear(); list.addAll(changelist);来添加。
- <include>标签、如果指定了ID,那么将不能直接通过findviewbyId找到,可以通过
View layout = getLayoutInflater().inflate(R.layout.head, null); //head.xml RelativeLayout index= (RelativeLayout)layout.findViewById(R.id.index); //找到id index.xxxxx;//做操作
- bottomsheet可以用23design里面提供的,没必要自己写。多处应用的话,写个BottomSheetDialogFragment包装起来就可以了。至于那些属性配置透明度、状态栏颜色什么的,全部可以在style里面完成。
- style="?android:attr/borderlessButtonStyle"可以去除BUTTON的投影效果
- 有MVP架构的代码,写单元测试那叫一个舒服。(但是MVP用了一年之后的感觉就是不想再用,恶心。没必要。MVVM或许还好点,或者自己定制一种MVC的方式,把controller写好。)
- 混淆的时候注意第三方框架,自定义控件。注解。
- 6.0动态权限申请流程
线程
- 主线程 = UI线程 = mainthread
- 通过多个Thead来跑同一个Runnable可以较好的实现资源共享,注意锁住关键对象。
- handler和线程和thread一一对应:Runnable并没有实现多线程
在主线程里面(也是在activity或者fragment里面) handler.post(new Runnable(){...})其实也是在主线程里面运行的。要实现多线程就new Thread(new Runnable(){...}).start();这也就是为什么我们可以传主线程的handler给adapter或者service或者任何其他文件,然后通过handler来sendmsg来更新UI。
在非主线程里面, handler.post(new Runnable(){...})是在子线程运行的,new Thread(new Runnable(){...}).start()也一样。 - 线程并发数量控制在2N+1 (N是cpu核数)
- 多线程访问同一个对象,要保证线程安全,不然容易抛出java.util.ConcurrentModificationException错误,怎么解决,保证线程安全:
- 给对象加同步锁
- 使用ConcurrentHashMap替换HashMap,CopyOnWriteArrayList替换ArrayList;
- 使用Vector替换ArrayList,Vector是线程安全的。Vector的缺点:大量数据操作时,由于线程安全,性能比ArrayList低.(这段话来至Bugly)
- FutureTask用来预加载,
- Semaphore 信号量 实现仿PV原语。
- AsyncTask就是一个封装了比较好的串行线程池(4.0+),在2.0+是并行的,但是现在2.0用的也不多,线程池配置不符合项目要求就自己定义比较灵活。
- HanlderThread的run()方法是一个无限制的循环,不需要了要quit掉。
- IntentService里面封装了HanlderThread,并用HanlderThread的Looper定义一个Hanlder来发送进来的intent携带的信息。是一个优先级比较高的service,用到服务的时候可以优先考虑。
第三方库
- 公司项目慎用Butter Knife,自己玩玩就行。
- EventBus这库,使用前,先画应用的数据流图!千万千万要画,数据流向不清晰,会导致后面很难维护。
- EventBus,普通的几次调用还可以,如果一两秒post它十几二十次,绝壁挂掉。
- 好吧,今天2016/11/8。我把EventBus的源码给过了一遍。为什么他会挂掉,是因为用了太多ThreadMode.Main,handler返回处理的太慢了?锁住了main thread。嗯,是这样的。
内存优化
- 关于内存抖动:发生在一个颜色采集器。
onDraw()、onLayout()是会频繁被调用的,应该避免对象分配的暴涨,和复杂的操作,诸如new Paint()等操作;有部分解决不了,用对象池解决。 - 关于内存飙升:不断地滑动viewpager。
- 使用懒加载,优化首次进入页面的速度和滑动的流畅度(UserVisibleHint=true时再加载网络数据和数据库数据)。然而我觉得如果不是很多实在没必要。
- 覆盖finalize方法,能比较简单查出内存泄漏的地方
@Override protected void finalize() throws Throwable { super.finalize(); Log.d("TGA", "===="+this.getClass().getSimpleName()); }
UDP
- 善用 socket重用。
- RTP,多用于流媒体传输、尽量保证大文件UDP传输的稳定性。
- 每次只能传64K,传文件实在不靠谱
- 255.255.255.255广播
- 短时间内收发包数量过多,容易丢包的问题
- 调试设置符合实际情况的时间间隔。
- 设置符合实际情况的缓冲区大小。
- 如果是包太大就分包发。
C++
- string→char*
//const char* std::str = "oaosj"; const char* c = str.c_str(); //char* std::str2 = "oaosj2"; int len = str2.lenght(); char* c2; c2= (char *)malloc((len+1)*sizeof(char)); str2.copy(c2,len,0);