你应该知道的那些Android小经验

原文出处:http://jayfeng.com/

做Android久了,就会踩很多坑,被坑的多了就有经验了,闲暇之余整理了部分,现挑选一些重要或者偏门的“小”经验做个记录。

查看SQLite日志

  1. adb shell setprop log.tag.SQLiteLog V
  2. adb shell setprop log.tag.SQLiteStatements V

因为实现里用了Log.isLoggable(TAG, Log.VERBOSE)做了判断,LessCode的LogLess中也参考了这种机制:LogLess
使用这种方法就可以在Release版本也能做到查看应用的打印日志了。

PNG优化

APK打包会自动对PNG进行无损压缩,如果自行无损压缩是无效的。
当然进行有损压缩是可以的:https://tinypng.com/

Tcpdump抓包

有些模拟器比如genymotion自带了tcpdump,如果没有的话,需要下载tcpdump:
http://www.strazzere.com/android/tcpdump
把tcpdump push到/data/local下,抓包命令:

  1. adb shell  /data/local/tcpdump -i any -p -s 0 -w /sdcard/capture.pcap

查看签名

很多开发者服务都需要绑定签名信息,用下面的命令可以查看签名:

  1. keytool -list -v -keystore release.jks

注意,这个是需要密码的,可以查看MD5, SHA1,SHA256等等。

单例模式(懒汉式)的更好的写法

特别说到这个问题,是因为网上很多这样的代码:

  1. public class Singleton {
  2. private static Singleton instance;
  3. private Singleton (){}
  4. public static Singleton getInstance() {
  5. if (instance == null) {
  6. instance = new Singleton();
  7. }
  8. return instance;
  9. }
  10. }

这种写法线程不安全,改进一下,加一个同步锁:

  1. public class Singleton {
  2. private static Singleton instance;
  3. private Singleton (){}
  4. public static synchronized Singleton getInstance() {
  5. if (instance == null) {
  6. instance = new Singleton();
  7. }
  8. return instance;
  9. }
  10. }

网上这样的代码更多,可以很好的工作,但是缺点是效率低。
实际上,早在JDK1.5就引入volatile关键字,所以又有了一种更好的双重校验锁写法:

  1. public class Singleton {
  2. private volatile static Singleton singleton;
  3. private Singleton (){}
  4. public static Singleton getSingleton() {
  5. if (singleton == null) {
  6. synchronized (Singleton.class) {
  7. if (singleton == null) {
  8. singleton = new Singleton();
  9. }
  10. }
  11. }
  12. return singleton;
  13. }
  14. }

注意,别忘记volatile关键字哦,否则就是10重,100重也可能还是会出问题。
上面是用的最多的,还有一种静态内部类写法更推荐:

  1. publlic class Singleton {
  2. private Singleton() {}
  3. private static class SingletonLoader {
  4. private static final Singleton INSTANCE = new Singleton();
  5. }
  6. public static Singleton getInstance() {
  7. return SingletonLoader.INSTANCE;
  8. }
  9. }

多进程Application

是不是经常发现Application里的方法执行了多次?百思不得其解。
因为当有多个进程的时候,Application会执行多次,可以通过pid来判断那些方法只执行一次,避免浪费资源。

隐式启动Service

这是Android5.0的一个改动,不支持隐式的Service调用。下面的代码在Android 5.0+上会报错:Service Intent must be explicit:

  1. Intent serviceIntent = new Intent();
  2. serviceIntent.setAction("com.jayfeng.MyService");
  3. context.startService(serviceIntent);

可改成如下:

  1. // 指定具体Service类,或者有packageName也行
  2. Intent serviceIntent = new Intent(context, MyService.class);
  3. context.startService(serviceIntent);

fill_parent的寿命

在Android2.2之后,支持使用match_parent。你的布局文件里是不是既有fill_parent和match_parent显得很乱?
如果你现在的minSdkVersion是8+的话,就可以忽略fill_parent,统一使用match_parent了,否则请使用fill_parent。

