Android 学习历程摘要之三

记录下Android学习与实践过程中遇到的问题和学习要点,可能有些地方可能理解不对,如果有朋友看到的话麻烦指正我一下,万分感谢

  • 速率判断类Velocity类,当要获取速度之前需要先调用computeCurrentVelocity方法来计算
  • 多线程:可以继承Thread类内部放置一个变量来作为每个线程自身的开关,避免使用全局变量,不好控制每个线程
  • 设置LayoutParams时需要设置该View的父布局下的LayoutParams,否则会出现类型转换异常
  • Toolbar中的minHeight设置后等于其menu的高度,单纯设置Height不会影响menu的高度
  • TextView拦截事件clickable和longClickable都为false可解除
  • 使用ImageView控件时如果需要图片与字一样大,可以使用background来设置图片,同时使用layout_alignBottom以及layout_alignTop与字对齐则会自动拉伸
  • 读取文件如果是字符文件,可以通过FileReader类,如果是二进制数据文件,可以通过FileInputStream类
  • 存储在应用目录下的私有数据文件,通常不会通过File类的方式直接进行读写,而是通过一些封装过的类或函数来操作,如Context.openFileOutput来打开存储在应用数据目录下的私有文件进行写入
  • 设置文件(SP)的加载与写入都会在独立的线程上进行,避免阻塞主线程,而所有设置文件的读写操作,都是线程安全的,开发时可以放心的在不同线程上对设置文件进行读取或者写入.但设置文件的读写并不是进程安全的,也就是说如果应用是多进程的,不要在不同进程中同时操作一份设置文件,这可能导致数据发生错乱。
  • 并发问题是使用数据库过程中最容易碰到的问题,Android框架层SqliteDatabase会对所有数据库对象进行加锁保护,通过同一个SqliteDatabase对象访问数据库是线程安全地,但是一旦出现了指向同一个数据库的多个SqliteDatabase对象同时在多个线程中被使用,那就跳脱了SqliteDatabase中的锁保护,就会导致数据库出现被锁的异常。因此在实践中,需要保证同时访问数据库的SqliteDatabase对象仅有一个。
  • 在默认情况下,DefaultHttpClient对象是线程非安全的,开发者不能在多个线程中同时调用该DefaultHttpClient对象的方法。要保证HttpClient的线程安全性,可以为它设置线程安全的管理对象。可以使用AndroidHttpClient来代替,本质上该对象是对DefaultHttpClient进行了封装和初始化,并将HttpClient设置为线程安全,详见《Android开发精要》P269
  • 状态栏具有透明度且布局上移置于状态栏底部
    findViewById(R.id.toolbar).setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
  • OpenGL开辟本地内存时需要注意使用的是allocate,还是allocateDirect,第一种分配方式产生的内存开销是在JVM中的,而第二种的分配方式产生的开销在JVM之外,页就是系统级的内存分配。在操作效率上,当操作数据量很小时,两种分配方式操作使用时间基本是相同的,第一种方式有时可能会更快,但是当数据量很大时,第二种方式会远远大于第一种的分配方式。
  • 当我们启动一个Service时,系统会倾向于将这个Service所依赖的进程进行保留,这样就会导致这个进程变得非常消耗内存。为了能够控制Service的生命周期,Android官方推荐的最佳解决方案就是使用IntentService,这种Service的最大特点就是当后台任务执行结束后会自动停止,从而极大程度上避免了Service内存泄漏的可能性。
  • onTrimMemory()方法有很多种其它类型的回调,可以在手机内存降低的时候及时通知我们。
  • Android API当中提供了一些优化过后的数据集合工具类,如SparseArray,SparseBooleanArray,以及LongSparseArray等,使用这些API可以让我们的程序更加高效。
  • 使用枚举通常会比使用静态常量要消耗两倍以上的内存,在Android开发当中我们应当尽可能地不使用枚举。
  • 任何一个Java类,包括内部类、匿名类,都要占用大概500字节的内存空间。
  • 任何一个类的实例要消耗12-16字节的内存开支,因此频繁创建实例也是会一定程序上影响内存的。
  • 在使用HashMap时,即使你只设置了一个基本数据类型的键,比如说int,但是也会按照对象的大小来分配内存,大概是32字节,而不是4字节。因此最好的办法就是像上面所说的一样,使用优化过的数据集合。
  • 手机开启了开发者模式中的不保留活动会导致所有activity在不可见的时候被回收,从而部分数据异常,比如相机预览会黑屏但仍然可以拍照等等,可以在onSaveInstance中做数据保存,在onCreate中进行数据恢复
  • 手机关闭了自身的下载服务会导致下载失败,如果应用的下载功能调用的是DownloadManger的话
  • EditText光标可见后(cursorVisibile),同时设置光标背景(textCursorDrawable)为@null的话,则光标颜色与正文颜色相同,也可自定义,此刻解决光标看起来不可见的bug
  • Button的英文文案始终大写的bug可通过设置textAllCaps为false解决,TextView也有此属性
  • AsyncTask一般用于比较耗时,且不常用的刷新,但是AsyncTask有最大并行线程数的限制
  • 点九图只能适用于拉伸的情况,对于压缩的情况并不适用,如果需要适配很多分辨率的屏幕时需要把点九图做的小一点。
  • Iterator在工作的时候,是不允许被迭代的对象被改变的,会抛出java.util.ConcurrentModificationException。Iterator被创建的时候,建立了一个内存索引表(单链表),这 个索引表指向原来的对象,当原来的对象数量改变的时候,这个索引表的内容没有同步改变,所以当索引指针往下移动的时候,便找不到要迭代的对象,于是产生错 误。List、Set等是动态的,可变对象数量的数据结构,但是Iterator则是单向不可变,只能顺序读取,不能逆序操作的数据结构,当 Iterator指向的原始数据发生变化时,Iterator自己就迷失了方向。
  • TextView.setMovementMethod(ScrollingMovementMethod.getInstance());可使TextView可滚动
  • android:clipToPadding=”false”可以解决视图被padding的距离给隐藏掉一部分的问题
  • 回收bitmap必须保证与bitmap绑定的ImageView等其他事物与之解绑,否则程序会出现错误
  • 子线程中做UI布局等操作时需要谨慎查找所调用API是否有需要刷新界面,此处可能有适配性问题,与不同android系统定制程度不同有关,建议与UI相关的操作不要放入子线程
  • DrawerLayout默认边距为64dp,可在其布局的第二个控件中设置marginRight来调整,比如-10则可变为54
  • 使用ListView或者RecyclerView创建子View调用LayoutInflater.inflate方法时,如果传入的父view为null,则会导致该子View的布局参数LayoutParams为null,从而其宽高则为自适应,所以应传入父view参数进而系统会通过父view所分配的宽高(即通过子view最外面布局所设置的宽高)来设置,默认为包裹内容。当子view宽高为match_parent时,父view所分配的子view的宽度为子view的包裹内容宽度,可通过设置minWidth等方法来设置想要的宽度
  • Seekbar的背景资源中间内容区域高度可以按UI想要的定,但是需要上下留白,左边黑点区域点在透明区域用以拉伸透明区域,否则拉伸的会是内容区域,导致seekbar高度过高,和想要的效果不一致
  • 可以使用setImageURI来替换掉setImageResource的背景
  • 相机预览布局宽高应优先屏幕宽度充满,按照比例选择高度,被覆盖的部分拍照后进行剪裁,如果根据界面来选择高度进而计算宽度,会导致适配问题,出现预览界面偏移,本质原因预览的尺寸被压缩,原本这个尺寸高度下的宽度是刚好充满屏幕的,但是由于高度被压缩,进而宽度变小,一般预览界面高度从屏幕最顶部开始,拍照后进行截取
  • view的绘制流程 度量onMeasure-布局onLayout-绘制onDraw
    对控件外部调用layout只是暂时的, 因为每个view的onLayout是由父View调用的, 参数也是由父view决定的, 一旦父view重绘, 你外面设置的这些值都会被覆盖
  • gridView异步加载图片混乱
    使用ImageLoader之类框架
    判断加载完bitmap后此时的ImageView是否还是需要设置该Bitmap的ImageView,如果不是则置为空等待后面的线程来设置
  • Fragment中ViewPager保存上一次的状态而导致setCurrentItem无效
    在onResume中设置
  • layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);会导致控件永远居中

版权声明

![Creative Commons BY-NC-ND 4.0 International License](/images/cc.png)

Lam’s Blog by Binghe Lin is licensed under a Creative Commons BY-NC-ND 4.0 International License.
林炳河创作并维护的Lam’s Blog采用创作共用保留署名-非商业-禁止演绎4.0国际许可证

本文首发于Lam’s Blog - Knowledeg as Action,版权所有,侵权必究。

本文永久链接:http://linbinghe.com/2017/3742c038.html