安卓代码中常用的代码以及问题收集

EnglishVersion ->_->:https://raw.githubusercontent.com/jiang111/awesome-android-tips/master/README-en.md

值得收藏的 AS 插件 ->_->:https://github.com/jiang111/awesome-androidstudio-plugins 

这里收集了大家常用的一些 Android 代码,持续更新中,内容来自自己的平时积累和网络上看到的文章,部分原文地址在最下方。如有错误欢迎指正,如有侵权,请联系我删除。里面可能会有重复内容,请忽略或者提醒我删除。

  • setBackgroundResource(0) 可以移除 View 的背景色

  • Resources.getSystem().getDisplayMetrics().density 可以不用 Context 也能获取屏幕密度哦

  • 通过重载 ViewGroup 的 dispatchDraw 可以实现一个简单的蒙版效果。 例如下拉刷新时,可以在 contentView 上加一层遮罩。 canvas.drawRect(0, mContentView.getTranslationY(), getWidth(), getHeight(), mMaskPaint);

  • new 出来的 View 可以用 View.generateViewId() (API 17 以上可用) 生成 id,系统保证唯一

  • 使用 GridView 时 android:padding 和 android:clipToPadding="false" 配合使用效果更好哦。

  • 在布局文件中,如果只是为了占位,可以用 Space 来取代 View。 最棒的一点是 Space 可以跳过 Draw 这个过程。

  • TypedValue.applyDimension(int unit, float value, DisplayMetrics metrics) 方便 dp, px, sp 之间的转换。

  • Activity.startActivities() 这个方法最直接的理解就是使用 intent 开启多个 Activity

  • TextUtils.isEmpty() 如果传入的 String 为 NULL 或者 Length 为 0 的话就返回 true。

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

  • TextView.setError() 设置文本框错误提醒

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

  • PhoneNumberUtils.convertKeypadLettersToDigits 这个方法简单粗暴,会将输入的字母根据键盘上的映射转换为数字。

  • ArgbEvaluator ArgbEvaluator.evaluate(float fraction, Object startValue, Object endValue);根据一个起始颜色值和一个结束颜色值以及一个偏移量生成一个新的颜色,分分钟实现类似于微信底部栏滑动颜色渐变。

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

  • DateUtils.formatDateTime()) 这个方法可以输出相应格式化的时间或者日期

  • Pair 这个类 可以用来存储存储一”组”数据。但不是 key 和 value 的关系。

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

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

  • android.media.ThumbnailUtils 这个类主要是用来处理缩略图相关的工作,比如:用来获取媒体(图片、视频)的缩略图

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

  • 模块间有消息需要传递时,使用 LocalBroadcastManager 替代 Listener 进行模块解耦。除了解耦,这样发送消息和执行消息差一个线程循环,可以减小方法的调用链,我这就碰到一次方法调用链太长导致 StackOverflow 的问题。

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

  • Handler 机制有一个特点是不会随着 Activity、Service 的生命周期结束而结束。也就是说,如果你 Post 了一个 Delay 的 Runnable,然后在 Runnable 执行之前退出了 Activity,Runnable 到时间之后还是要执行的。如果 Runnable 里面包含更新 View 的操作,可能会造成内存泄露,所以可以在 onDestory() 的时候调用 removeCallbacksAndMessages 来移除这个 Handler 所对应等待执行的 message。

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

  • SharedPreferences.Editor.commit 这个方法是同步的,一直到把数据同步到 Flash 上面之后才会返回,由 IO 操作的不可控,尽量使用 apply 方法代替。apply 只在 API Level>=9 才会支持,需要做兼容。不过,最新的support v4 包已经为我们做好了处理,使用SharedPreferencesCompat.EditorCompat.getInstance().apply(editor) 即可。

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

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

  • Application 的生命周期就是进程的生命周期。只有进程被干掉时,Application 才会销毁。哪怕是没有 Activity、Service 在运行,Application 也会存在。所以,为了减少内存压力,尽量不要在 Application 里面引用大对象、Context 等。

  • 设置全屏方法有 2 种:1.通过代码设置,2 通过 manifest 文件设置。用代码设置全屏时 app 在我们应用运行后,可能会看到短暂的状态栏,然后才全屏,而第二种方法是不会有这种情况的,所以推荐第二种。

    //方法 1: 
    //无 title   
    requestWindowFeature(Window.FEATURE_NO_TITLE);    
    getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN,WindowManager.LayoutParams. FLAG_FULLSCREEN);   
    //必须在 setContentView()之前调用
    setContentView(R.layout.main);  
    //方法 2:
    
    
  • viewpager 的 setCurrentItem 一定要在 setAdapter 方法之后调用才会有效果.

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

  • TabLayout 修改字体的方法 官方的 TabLayout 没有提供修改 TextView size 的方法,可以新建一个 style CustomTabLayoutTextAppearance 继承 TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse ,然后增加 item ,设置 android:textAllCaps 为 true ,再设置 android:textSize 为你想设置的大小。 再在 TabLayout 的布局文件里设置 app:tabTextAppearance="@style/CustomTabLayoutTextAppearance" 即可。 

  • 遍历 HashMap 的最佳方法

    public static void printMap(Map mp) {
      for (Map.Entry m : mp.entrySet()) {
              System.out.println(m.getKey() + ":" + m.getValue());
          }
    }
    
  • 使用 Java 在一个区间内产生随机整数数

    public static int randInt(int min, int max) {
      Random rand = new Random();
      int randomNum = rand.nextInt((max - min) + 1) + min;
      return randomNum;
    }
    
  • 如果子类实现 Serializable 接口而父类未实现时,父类不会被序列化,但此时父类必须有个无参构造方法,否则会抛 InvalidClassException 异常。

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

  • 当使用 JakeWharton 的 TabPageIndicator 时,如果需要先做一些耗时的操作,然后再展示 TabPageIndicator 的话,需要先设置 mIndirector.setVisibility(View.GONE);然后耗时任务结束以后再 mIndirector.setVisibility(View.VISIBLE);否则会报错

  • 类继承之间的调用顺序 父类 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_COMPATIBILITY|START_STICKY 的兼容版本,但不保证服务被 kill 后一定能重启。 |

  • 不能在 Activity 没有完全显示时显示 PopupWindow 和 Dialog

  • 在多进程之间不要用 SharedPreferences 共享数据,虽然可以(MODE_MULTI_PROCESS),但极不稳定

  • 有些时候不能使用 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 用于使用。
  • 谨慎使用 Android 的透明主题,透明主题会导致很多问题,比如:如果新的 Activity 采用了透明主题,那么当前 Activity 的 onStop 方法不会被调用;在设置为透明主题的 Activity 界面按 Home 键时,可能会导致刷屏不干净的问题;进入主题为透明主题的界面会有明显的延时感
  • 不要在非 UI 线程中初始化 ViewStub,否则会返回 null

  • 尽量不要通过 Application 缓存数据,这不稳定

  • 华为手机无法打开 USB 调试的问题,

  • 插好数据线,拨号界面 输入 ##2846579## 进入工程模式
  • projectmenu→3 后台设置→4USB 端口配置→Balong 调试模式,点确定
  • 不要拔线,退出工程模式,直接重启手机,电脑中显示可移动磁盘(若仍未出现,重复步骤 1、2)
  • 这个是关闭 USB 调试的情况下电脑中使用手机的可移动磁盘的方法,使用后下拉菜单中 usb 选项也回来了。

  • android listview 中的消息被软键盘遮挡了,在设置 listview 的时候加上 android:transcriptMode="normal"就好了

  • TextUtils 是一个非常好用的工具类,把 List 转成字符串,逗号分隔,逗号分隔的 String 字符串,切割成 List,分别可以用 TextUtils 的 join 和 split 方法。如果要对 List 去重,则可以用 Collection 的 frequency 方法。

  • 在 activity 中调用 moveTaskToBack (boolean nonRoot)方法即可将 activity 退到后台,注意不是 finish()退出。

  • activity 中的 runOnUiThrea(Runnable action)方法可以直接回到主线程

  • listview 有个 footerDividersEnabled 和 headerDividersEnabled 方法可以设置 listview 的顶部和底部 divide,但是必须保证你设置了 headview 和 footview 才会有效果

  • Throwable 类中的 getStackTrace()方法,根据这个方法可以得到函数的逐层调用地址,其返回值为 StackTraceElement[];

  • StackTraceElement 类,其中四个方法 getClassName(),getFileName(),getLineNumber(),getMethodName()在调试程序打印 Log 时非常有用;

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

  • Resources 类中的 getIdentifier(name, defType, defPackage)方法,根据资源名称获取其 ID,做 UI 时经常用到;

  • view 的 isShown 方法,只有当 view 本身以及它的所有祖先们都是 visible 时,isShown()才返回 TRUE。而平常我们调用 if(view.getVisibility() == View.VISIBLE)只是对 view 本身而不对祖先的可见性进行判断。

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

  • TextView 类中的 append(CharSequence)方法,添加文本。一些特殊文本直接用+连接会变成 String;

  • System 类中的 arraycopy(src, srcPos, dest, destPos, length)方法,用来 copy 数组;

  • Fragment 类中的 onHiddenChanged(boolean)方法,使用 FragmentTransaction 中的 hide(),show()时只会调用 Fragment 中的 show 和 hidden 状态,其他生命周期不会调用。

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

  • TextView 类中的 setTransformationMethod(TransformationMethod)方法,可用来实现“显示密码”功能

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

  • apache 提供的一系列 jar 包:commons-lang.jar,commons-collections.jar,commons-beanutils.jar 等,里面很多方法可能是你曾经用几十几百行代码实现过的,但是执行效率或许要差很多,比如:ArrayUtils,StringUtils……;

  • ActivityLifecycleCallbacks 接口,用于在 Application 类中监听各 Activity 的状态变化 阅读地址点我

  • ActionBar.hide()/.show() 顾名思义,隐藏和显示 ActionBar,可以优雅地在全屏和带 Actionbar 之间转换。

  • SystemClock.sleep() 这个方法在保证一定时间的 sleep 时很方便,通常我用来进行 debug 和模拟网络延时。

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

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

  • getParent().requestDisallowInterceptTouchEvent(true);剥夺父 view 对 touch 事件的处理权,谁用谁知道。

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

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

  • Executors. newSingleThreadExecutor();这个是 java 的,之前不知道它,自己花很大功夫去研究了单线程顺序执行的任务队列

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

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

  • ViewFlipper,实现多个 view 的切换(循环),可自定义动画效果,且可针对单个切换指定动画。

  • android util 包中的 Pair 类,可以方便的用来存储一"组"数据。注意不是 key value

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

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

  • Messenger,面试的时候通常都会被问到进程间通信,一般情况下大家都是开始背书,AIDL 巴拉巴拉。。有一天在鸿神的博客看到这个,嗯,如他所说,又可以装一下了。

  • 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 的值全为数字的时候, 你就会懵逼了.

  • TouchDelegate 可用于更改 View 的触摸区域。场景:比如在 RecyclerView 的 ItemView 里包含了 CheckBox 组件, 然后想实现点击 ItemView 的时候,也可以触发 CheckBox,就可以使用此类

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

  • Palette 可用于提取一张图片的颜色。

  • ViewDragHelper,做过自定义 ViewGroup 的童鞋都应该知道这个东西吧,用来处理触摸事件的神器,妈妈再也不用担心我自定义控件了。

  • PageTransformer 用于定义 ViewPager 页面切换时的动画效果(淡入淡出,放大缩小神马的…)官方有例子,直接看吧。

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

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

  • View.getContext 顾名思义,就不用解释了吧…以前在写 RecyclerView 的 Adapter 的时候,为了使用 LayoutInflater,经常傻乎乎地在构造函数中传入一个外部的 context….是不是只有我不知道而已(笑 cry 脸)

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

  • Activity.runOnUiThread 与 View.post 类似,方便在非 UI 线程中对界面进行修改。

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

  • android:animateLayoutChanges 这是一个非常酷炫的属性。在父布局加上 android:animateLayoutChanges="true" 后,如果触发了 layout 方法(比如它的子 View 设置为 GONE),系统就会自动帮你加上布局改变时的动画特效!!

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

  • rv 的 Layoutmanager 可以直接申明在 xml 中,具体代码可查看 RecyclerView.createLayoutManager 方法. 

  • RecyclerView 在 23.2.+的版本中新增了自动测量的功能,由于新增了自动测量,那么它的 item 的根布局在需要测量的方向上就不能写 match_parent 了,需要改成 wrap_content

  • getParent().requestDisallowInterceptTouchEvent(true);剥夺父 view 对 touch 事件的处理权,谁用谁知道。

  • Canvas 中 clipRect、clipPath 和 clipRegion 剪切区域的 API。

  • GradientDrawable 有个阴影效果还不错,以为是切的图片,一看代码,什么鬼= =!

  • 有朋友提到了在自定义 View 时有些方法在开启硬件加速的时候没有效果的问题,在 API16 之后确实有很多方法不支持硬件加速,通常我们关闭硬件加速都是在清单文件中通过,其实 android 也提供了针对特定 View 关闭硬件加速的方法,调用 View.setLayerType(View.LAYER_TYPE_SOFTWARE, null);即可。

  • PointF,graphics 包中的一个类,我们经常见到在处理 Touch 事件的时候分别定义一个 downX,一个 downY 用来存储一个坐标,如果坐标少还好,如果要记录的坐标过多那代码就不好看了。用 PointF(float x, float y);来描述一个坐标点会清楚很多。

  • StateListDrawable,定义 Selector 通常的办法都是 xml 文件,但是有的时候我们的图片资源可能是从服务器动态获取的,比如很多 app 所谓的皮肤,这种时候就只能通 StateListDrawable 来完成了,各种 addState 即可。

  • android:duplicateParentState="true",让子 View 跟随其 Parent 的状态,如 pressed 等。常见的使用场景是某些时候一个按钮很小,我们想要扩大其点击区域的时候通常会再给其包裹一层布局,将点击事件写到 Parent 上,这时候如果希望被包裹按钮的点击效果对应的 Selector 继续生效的话,这时候 duplicateParentState 就派上用场了。

  • ViewConfiguration.getScaledTouchSlop();触发移动事件的最小距离,自定义 View 处理 touch 事件的时候,有的时候需要判断用户是否真的存在 movie,系统提供了这样的方法。

  • ViewStub,有的时候一块区域需要根据情况显示不同的布局,通常我们都会通过 setVisibility 的方法来显示和隐藏不同的布局,但是这样默认是全部加载的,用 ViewStub 可以更好的提升性能。

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

  • TextView.setCompoundDrawablePadding,代码设置 TextView 的 drawable padding。

  • ImageSwitcher,可以用来做图片切换的一个类,类似于幻灯片。

  • 在自定义控件的时候,能用 drawable 来绘制圆,或者其他样式的时候,尽量用 drawable,因为 drawable 的效果要远胜于 canvas.drawXXX().

  • 如果想要自定义 View 支持 SwipeRefreshLayout,只需要声明并实现 ScrollingView 接口即可,RecyclerView 和 NestedScrollView 已经实现此接口。

  • AtomicFile——通过使用备份文件进行文件的原子化操作。这个知识点之前我也写过,不过最好还是有出一个官方的版本比较好。

  • DatabaseUtils——一个包含各种数据库操作的使用工具。

  • Activity.isChangingConfigurations ()——如果在 Activity 中 configuration 会经常改变的话,使用这个方法就可以不用手动做保存状态的工作了。

  • SearchRecentSuggestionsProvider——可以创建最近提示效果的 provider,是一个简单快速的方法。

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

  • android:fillViewport (ScrollView)——在这片文章中有详细介绍文章链接,可以解决在 ScrollView 中当内容不足的时候填不满屏幕的问题。

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

  • android:enterFadeDuration/android:exitFadeDuration (Drawables)——此属性在 Drawable 具有多种状态的时候,可以定义它展示前的淡入淡出效果。

  • Log.wtf()的意思是 What a Terrible Failure,而不是 What The Fuck!

  • 使用 RenderScript 虚化图片效果。如果你的 app 的 minSDK 为 16 或者更低,你需要使用 support 模式,因为很多方法都是在 API 17 之后添加的。renderscriptTargetApi 最高到 23,但是你应该把它设置到能保持脚本中使用到的功能完整的最低 API。如果你想在 support 模式下 target API 21+你必须使用 gradle-plugin 2.1.0 和 buildToolsVersion “23.0.3” 或者以上。需要在 gradle 中添加 renderscriptTargetApi 18,renderscriptSupportModeEnabled true 这两句话

    public static Bitmap blurBitmap(Context context, Bitmap src, int radius) {
          Bitmap dest = src.copy(src.getConfig(), true);
          RenderScript rs = RenderScript.create(context);
          Allocation allocation = Allocation.createFromBitmap(rs, src);
          Type t = allocation.getType();
          Allocation blurredAllocation = Allocation.createTyped(rs, t);
          ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
          blurScript.setRadius(radius);
          blurScript.setInput(allocation);
          blurScript.forEach(blurredAllocation);
          blurredAllocation.copyTo(dest);
          allocation.destroy();
          blurredAllocation.destroy();
          blurScript.destroy();
          t.destroy();
          rs.destroy();
          return dest;
      }
    
  • 如果想把一个 view 保存为 Bitmap,正常情况下用第一种方法就可以了,但是如果是 ScrollView,则必须采用第二种方法。 
     

  • 当 Activity LauncherMode 为 singleTask singleInstance 时,使用 startActivityForResult 会立马返回,不能正常调用。具体请看http://www.360doc.com/content/15/0123/14/12928831_443085580.shtml

  • 当 PopupWindow 中有 EditText 控件时,因为 Popupwindow 默认没有获取到焦点,需要手动设置焦点,这样子 view 才能获取到事件的监听。所以你需要在创建完 popwindow 后设置他的焦点,popupWindow.setFocusable(true);就可以让 EditText 获取焦点。

  • PopupWindow 默认点击外部的时候不消失,需要对 PopupWindow 设置一个背景图 popWindow.setBackgroundDrawable(new BitmapDrawable());要创建一个空对象,设置为 null 是不行的,或者就创建一个全透明的背景图。

  • android 中的序列化官方推荐 Parceble,其实 Parceble 最好用于内存之间数据的交换,如果要把数据写入硬盘的话,推荐实现 Serializable

  • tools 标签可以很好的帮助开发者实时预览 xml 的效果,通过 tools:background 可以预览控件所占的控件,tools:visibility 可以把一个 gone 的控件在预览的时候展示出来,并且运行以后 tools 标签的内容不会展示出来.例如:

    
    
  • android studio 2.1 起已经支持 jdk8 了,使用的时候要在 gradle 中加上,需要把 buildToolsVersion 更新到 24 以上的版本

    android {
      defaultConfig {
      ...
              jackOptions {
                  enabled true
              }
          }
     ...
      compileOptions {
          targetCompatibility 1.8
          sourceCompatibility 1.8
      }
    }
    
  • 6.0 之后 getResources().getColor()方法被废弃了,大家可以用 ContextCompat.getColor(context, R.color.color_name)替换,ContextCompat 是 v4 包里的,请放心使用,另外还有 getDrawable()等方法

  • 图片的资源文件官方推荐只把 launcher 放在 mipmap 文件夹下面,而 app 用到的资源文件建议放在 drawable 下面。

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

  • 如果你在 manifest 中把一个 activity 设置成 android:windowSoftInputMode="adjustResize",那么 ScrollView(或者其它可伸缩的 ViewGroups)会缩小,从而为软键盘腾出空间。但是,如果你在 activity 的主题中设置了 android:windowFullscreen="true",那么 ScrollView 不会缩小。这是因为该属性强制 ScrollView 全屏显示。然而在主题中设置 android:fitsSystemWindows="false" 也会导致 adjustResize 不起作用

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

  • Activity 的 onDestory 方法调用时机是不确定的(有时候离开界面很久之后才会调用 onDestory 方法),应该避免指望通过 onDestory 方法去释放与 Activity 相关的资源,否则会导致一些随机 bug

  • 2.X 时代 Bitmap 对象虽然存储在堆内存中,但是用了一个 byte 数组存储其像素信息。通过计数器来记录该像素信息被引用的个数。有人认为这个 byte 数组在 native 堆中,但事实上它也在堆中。只有在使用者调用 recycle()后,Bitmap 对象才会释放像素信息,才会在失去引用后被垃圾回收机制销毁。再加上 DVM 的 heap size 有严格的阀值,所以在使用大量图片资源的时候,及其容易发生 OOM。解决办法一般都是,用一个哈希表存储 Bitmap 对象的软引用,作为内存缓存,并在适当时机掉用其 recycle()。3.0 以上版本 Bitmap 对象可以通过垃圾回收机制完全销毁,理论上不用再调用 recycle()。

  • .gitignore 只能忽略那些原来没有被 track 的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore 是无效的。那么解决方法就是先把本地缓存删除(改变成未 track 状态),然后再提交:

    git rm -r --cached .
    git add .
    git commit -m 'update .gitignore'
    
  • 时间戳请使用 long 或者 String 类型接收,遇到的坑,由于项目中的 model 好多都是通过 GsonFormat 生成的,服务器给的 json 中的时间戳都是 10 位的,导致了 GsonFormat 自动解析成了 int, 当测试人员选择时间为 2100 年的时候时间戳是 4 开头的十位 用 int 类型接收越界了,导致报错

  • 为你的 app 添加默认布局样式,比如:每一个控件都需要写 width 和 height 属性,然而很多的控件的宽高属性都是 wrap_content,那么我们可以通过在 style 文件添加如下样式:

    
    

    这样,控件的宽高默认都是 wrap_content 样式啦。

  • 在 style 中写的样式通过视同 parent 标签来扩展你的样式,这样更高效,这里官方的建议是,只有 Android 自带的 style 才用 parent 标签,如果是自定义的 style,直接用.符号来连接就行。如 Fill.Height。

    
    
    
  • Android 上的应用切换按钮列出的其实不是应用而是 Task,所以你会看到有的应用在切换视图里有多个任务。如果你的应用中有逻辑上相互独立的部分,或者想在多窗口环境下并排显示应用的两个不同部分,这种情况就适合多任务了。使用 manifest 属性(静态)或者 intent flags(动态)可以实现这一点,详见视频:http://v.youku.com/v_show/id_XMTU2ODk4NDg2NA==.html?f=26587294

  • 当 app 的 theme 用的是 NoActionBar,但是在 layout 中仍然用到 toolbar 的时候,不要在 style 文件中加 fitsSystemWindows 属性,而是在用到 toolbar 的 layout 最外层加 fitsSystemWindows,否则当你使用 EditText,在小米手机上长按 EditText 调出系统粘贴功能的时候,粘贴的 layout 的布局会错位.

  • 当 WebView 与 ScrollView 嵌套使用,并且 WebView 有字体放大缩小的功能时,当切换 webview 的字体后,webview 的高度并不能很好的计算出来,这时候可以通过注入的方式,让 js 算出高度,经测试,这样是最可靠的,代码地址:http://blog.csdn.net/jys1115/article/details/43525979

  • Context 类中的 createPackageContext(packageName, flags)方法,可用来获取指定包名应用程序的 Context 对象。

  • TextView 类的 setKeyListener(KeyListener)方法; 其中 DigitsKeyListener 类,使用 getInstance(String accepted)方法即可指定 EditText 可输入字符集;

  • View 类中的 getLocationInWindow(int[])方法和 getLocationOnScreen(int[])方法,获取 View 在窗口/屏幕中的位置;

  • Context.getCacheDir() - 可以获取到 app 默认的缓存路径。

  • StaticLayout 在自定义控件绘制文本的时候很有用。

  • Android 中的四大组件千万不要通过 new 的方式创建出来。

  • 测试 app 的时候,我们大都想要将 debug 和 release 版本同时安装到手机里,可以通过在 gradle 中修改 applicationid 来实现:

    android {
      buildTypes {
          debug {
              applicationIdSuffix '.debug'
              versionNameSuffix '-DEBUG'
          }
          release {
              //...
          }
      }
    }
    
  • 在大多数的登陆界面中,都提供了用户是否让密码可见的选项,Support Library 24.2.0 提供了官方的实现,TextInputLayout 中添加了 passwordToggleEnabled 属性来开启此功能,并且可以通过 passwordToggleDrawable 设置图标。(摘自:Android 笔记的微博)

  • 同样,在 Support Library 24.2.0 中增加 RecyclerView 在快速滚动时的回调接口,SnapHelper 是官方的一个实现 OnFlingListener 的 一个抽象类,LinearSnapHelper 则是一个完整的实现.LinearSnapHelper 默认实现的功能是类似 ViewPager,在滚动结束后,会选择列表某一条居中展示(这里有开始位置展示,或者结束位置显示点我).例如:

      LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
      recyclerView.setLayoutManager(linearLayoutManager);
      LinearSnapHelper snapHelper = new LinearSnapHelper();
      snapHelper.attachToRecyclerView(recyclerView);
    
  • Android 中推荐使用的数据结构 :

    ArrayMap in place of HashMap 
    ArraySet in place of HashSet 
    SparseArray in place of HashMap 
    SparseBooleanArray in place of HashMap 
    SparseIntArray in place of HashMap  
    SparseLongArray in place of HashMap  
    LongSparseArray in place of HashMap
    
  • 生成 GUID(由于 java 中只能生成 UUID,所以这里要转换一下):

      return UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
    
  • 业务场景:需要定时后台扫描数据库,上传本地照片至云端,定时任务采用何种模式: 1.Handler 或者 Timer 定时一般为秒级别的任务,Timer 会启动额外线程,而 Handler 可以不用。 2.无论是 Handler 还是 Timer 都需要依赖于进程存活 3.利用 Handler 实现定时任务的类:HandlerTimer 4.如果时间较长,则需要使用 AlarmManager 5.另外,我们对于这种业务应该优先考虑是否可以基于事件通知。 6.如果是加入媒体库的文件,我们可以使用 registerContentObserver 监听媒体库文件变化。

  • 把 Activity 作为参数传给一个静态方法,会影响这个 Activity 的正常销毁吗? 1.内存泄露与方法是否是静态与否无关,与内部的方法体实现有关系。 2.内存泄露可以简单理解成:生命周期长的对象不正确持有了持有了生命周期短的对象,导致生命周期短的对象无法回收。 3.比如 Activity 实例被 Application 对象持有,Activity 实例被静态变量持有。

  • 在 assert 文件夹下存放单个文件的大小不能超过 1M,如果读取超过 1M 的文件会报 "Data exceeds UNCOMPRESS_DATA_MAX (1314625 vs 1048576)" 的 IOException。如果一定要存储,可以分割文件,再去合并文件

  • 在 Android library 中不能使用 switch-case 语句访问资源 ID,因为 case 分支后面跟的参数必须是常数,而 library 中的每一个资源 ID 都没有被声明为 final。

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

  • 不要通过 Bundle 传递大块的数据,否则会报 TransactionTooLargeException 异常

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

  • .9 图不能通过 tinypng 压缩,不然会有问题;

  • genymotion 模拟器快是因为它是基于 x86 架构的,如果你的应用中用到了 so,但没有 x86 架构的 so,只能放弃使用它;Android Studio 的模拟器也一样;

  • 使用 Toast 时,建议定义一个全局的 Toast 对象,这样可以避免连续显示 Toast 时不能取消上一次 Toast 消息的情况(如果你有连续弹出 Toast 的情况,避免使用 Toast.makeText);

  • 尽量避免给 window 和 Activity 同时都设置了背景,这样会造成过渡绘制,可以通过在给 Activity 设置主题时,去掉 windowBackground 背景的方式减少一层过渡绘制,有时候为了避免进入 Activity 时会黑屏或者白屏(和主题有关),会在给 Activity 设置主题的时候给 window 设置背景,如果这种情况下给 Activity 也设置了背景,是会增加一倍内存的:

    @null
    
  • 设置中更改字体为特大之类的会影响到 app 的字体样式,解决方法有: 1.将所有字体使用的单位换成 dp,不再使用 sp.这样不是很靠谱,并不是所有人都能做到。 2.

    Configuration configuration = getResources().getConfiguration();
    configuration.fontScale = (float) 1; 
    //0.85 小, 1 标准大小, 1.15 大,1.3 超大 ,1.45 特大 
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics); 
    metrics.scaledDensity = configuration.fontScale * metrics.density;
    getBaseContext().getResources().updateConfiguration(configuration, metrics); 
    //(ps:dialog popupwindow 除外,这两种需要在控件中重新设置 fontScale)
    
  • Android 中新引入的替代枚举的注解有 IntDef 和 StringDef,这里以 IntDef 做例子说明一下.

    public class Colors {
      @IntDef({RED, GREEN, YELLOW})
      //声明必要的 int 常量,使用@IntDef 修饰 LightColors,参数设置为待枚举的集合
      @Retention(RetentionPolicy.SOURCE)
      //使用@Retention(RetentionPolicy.SOURCE)指定注解仅存在与源码中,不加入到 class 文件中
      public @interface LightColors{}
      //声明一个注解为 LightColors
      public static final int RED = 0;
      public static final int GREEN = 1;
      public static final int YELLOW = 2;
    }
    //用法
    private void setColor(@Colors.LightColors int color) {
          Log.d("MainActivity", "setColor color=" + color);
    }
    //调用的该方法的时候
    setColor(Colors.GREEN);
    
  • PathInterpolatorCompat 很方便的使用它来创建各种插值曲线,举个非常简单的例子:

    Path path = new Path();
    path.cubicTo(0.2f, 0f, 0.1f, 1f, 0.5f, 1f);
    path.lineTo(1f, 1f);
    ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, 500);
    animator.setInterpolator(PathInterpolatorCompat.create(path));
    animator.start();
    
  • 检测当前网络能否访问远程服务器(国内通过 ping 百度来检测)

    public static boolean isNetWorkAvailable(final Context context) {
          try {
              Runtime runtime = Runtime.getRuntime();
              Process pingProcess = runtime.exec("/system/bin/ping -c 1 www.baidu.com");
              int exitCode = pingProcess.waitFor(); //0 代表连通,2 代表不通
              return (exitCode == 0);
          } catch (Exception e) {
              e.printStackTrace();
          }
          return false;
      }
    
  • 拦截系统返回键(onBackPressed()),使 App 不退出,而是进入后台运行

    @Override
    public void onBackPressed() {
      moveTaskToBack(false);
    }
    
  • view.performClick() 自动调用 View 点击事件。通常按钮等控件只有在用户点击时才能触发其点击事件,该方法可以由某些特殊条件触发模拟用户点击行为。类似的还有 performLongClick() 方法。

  • Linkify.addLinks() 通过 android:autoLink 属性可以为其添加诸如 web、phone 等固定模版的超链接点击事件。但毕竟系统模版有限,而利用 Linkify.addLinks() 方法可以添加一些应用内自定义模版,比如新浪微博中的 "@XXX" 格式的超链接跳转等,都可以通过自定义正则表达式来匹配处理。

  • getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE) 设置安全窗口,禁用系统截屏。防止 App 中的一些界面被截屏,并显示在其他设备中造成信息泄漏。(常见手机设备系统截屏操作方式为:同时按下电源键和音量键。)

  • activity 生命周期(Ref Link) 

  • RecyclerView 调用 notifyItem()的时候会有默认的动画,可以通过调用((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);来去掉默认动画.以防止出现闪屏的问题

  • Toolbar 使用的主题如果 parent="ThemeOverlay.AppCompat.Light",只要改一下 @color/white 就可以使 OverflowButton 变为白色,同时点击它展开的菜单背景也可以是白的

  • Android View 的生命周期示例图样。来自 G+ +Arpit Mathur 

  • 当需要从资源文件中获取 html 并展示时,使用 Resource#getText() 而不是 Resource#getString()。当需要动态显示 HTML 时,使用 Html.fromHtml() 请看这里

  • JAVA 中时间 String 转 Timestamp

    try {
      DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
      format.setLenient(false);
      //要转换字符串 str_test  自定义的格式为 yyyy-mm-dd,可以改成你需要的格式
      String str_test ="2011-04-24";
      Timestamp ts = new Timestamp(format.parse(str_test).getTime());
      System.out.println(ts.toString());
    } catch (ParseException e) {
    e.printStackTrace();
    }
    
  • 当 Activity 继承 FragmentActivity 的时候,调用 startActivityForResult 方法中传递的 requestCode 范围应该在 0-65535 范围内,否则会报"Can only use lower 16 bits for requestCode"异常。

你可能感兴趣的:(android)