ListView的局部刷新

有的列表可能notifyDataSetChanged()代价有点高,最好能局部刷新。
局部刷新的重点是,找到要更新的那项的View,然后再根据业务逻辑更新数据即可。

  1. private void updateItem(int index) {
  2. int visiblePosition = listView.getFirstVisiblePosition();
  3. if (index - visiblePosition >= 0) {
  4. //得到要更新的item的view
  5. View view = listView.getChildAt(index - visiblePosition);
  6. // 更新界面(示例参考)
  7. // TextView nameView = ViewLess.$(view, R.id.name);
  8. // nameView.setText("update " + index);
  9. // 更新列表数据(示例参考)
  10. // list.get(index).setName("Update " + index);
  11. }
  12. }

强调一下,最后那个列表数据别忘记更新, 不然数据源不变,一滚动可能又还原了。

系统日志中几个重要的TAG

  1. // 查看Activity跳转
  2. adb logcat -v time | grep ActivityManager
  3. // 查看崩溃信息
  4. adb logcat -v time | grep AndroidRuntime
  5. // 查看Dalvik信息,比如GC
  6. adb logcat -v time | grep "D\/Dalvik"
  7. // 查看art信息,比如GC
  8. adb logcat -v time | grep "I\/art"

一行居中,多行居左的TextView

这个一般用于提示信息对话框,如果文字是一行就居中,多行就居左。
在TextView外套一层wrap_content的ViewGroup即可简单实现:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent">
  4. <!-- 套一层wrap_content的ViewGroup -->
  5. <LinearLayout
  6. android:layout_width="wrap_content"
  7. android:layout_height="wrap_content"
  8. android:layout_centerInParent="true">
  9. <TextView
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:text="@string/hello_world" />
  13. </LinearLayout>
  14. </RelativeLayout>

setCompoundDrawablesWithIntrinsicBounds()

网上一大堆setCompoundDrawables()方法无效不显示的问题,然后解决方法是setBounds,需要计算大小…
不用这么麻烦,用setCompoundDrawablesWithIntrinsicBounds()这个方法最简单!

计算程序运行时间

为了计算一段代码运行时间,一般的做法是,在代码的前面加个startTime,在代码的后面把当前时间减去startTime,这个时间差就是运行时间。
这里提供一种写起来更方便的方法,完全无时间逻辑,只是加一个打印log就够了。

  1. // 测试setContentView()的时间
  2. Log.d("TAG", "Start");
  3. setContentView(R.layout.activity_http);
  4. Log.d("TAG", "End");

没有计算时间的逻辑,这能测出来?
把日志过滤出来,运行命令“adb logcat -v time | grep TAG”:

  1. 03-18 14:47:25.477 D/TAG     (14600): Start
  2. 03-18 14:47:25.478 D/TAG     (14600): End

通过-v time参数,可以比较日志左边的时间来算出中间的代码运行的时间。

JAVA引用类型一览表

对象引用:强引用 > 软引用 > 弱引用 > 虚引用。

引用类型 回收时机 用途 生存时间
强引用 从来不会 对象的一般状态 JVM停止运行时终止
软引用 在内存不足时 对象缓存 内存不足时终止
弱引用 在垃圾回收时 对象缓存 GC运行后终止
虚引用 在垃圾回收时 对象跟踪 GC运行后终止

Context使用场景

为了防止Activity,Service等这样的Context泄漏于一些生命周期更长的对象,可以使用生命周期更长的ApplicationContext,但是不是所有的Context的都能替换为ApplicationContext
这是网上流传的一份表格:

  Application Activity Service ContentProvider BroadcastReceiver
Show Dialog
Start Activity
Layout Inflation
Start Service
Bind Service
Send Broadcast
Regist BroadcastReceiver
Load Resource Value

图片缓存大小

