android开发要避免的那些坑

Posted zhangke3016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android开发要避免的那些坑相关的知识,希望对你有一定的参考价值。

  • SparseArray 目前有很多地方从性能优化方说使用SparseArray来替换hashMap,来节省内存,提高性能。

  • Linkify.addLinks() 这个类可以更方便的为文本添加超链接。

  • ThumbnailUtils 这个类主要是用来处理缩略图相关的,有过这方面需求的,应该是用过这个类的。

  • Bitmap.extractAlpha();返回一个新的Bitmap,capture原始图片的alpha值。有的时候我们需要动态的修改一个元素的背景图片又不希望使用多张图片的时候,通过这个方法,结合Canvas和Paint可以动态的修改一个纯色Bitmap的颜色。

  • 静态变量不要直接或者间接引用Activity、Service等。这会使用Activity以及它所引用的所有对象无法释放,然后,用户操作时间一长,内存就会狂升。

  • Handler机制有一个特点是不会随着Activity、Service的生命周期结束而结束。也就是说,如果你Post了一个Delay的Runnable,然后在Runnable执行之前退出了Activity,Runnable到时间之后还是要执行的。如果Runnable里面包含更新View的操作,程序崩溃了。

  • 不少人在子线程中更新View时喜欢使用Context.runOnUiThread,这个方法有个缺点,就是一但Context生命周期结束,比如Activity已经销毁时,一调用就会崩溃。

  • PackageManager.getInstalledPackages这个方法经常使用,你可能不知道,当获取的结果数量比较多的时候,在某些机型上面调用它花费的时间可能秒级的,所以尽量在子线程中使用。另外,如果结果太多,超过系统设置的Binder数据最大传输量的上限,则会发生TransactionException,如果你使用这个方法获取机器上的己安装应用列表,最好做一下预防。

  • 如果使用Context.startActivity启动外部应用,最好做一下异常预防,因为寻找不到对应的应用时,会抛出异常。如果你要打开的是应用内的Activity,不防使用显式Intent,这样能提高系统搜索目标Activity的效率。

  • 判断手机是不是飞行模式 boolean isEnabled = Settings.System.getInt(context.getContentResolver(),
    Settings.System.AIRPLANE_MODE_ON, 0) == 1;

  • 如果子类实现Serializable接口而父类未实现时,父类不会被序列化,但此时父类必须有个无参构造方法,否则会抛InvalidClassException异常。

  • transient关键字修饰变量可以限制序列化。

  • 类继承之间的调用顺序 父类static成员 -> 子类static成员 -> 父类普通成员初始化和初始化块 -> 父类构造方法 ->子类普通成员初始化和初始化块 -> 子类构造方法

  • 华为手机无法显示log解决方案,.拨号界面输入(##2846579##) Service menu will appear.Go
    to “ProjectMenu” -> “Background Setting” -> “Log Setting”Open “Log switch” and set it to ON.Open “Log level setting” and set the log level you wish.

  • 后台service经常因为重启之类的出现onStartCommand()中的Intent传递的参数为null,通过在onStartCommand()中的返回值改成return super.onStartCommand(intent,Service.START_REDELIVER_INTENT, startId); 可以解决问题。下面介绍几个flag的意思:

flag解释
START_STICKY如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITYSTART_STICKY的兼容版本,但不保证服务被kill后一定能重启。
  • getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
    ViewGroup.LayoutParams.MATCH_PARENT);设置全屏方法一定要在setContentView之后

  • viewpager 的 setCurrentItem 一定要在 setAdapter 方法之后调用才会有效果.

  • 当前Activity的onPause方法执行结束后才会执行下一个Activity的onCreate方法,所以在onPause方法中不适合做耗时较长的工作,这会影响到页面之间的跳转效率;

  • 谨慎使用android的透明主题,透明主题会导致很多问题,比如:如果新的Activity采用了透明主题,那么当前Activity的onStop方法不会被调用;在设置为透明主题的Activity界面按Home键时,可能会导致刷屏不干净的问题;进入主题为透明主题的界面会有明显的延时感;

  • 不要在非UI线程中初始化ViewStub,否则会返回null;

  • 尽量不要通过Application缓存数据,这不稳定:不要在Android的Application对象中缓存数据!

  • (AnimationDrawable在Android5.0及以上的版本已有明显的优化)尽量不要使用AnimationDrawable,它在初始化的时候就将所有图片加载到内存中,特别占内存,并且还不能释放,释放之后下次进入再次加载时会报错;

  • 谨慎使用Android的多进程,多进程虽然能够降低主进程的内存压力,但会遇到如下问题:(1)不能实现完全退出所有Activity的功能(如果有同行在应用内采用多进程成功实现过完全退出程序欢迎沟通交流);(2)首次进入新启动进程的页面时会有延时的现象(有可能黑屏、白屏几秒,是白屏还是黑屏和新Activity的主题有关);(3)应用内多进程时,新启动一个进程都会重新跑一次Application的onCreate方法,不上重新创建一个Application,但会重新跑Application的onCreate,这样就不能在Application中缓存数据作为内存共享的途径了;(4)多进程间通过SharedPreferences共享数据时不稳定,具体可以查阅《Android开发艺术探索》。

  • View的面积越大绘制的时间就越长,透明通道对View的绘制速度影响很大;

  • 做自定义手写功能时,底层上报的点并不会都在MotionEvent中能够及时接收到,比如底层一秒钟200个点,上层收到的可能只有几十个点,为了提高手写的流畅度,在onTouchEvent中,通过MotionEvent中的getHistorySize能够获取到从底层传输到上层过程中所有的点;

  • 在Android4.0以后,在Manifest.xml中静态注册的广播,程序安装后必须启动一次才能接收到广播,比如你的应用监听开机启动的广播,必须要你的程序被运行过才能监听到;

  • 在2.3之前GC操作是不能并发进行的,也就是系统正在进行GC程序就只能阻塞住等待GC结束,在2.3之后GC操作改成了并发的方式进行,GC过程中不会影响程序的正常运行,但在GC操作的开始和结束还是会短暂阻塞一段时间。所以频繁的GC会导致使用应用的过程中卡顿,所以为了应用在使用过程中更流畅,需要尽量减少触发GC操作,这涉及到性能优化,对于静态代码的分析,AS已经很强大了,可以使用Android Studio的Analyze→Inspect Code…进行分析;

  • 在字符串处理方面,android.text.TextUtils这个类就能胜任绝任多数的工作public static boolean isEmpty(@Nullable CharSequence str) 这个方法判断字符串非null且非空
    public static CharSequence concat(CharSequence… text) 字符串连接
    public static boolean equals(CharSequence a, CharSequence b) 判断两个字符串对象的内容是否相等,内部进行了非null判断
    public static String htmlEncode(String s) 将html代码中的特殊字符进行转码处理
    这里写图片描述

  • 当判断一些常用的URI的时候,可以用android.webkit.URLUtil这个工具类
    这里写图片描述

  • android.text.format.DateUtils 这个类是Android提供的格式化日期的工具类。

    public static String formatDateTime(Context context, long millis, int
    flags); 这个方法可以格式化日期和时间,接收三个参数,其中第三个参数flags决定输出后的格式,如果只输出日期的话:
    DateUtils.formatDateTime(context,millis,DateUtils.FORMAT_SHOW_DATE)

    public static boolean isToday(long when) 判断日期是否是今天

    public static CharSequence getRelativeTimeSpanString(long startTime)
    返回与当前的相对时间的字符串比如微信的聊天列表上显示的上一条信息的时间,如果是今天就显示今天的时间,是昨天的就显示昨天,再久远一点的就显示日期(但是这个方法的最大只能精确到天,不能像微信那样显示到几秒前,几分钟前)。

  • tools schemas在新建Activity时IDE都会在xml的根节点默认加上tools的命名空间

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:app="http://schemas.android.com/apk/res-auto"
       xmlns:tools="http://schemas.android.com/tools"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"
       tools:context=".MainActivity"
       tools:showIn="@layout/activity_main_utils">
    
       <Button
           android:id="@+id/btn_select_date"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
    </LinearLayout>

    在写布局的时候经常会写一些无用的字符串用来预览布局,但是这些数据一般会在完成后删除,有时候在维护时为了方便预览再写上。这时可以使用tools的命名空间,比如tools:text=”点击选择日期”tools仅仅可以预览,在运行的状态下解析布局文件时就会忽略过这条属性。这非常适合用于预览布局。

  • 如果是在应用范围内的广播可以使用LocalBroadcastManager这个API(低版本用v4下的),更加安全高效,不必担心别的app伪造广播或收听你的广播做一些不好的事情。

  • Html.fromHtml() 如果你对Html熟悉的话,可以很迅速通过这个方法处理一些富文本操作。比如超链接和图文排版等处理。

  • Build.VERSION_CODES 有些时候我们的app需要根据不同的SDK版本进行执行不同的操作

  • ValueAnimator.reverse() 顺畅的取消动画效果

  • Formatter.formatFileSize() 这个方法会格式化数据的大小,根据输入的字节大小,返回 B KB MB GB等等(最大支持到 PB)。当然要注意的是输入的最大值是 Long.MAX_VALUE.

  • TypedValue.applyDimension() 首先这个方法我们可以用来对sp dp 和 px 之间的单位转换

  • 有些时候不能使用Application的Context,不然会报错(比如启动Activity,显示Dialog等)
    这里写图片描述
    *备注:大家注意看到有一些NO上添加了一些数字,其实这些从能力上来说是YES,但是为什么说是NO呢?下面一个一个解释: 1. 数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task,一般情况不推荐; 2. 数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用; 3. 数字3:在Receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视); 4. ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用

  • UncaughtExceptionHandler接口,再好的代码异常难免,利用此接口可以对未捕获的异常善后

  • Arrays类中的一系列关于数组操作的工具方法:binarySearch(),asList(),equals(),sort(),toString(),copyOfRange()等;Collections类中的一系列关于集合操作的工具方法:sort(),reverse()等;

  • Activity类中的onWindowFocusChanged(boolean),onNewIntent(intent)等回调方法;

  • PageTransformer接口,用来自定义ViewPager页面切换动画,用setPageTransformer(boolean,PageTransformer)方法来进行设置;

  • UrlQuerySanitizer——使用这个工具可以方便对 URL 进行检查。

  • ActivityOptions ——方便的定义两个Activity切换的动画。 使用ActivityOptionsCompat可以很好解决旧版本的兼容问题。

  • getParent().requestDisallowInterceptTouchEvent(true);剥夺父view对touch事件的处理权

  • IntentService,一个可以干完活后自己去死且不需要我们去管理子线程的Service

  • HandlerThread,代替不停new Thread开子线程的重复体力写法。

  • android:animateLayoutChanges=”true”,LinearLayout中添加View的动画的办法,支持通过setLayoutTransition()自定义动画。

  • AsyncQueryHandler,如果做系统工具类的开发,比如联系人短信辅助工具等,肯定免不了和ContentProvider打交道,如果数据量不是很大的情况下,随便搞,如果数据量大的情况下,了解下这个类是很有必要的,需要注意的是,这玩意儿吃异常。

  • android:descendantFocusability,ListView的item中CheckBox等元素抢焦点导致item点击事件无法响应时,除了给对应的元素设置
    focusable,更简单的是在item根布局加上android:descendantFocusability=”blocksDescendants”。

  • includeFontPadding=”false”,TextView默认上下是有一定的padding的,有时候我们可能不需要上下这部分留白,加上它即可。

  • Messenger,面试的时候通常都会被问到进程间通信,除了AIDL,还有这个可以装下~~(Android开发艺术探索中有讲)

  • EditTxt.setImeOptions, 使用EditText弹出软键盘时,修改回车键的显示内容。

  • java8中新增的LocalDate和LocalTime接口,Date虽然是个万能接口,但是它真的不好用,有了这俩,终于可以愉快的处理日期时间了。

  • WeakHashMap,直接使用HashMap有时候会带来内存溢出的风险,使用WaekHashMap实例化Map。当使用者不再有对象引用的时候,WeakHashMap将自动被移除对应Key值的对象。

  • 使用SnackBar的时候,不要使用view.getRootView()作为snackbar的view,华为荣耀7 会出问题。

  • 设置TextView单行显示的时候不要用Lines=1,而要用singleLine=”true”,因为魅族部分手机在设置Lines=1的时候,然后TextView的值全为数字的时候, 你就会懵逼了。

  • ArgbEvaluator可用于计算不同颜色值之间的插值,配合ValueAnimator.ofObject或者ViewPager.PageTransformer使用,可以实现不同颜色之间的平滑过渡。

  • Activity.recreate重新创建Activity。有什么用呢?可以在程序更换主题后,立马刷新当前Activity,而不会有明显的重启Activity的动画。(屏幕会变黑一下)

  • View.getContext顾名思义,就不用解释了吧

  • View.post方便在非UI线程对界面进行修改,与Handler的作用类似。并且由于post的Runnable会保证在该View绘制完成的前提下才调用,所以一般也可以用于获取View的宽高;还有一种是用getViewTreeObserver获取宽高。

  • Fragment.setUserVisibleHintFragment可以重写此方法,然后根据参数的布尔值(true的话表示当前Fragment对用户可见),来执行一些逻辑。

  • android:clipToPadding
    设置父view是否允许其子view在它的padding(这里指的是父View的padding)中绘制。是不是有点绕?举个实际场景吧:假如有个ListView,我们想要在初始位置时,第一项Item离顶部有10dp的距离,就可以在ListView的布局中加入android:clipToPadding=”false” android:paddingTop=”10dp”即可。

  • onTrimMemory,在Activity中重写此方法,会在内存紧张的时候回调(支持多个级别),便于我们主动的进行资源释放,避免OOM。

  • android:clipChildren (ViewGroup)——如果此属性设置为不可用,那么 ViewGroup 的子 View在绘制的时候会超出它的范围,在做动画的时候需要用到。

  • android:tileMode (BitmapDrawable)——可以指定图片使用重复填充的模式。

  • SharedPreference.Editor的apply是异步操作,不会返回成功的状态,而commit是同步操作,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后再操作下一个数据,从而降低了效率。

参考: http://www.zhihu.com/question/27818921
https://github.com/jiang111/awesome-android-tips

以上是关于android开发要避免的那些坑的主要内容,如果未能解决你的问题,请参考以下文章

Android相机开发那些坑

EFCore2.2中使用Group By的那些坑及解决方法

android开发的注意事项AndroidManifest里面的那些坑

使用JDK的同步容器时,应该避免那些坑?

eclipse转Android studio遇到的那些坑

使用JDK的同步容器时,应该避免那些坑?