Hack11 为文本添加发亮的效果
问题:如何设计一个显示高亮绿灯的数字时钟?
解决方案:应先继承TextView类,并为其设置 digital-7.ttf 字体。在背景文件中添加两个TextView标签,第一个显示 88:88:88的阴影(半透明效果),第二个用于显示 当前时间。布局代码如下:
1 |
|
修改 android:shadowDx 和 android:shadowDy 属性的值可以改变阴影与文本之间的偏移。指定 android:shadowRadius 属性可以让用户产生一种 文本更亮 的错觉。为了产生一种发亮的效果,我们没有使用android:shadowDx和android:shadowDy属性,而是通过修改android:shadowRadius属性。
Hack12 为背景添加圆角边框
问题:如何为TextView、Button等控件添加圆角边框?
解决方案:可以修改控件的 background 或 style 属性,将其指定为 带有shape标签 的drawable文件。值得一提的是,在Android 5.0中出现了一个全新的控件——CardView。CardView被包装为一种布局,拥有多种圆角、阴影以及点击效果,可以给使用者带来非常好的交互体验。
Hack13 在onCreate()方法中获取View的宽度和高度
问题:为什么onCreate()方法调用getWidth()和getHeight()方法返回值都是0?
解决方案:在onCreate()方法中直接调用 getWidth() 和 getHeight() 方法时,视图正处于绘制阶段。只有在整个布局绘制完毕后,视图才能得到自身的宽和高,这个过程发生在onCreate()方法之后。开发者应通过View的 post() 方法解决该问题。
Hack14 VideoView的转屏处理技巧
问题:如何处理视频的转屏操作?
解决方案:首先,要让Activity能够处理转屏操作。要实现这个功能,需要在AndroidManifest.xml文件中相应的Activity标签中添加 android:configChanges=”orientation” 属性。配置该属性后,当屏幕旋转时,系统不会重启Activity,而是调用该Activity的 onConfigurationChanged() 方法。重写onConfigurationChanged()方法,在其中调用setVideoViewPosition()方法。在setVideoViewPosition()方法中,判断屏幕的朝向并根据结果对VideoView的位置做不同的处理。
Hack15 移除背景以提升Activity启动速度
问题:有什么方法能提高复杂视图树的加载速度?
解决方案:Android SDK中提供了 Hierarchy Viewer 工具,该工具可以用来检测未被使用的视图以减少视图树的层次。DecorView 是视图树的根节点,默认情况下框架层会以默认背景色填充窗口,而DecorView就是持有默认窗口背景图片的视图。如果使用不透明的界面或者自定义背景,那么就可以将Activity标签中的windowBackground属性设置为null。
Hack16 更改Toast显示位置的技巧
问题:如何修改Toast显示的位置?
解决方案:开发者可以使用 Toast.setGravity() 方法改变Toast默认位置。
Hack17 使用Gallery创建向导表单
问题:当需要用户填充一个较长的表单时,有什么好的设计方式?
解决方案:利用 Gallery 中的自定义视图创建一个向导表单,并通过Adapter进行数据绑定。
Hack18 在发布正式版本前移除日志语句
问题:在开发过程中,开发者可能会打印一些日志来检查请求是否成功。有什么在发布正式版本前移除日志的办法?
解决方案:ProGuard工具 可以移除不必要的代码,或者使用语义模糊的名称来重命名类、方法和变量,以此达到 压缩、优化 和 混淆 代码的目的。在Android Studio中,build.gradle文件内proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.txt’语句指定了ProGuard工具的执行目标。下面是常用proguard-rules的代码:
1 | #指定代码的压缩级别 |
Hack19 使用Hierarchy Viewer工具移除不必要的视图
问题:如何找出视图树中那些不必要的视图以及性能瓶颈?
解决方案:Android SDK中提供了 Hierarchy Viewer 工具,可以用来查看视图树并分析视图树中各个视图在测量、布局、绘制阶段所消耗的时间。View节点中带有红色或黄色的点代表速度较慢的View对象。请注意,低性能并不表示一定有问题,特别像是ViewGroup对象,View的子节点越多,结构越复杂,性能越差。
该工具还可以帮助开发者找到性能问题,只要察看每个View节点的性能指标(颜色点)就可以,你可以看到测量、布局或绘制最慢的View对象是哪个,这样就能快速确定要优先判断哪里出了问题。
请注意:出于安全性的考虑,Hierarchy Viewer只能连接 Android开发版手机 或是 模拟器。Hierarchy Viewer在连接手机时,手机上必须启动一个叫 View Server 的客户端与其进行socket通信。而在商业手机上,是无法开启View Server的,故Hierarchy Viewer无法连接到普通的商业手机。
Hack20 模型-视图-主导器(MVP)模式
问题:MVP模式是什么?与MVC模式有怎样的区别?
解决方案:MVP模式是MVC模式在Android上的一种变体,要介绍MVP模式就得先说说MVC模式。在 MVC模式 中,Activity应该是属于 View 这一层。而实质上,它既担任了View的角色,同时也包含一些Controller的东西在里面。这对于开发与维护来说不太友好,耦合度很高。把Activity的 View 和 Controller 抽离出来就变成了 View 和 Presenter,这就是 MVP模式。
MVP的好处大体来说有以下3点:
- Activity代码变得更加简洁。使用MVP模式之后,Activity就能瘦身许多了。每个Activity基本上只有FindView、SetListener以及Init的代码,其他的就是对Presenter的调用以及对View接口的实现。 这种情形下阅读代码就容易多了,而且开发者只要看Presenter的接口,就能明白这个模块都有哪些业务,很快就能定位到具体代码。Activity变得容易维护,以后要调整业务、增删功能也就变得简单许多。
- 方便进行单元测试。MVP模式中,由于业务逻辑都在Presenter里,开发者完全可以写一个PresenterTest的实现类继承Presenter的接口。只要在Activity里把Presenter的创建换成PresenterTest,就能进行单元测试了,测试完再换回来即可。
- 避免Activity的内存泄露。Android APP发生OOM的最大原因就是出现内存泄露造成APP的内存不够用,而造成内存泄露的两大原因之一就是Activity泄露和Bitmap泄露。 Activity是有生命周期的,用户随时可能切换Activity,当APP的内存不够用的时候,系统会回收处于后台的Activity的资源以避免OOM。采用传统的MVC模式,一大堆异步任务和对UI的操作都放在Activity里面。比如用户可能从网络下载一张图片,在下载成功的回调里把图片加载到Activity的ImageView里面,所以异步任务保留着对Activity的引用。这样一来,即使Activity已经被切换到后台(onDestroy方法已经执行),这些异步任务仍然保留着对Activity实例的引用,所以系统就无法回收这个Activity实例了,结果就是Activity泄露。Android的组件中,Activity对象往往是在堆里占最多内存的,所以系统会优先回收Activity对象。如果出现Activity泄露,应用程序很容易因为内存不够而OOM。采用MVP模式,只要在当前的Activity的onDestroy方法里,分离异步任务对Activity的引用,就能避免Activity泄露。