现在很多图片库需要给图片设置一个最大缓存,但是这个值设置多少合适呢?
高端机和低端机的配置显然应该不同,可以考虑设置一个动态值。
建议设置为应用可用内存的1/8:

  1. int memoryCache = (int) (Runtime.getRuntime().maxMemory() / 8);

系统内置的一些工具类

在AOSP源码全局搜了一下包含Util关键字的类,整理出这个列表供大家参考:

  1. // 系统
  2. ./android/database/DatabaseUtils.java
  3. ./android/transition/TransitionUtils.java
  4. ./android/view/animation/AnimationUtils.java
  5. ./android/view/ViewAnimationUtils.java
  6. ./android/webkit/URLUtil.java
  7. ./android/bluetooth/le/BluetoothLeUtils.java
  8. ./android/gesture/GestureUtils.java
  9. ./android/text/TextUtils.java
  10. ./android/text/format/DateUtils.java
  11. ./android/os/FileUtils.java
  12. ./android/os/CommonTimeUtils.java
  13. ./android/net/NetworkUtils.java
  14. ./android/util/MathUtils.java
  15. ./android/util/TimeUtils.java
  16. ./android/util/ExceptionUtils.java
  17. ./android/util/DebugUtils.java
  18. ./android/drm/DrmUtils.java
  19. ./android/media/ThumbnailUtils.java
  20. ./android/media/ImageUtils.java
  21. ./android/media/Utils.java
  22. ./android/opengl/GLUtils.java
  23. ./android/opengl/ETC1Util.java
  24. ./android/telephony/PhoneNumberUtils.java
  25. // 设计和支持库
  26. ./design/src/android/support/design/widget/ViewGroupUtils.java
  27. ./design/src/android/support/design/widget/ThemeUtils.java
  28. ./design/src/android/support/design/widget/ViewUtils.java
  29. ./design/lollipop/android/support/design/widget/ViewUtilsLollipop.java
  30. ./design/base/android/support/design/widget/AnimationUtils.java
  31. ./design/base/android/support/design/widget/MathUtils.java
  32. ./design/honeycomb/android/support/design/widget/ViewGroupUtilsHoneycomb.java
  33. ./v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchUIUtil.java
  34. ./v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchUIUtilImpl.java
  35. ./v7/recyclerview/src/android/support/v7/util/MessageThreadUtil.java
  36. ./v7/recyclerview/src/android/support/v7/util/AsyncListUtil.java
  37. ./v7/recyclerview/src/android/support/v7/util/ThreadUtil.java
  38. ./v7/recyclerview/tests/src/android/support/v7/widget/AsyncListUtilLayoutTest.java
  39. ./v7/recyclerview/tests/src/android/support/v7/util/AsyncListUtilTest.java
  40. ./v7/recyclerview/tests/src/android/support/v7/util/ThreadUtilTest.java
  41. ./v7/appcompat/src/android/support/v7/graphics/drawable/DrawableUtils.java
  42. ./v7/appcompat/src/android/support/v7/widget/DrawableUtils.java
  43. ./v7/appcompat/src/android/support/v7/widget/ThemeUtils.java
  44. ./v7/appcompat/src/android/support/v7/widget/ViewUtils.java
  45. ./v4/tests/java/android/support/v4/graphics/ColorUtilsTest.java
  46. ./v4/jellybean-mr1/android/support/v4/text/TextUtilsCompatJellybeanMr1.java
  47. ./v4/jellybean/android/support/v4/app/BundleUtil.java
  48. ./v4/jellybean/android/support/v4/app/NavUtilsJB.java
  49. ./v4/java/android/support/v4/app/NavUtils.java
  50. ./v4/java/android/support/v4/database/DatabaseUtilsCompat.java
  51. ./v4/java/android/support/v4/graphics/ColorUtils.java
  52. ./v4/java/android/support/v4/text/TextUtilsCompat.java
  53. ./v4/java/android/support/v4/util/TimeUtils.java
  54. ./v4/java/android/support/v4/util/DebugUtils.java
  55. ./v4/java/android/support/v4/content/res/TypedArrayUtils.java

这么多工具类,一定可以找到对你有用的。

ClipPadding

这个不多说,ListView的ClipPadding设为false,就能为ListView设置各种padding而不会出现丑陋的滑动“禁区”了。

强大的dumpsys

dumpsys可以查看系统服务和状态,非常强大,可通过如下查看所有支持的子命令:

  1. dumpsys | grep "DUMP OF SERVICE"

这里列举几个稍微常用的:

子命令 备注
activity 显示所有的activities的信息
cpuinfo 显示CPU信息
window 显示键盘,窗口和它们的关系
meminfo 内存信息(meminfo $package_name or $pid 使用包名或者进程id显示内存信息)
alarm 显示Alarm信息
statusbar 显示状态栏相关的信息(找出广告通知属于哪个应用)
usagestats 每个界面启动的时间

bugreport命令

很多人都用过adb logcat,但是如果想要更详细的信息,logcat则无能为力。
所以大多数手机厂商测试更多的是用adb bugreport来抓log给开发人员分析。

  1. // 除了log,还包括启动后的系统状态,包括进程列表,内存信息,VM信息等等
  2. // 而且不像logcat是一直打印的,bugreport命令输出到当前时间就停止结束了。
  3. adb bugreport > main.log

dpi文件夹的换算比例

之前的ldpi基本可以抛弃了,主流的dpi已经从很早之前的mdip转移到了xhdpi了,特别提醒。

PPI RESOLUTION DP PX
mdpi(160dp) 320P 1 1
hdpi(240dp) 480P 1 1.5
xhdpi(320dp) 720P 1 2
xxhdpi(480dpi) 1080P 1 3

更新媒体库文件

以前做ROM的时候经常碰到一些第三方软件(某音乐APP)下载了新文件或删除文件之后,但是媒体库并没有更新,因为这个是需要第三方软件主动触发。

  1. // 通知媒体库更新单个文件状态
  2. Uri fileUri = Uri.fromFile(file);
  3. sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,fileUri));

媒体库会在手机启动,SD卡插拔的情况下进行全盘扫描,不是实时的而且代价比较大,所以单个文件的刷新很有必要。

Monkey参数

大家都知道,跑monkey的参数设置有一些要注意的地方,比如太快了不行不切实际,太慢了也不行等等,这里给出一个参考:

  1. adb shell monkey -p <packageName> -s 1000 --ignore-crashes --ignore-timeouts --ignore-security-exceptions  --pct-trackball 0 --pct-nav 0 --pct-majornav 0 --pct-anyevent 0  -v --throttle 300 1200000000

一边跑monkey,一边抓log吧。

小结

无论是大经验还是小经验,有用就是好经验。

时间: 2024-08-13 15:12:01

你应该知道的那些Android小经验的相关文章

Android小经验

转载自:http://mp.weixin.qq.com/s?__biz=MzA4MjU5NTY0NA==&mid=404388098&idx=1&sn=8bbbba7692dca68cdda2212dec4d86c0&scene=21#wechat_redirect 今天是冯建同学投稿.总结他在Android开发方面的各种小经验,我认为很有意义,所谓经验丰富有时候是指积累的这些小经验许多,他这篇分享相信会帮助到一些朋友.我也曾推荐过他的 APK魔鬼瘦身 一文.没看过的朋友也

Android开发的16条小经验总结

Android开发的16条小经验总结,希望对各位搞Android开发的朋友有所帮助. 1. TextView中的getTextSize返回值是以像素(px)为单位的, 而setTextSize()是以sp为单位的. 所以如果直接用返回的值来设置会出错,解决办法是用setTextSize()的另外一种形式,可以指定单位: setTextSize(int unit, int size)    TypedValue.COMPLEX_UNIT_PX : Pixels    TypedValue.COMP

提高工作效率的16条Android开发小经验

笔者在经历了多个Android开发项目之后,个人积累也从别处学习了很多在Android开发中非常实用的小经验.下面从中选择了最实用的16条,分享给大家. 1.TextView中的getTextSize返回值是以像素(px)为单位的,而setTextSize()是以sp为单位的.所以如果直接用返回的值来设置会出错,解决办法是用setTextSize()的另外一种形式,可以指定单位: 1 2 3 4 <span style="font-size:16px;">setTextSi

Android开发中15条小经验

Android开发中15条小经验 1. TextView中的getTextSize返回值是以像素(px)为单位的,而setTextSize()是以sp为单位的. 所以如果直接用返回的值来设置会出错,解决办法是用setTextSize()的另外一种形式,可以指定单位: setTextSize(intunit,intsize) TypedValue.COMPLEX_UNIT_PX:Pixels TypedValue.COMPLEX_UNIT_SP:ScaledPixels TypedValue.CO

关于achartengine的使用一些小经验

最近项目上要使用图表,便开始在网上找各种图表架包,好看的都是收费的,最后还是决定用google的achartengine.achartengine使用起来还算好,就是修改样式很烦.下面就分享下开发经验吧.所有的chart都分两块,一块是Renderer(如XYMultipleSeriesRenderer,我的理解是,这个renderer为视图render的模板,就是你想用什么图标,一个图图表基本分2层,这个是最下面一层),一块是Dataset(如XYMultipleSeriesDataset,用

Android 学习经验之分享

刚学Android开发的人肯定想知道过来人是怎样入门的,有哪些Android学习经验,怎样能少走弯路.下面小编就跟大家分享一下自己当初学Android的入门经验,虽算不上经典,但都是真正讲出了自己的学习过程,尽管每个人的学习方法和习惯等不同,但或许也可以从中学到东西. 一.看Android开发视频: 我刚开始接触android的时候,主要是跟着网上Android开发视频入的门,自己跟着一点一点的敲代码,就这样算是简单的入门,现在很多在线学习视频网站上面有很多的Android视频课程学习资源,记得

Android -- 小问题 InputStream的read方法读取字节不完全的问题

关于InputStream.read(byte[] b)和InputStream.read(byte[] b,int off,int len)这两个方法都是用来从流里读取多个字节的,有经验的程序员就会发现,这两个方法经常 读取不到自己想要读取的个数的字节.比如第一个方法,程序员往往希望程序能读取到b.length个字节,而实际情况是,系统往往读取不了这么多.仔细阅读Java的API说明就发现了,这个方法 并不保证能读取这么多个字节,它只能保证最多读取这么多个字节(最少1个).因此,如果要让程序读

OC开发学习过程中的一些小经验

1.引入头文件以及框架 :  @import   XXXX         XXXX表示需要引入的文件/框架2.头文件引用循环:两个头文件相互包含时,将其中一个头文件的类用@class引入3.设置边角幅度 :[  XX.layer setCornerRadius:100 ]  ;    XX表示需要设置边角的对象,一般是给按钮设置,边角幅度大小跟最后数字取值关联.4.多个引号处理方法:引号前加\,如果还有括号影响,就再单独用@“ “将其框起来..专业术语叫转义字符.. 5.在UIWebview中

新产品为了效果,做的比较炫,用了很多的图片和JS,所以前端的性能是很大的问题,分篇记录前端性能优化的一些小经验。

第一篇:HTTP服务器 因tomcat处理静态资源的速度比较慢,所以首先想到的就是把所有静态资源(JS,CSS,image,swf) 提到单独的服务器,用更加快速的HTTP服务器,这里选择了nginx了,nginx相比apache,更加轻量级, 配置更加简单,而且nginx不仅仅是高性能的HTTP服务器,还是高性能的反向代理服务器. 目前很多大型网站都使用了nginx,新浪.网易.QQ等都使用了nginx,说明nginx的稳定性和性能还是非常不错的. 1. nginx 安装(linux) htt