首页 编程 软件学院 查看内容

Android 开发最佳实践(二)

2015-7-7 11:04 |来自: 开发技术前线 1422 0

摘要: include layout="@layout/reusable_part" / /LinearLayout作为一个经验法则,android:layout_****属性应该在 layout XML 中定义,同时其它属性android:****应放在 styler XML中。此规则也有例外,不过大体工作的很 ...
关键词: nbsp 一个 文件 android ProGuard name color 测试 layout LinearLayout

 <include layout="@layout/reusable_part" />

</LinearLayout>

作为一个经验法则, android:layout_**** 属性应该在 layout XML 中定义,同时其它属性 android:**** 应放在 styler XML中。此规则也有例外,不过大体工作

的很好。这个思想整体是保持layout属性(positioning, margin, sizing) 和content属性在布局文件中,同时将所有的外观细节属性(colors, padding, font)放

在style文件中。

例外有以下这些:

  • android:id 明显应该在layout文件中
  • layout文件中 android:orientation 对于一个 LinearLayout 布局通常更有意义
  • android:text 由于是定义内容,应该放在layout文件中
  • 有时候将 android:layout_width 和 android:layout_height 属性放到一个style中作为一个通用的风格中更有意义,但是默认情况下这些应该放到layout文件中。

使用styles几乎每个项目都需要适当的使用style文件,因为对于一个视图来说有一个重复的外观是很常见的。

在应用中对于大多数文本内容,最起码你应该有一个通用的style文件,例如:

<style name="ContentText">
    <item name="android:textSize">@dimen/font_normal</item>
    <item name="android:textColor">@color/basic_black</item>
</style>

应用到TextView 中:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />

你或许需要为按钮控件做同样的事情,不要停止在那里。将一组相关的和重复android:**** 的属性放到一个通用的style中。

将一个大的style文件分割成多个文件你可以有多个 styles.xml 文件。Android SDK支持其它文件, styles 这个文件名称并没有作用,起作用的是在文件

里xml的 <style> 标签。因此你可以有多个style文件 styles.xml ,style_home.xml , style_item_details.xml , styles_forms.xml 。

不用于资源文件路径需要为系统构建起的有意义,在 res/values 目录下的文件可以任意命名。

colors.xml 是一个调色板 在你的 colors.xml 文件中应该只是映射颜色的名称一个RGBA值,而没有其它的。不要使用它为不同的按钮来定义RGBA值。

不要这样做

<resources>
    <color name="button_foreground">#FFFFFF</color>
    <color name="button_background">#2A91BD</color>
    <color name="comment_background_inactive">#5F5F5F</color>
    <color name="comment_background_active">#939393</color>
    <color name="comment_foreground">#FFFFFF</color>
    <color name="comment_foreground_important">#FF9D2F</color>
    ...
    <color name="comment_shadow">#323232</color>

使用这种格式,你会非常容易的开始重复定义RGBA值,这使如果需要改变基本色变的很复杂。同时,这些定义是跟一些环境关联起来的,如 button 或者 comment ,

应该放到一个按钮风格中,而不是在 color.xml 文件中。

相反,这样做:

<resources>

    <!-- grayscale -->
    <color name="white"     >#FFFFFF</color>
    <color name="gray_light">#DBDBDB</color>
    <color name="gray"      >#939393</color>
    <color name="gray_dark" >#5F5F5F</color>
    <color name="black"     >#323232</color>

    <!-- basic colors -->
    <color name="green">#27D34D</color>
    <color name="blue">#2A91BD</color>
    <color name="orange">#FF9D2F</color>
    <color name="red">#FF432F</color>

</resources>

向应用设计者那里要这个调色板,名称不需要跟”green”, “blue”, 等等相同。

“brand_primary”, “brand_secondary”, “brand_negative” 这样的名字也是完全可以接受的。

像这样规范的颜色很容易修改或重构,会使应用一共使用了多少种不同的颜色变得非常清晰。

通常一个具有审美价值的UI来说,减少使用颜色的种类是非常重要的。

像对待colors.xml一样对待dimens.xml文件与定义颜色调色板一样,你同时也应该定义一个空隙间隔和字体大小的“调色板”。

一个好的例子,如下所示:

<resources>

    <!-- font sizes -->
    <dimen name="font_larger">22sp</dimen>
    <dimen name="font_large">18sp</dimen>
    <dimen name="font_normal">15sp</dimen>
    <dimen name="font_small">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_huge">40dp</dimen>
    <dimen name="spacing_large">24dp</dimen>
    <dimen name="spacing_normal">14dp</dimen>
    <dimen name="spacing_small">10dp</dimen>
    <dimen name="spacing_tiny">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_tall">60dp</dimen>
    <dimen name="button_height_normal">40dp</dimen>
    <dimen name="button_height_short">32dp</dimen>

</resources>

布局时在写 margins 和 paddings 时,你应该使用 spacing_**** 尺寸格式来布局,而不是像对待String字符串一样直接写值。

这样写会非常有感觉,会使组织和改变风格或布局是非常容易。

避免深层次的视图结构有时候为了摆放一个视图,你可能尝试添加另一个LinearLayout。你可能使用这种方法解决:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <RelativeLayout
        ...
        >

        <LinearLayout
            ...
            >

            <LinearLayout
                ...
                >

                <LinearLayout
                    ...
                    >
                </LinearLayout>

            </LinearLayout>

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

即使你没有非常明确的在一个layout布局文件中这样使用,如果你在Java文件中从一个view inflate(这个inflate翻译不过去,大家理解就行) 到其他views当中,也是可能会发生的。

可能会导致一系列的问题。你可能会遇到性能问题,因为处理起需要处理一个复杂的UI树结构。

还可能会导致以下更严重的问题 StackOverflowError .

因此尽量保持你的视图tree:学习如何使用 RelativeLayout ,

如何 optimize 你的布局 和如何使用

<merge> 标签 .

小心关于WebViews的问题.如果你必须显示一个web视图,

比如说对于一个新闻文章,避免做客户端处理HTML的工作,

最好让后端工程师协助,让他返回一个 “  ” HTML。

WebViews 也能导致内存泄露

当保持引他们的Activity,而不是被绑定到ApplicationContext中的时候。

当使用简单的文字或按钮时,避免使用WebView,这时使用TextView或Buttons更好。

测试框架

Android SDK的测试框架还处于初级阶段,特别是关于UI测试方面。Android Gradle

目前实现了一个叫 connectedAndroidTest 的测试,

它 使用一个JUnit 为Android提供的扩展插件 extension of JUnit with helpers for Android .可以跑你生成的JUnit测试,

只当做单元测试时使用 Robolectric ,views 不用

它是一个最求提供”不连接设备的”为了加速开发的测试,

非常时候做 models 和 view models 的单元测试。

然而,使用Robolectric测试时不精确的,也不完全对UI测试。

当你对有关动画的UI元素、对话框等,测试时会有问题,

这主要是因为你是在 “在黑暗中工作”(在没有可控的界面情况下测试)

** Robotium 使写UI测试非常简单。

** 对于UI测试你不需 Robotium 跑与设备连接的测试。

但它可能会对你有益,是因为它有许多来帮助类的获得和分析视图,控制屏幕。

测试用例看起来像这样简单:

solo.sendKey(Solo.MENU);
solo.clickOnText("More"); // searches for the first occurence of "More" and clicks on it
solo.clickOnText("Preferences");
solo.clickOnText("Edit File Extensions");
Assert.assertTrue(solo.searchText("rtf"));

模拟器

如果你全职开发Android App,那么买一个 Genymotion emulator license吧。

Genymotion 模拟器运行更快的秒帧的速度,比起典型的AVD模拟器。他有演示你APP的工具,高质量的模拟网络连接,GPS位置,等等。它同时还有理想的连接测试。

你若涉及适配使用很多不同的设备,买一个Genymotion 版权是比你买很多真设备便宜多的。

注意:Genymotion模拟器没有装载所有的Google服务,如Google Play Store和Maps。你也可能需要测试Samsung指定的API,若这样的话你还是需要购买一个真实的Samsung设备。

混淆配置

ProGuard 是一个在Android项目中广泛使用的压缩和混淆打包的源码的工具。

你是否使用ProGuard取决你项目的配置,当你构建一个release版本的apk时,通常你应该配置gradle文件。

buildTypes {
    debug {
        minifyEnabled false
    }
    release {
        signingConfig signingConfigs.release
        minifyEnabled true
        proguardFiles 'proguard-rules.pro'
    }
}

为了决定哪些代码应该被保留,哪些代码应该被混淆,你不得不指定一个或多个实体类在你的代码中。

这些实体应该是指定的类包含main方法,applets,midlets,activities,等等。

Android framework 使用一个默认的配置文件,可以在SDK_HOME/tools/proguard/proguard-android.txt 

目录下找到。自定义的工程指定的 project-specific 混淆规则,如在 my-project/app/proguard-rules.pro 中定义,

会被添加到默认的配置中。

关于 ProGuard 一个普遍的问题,是看应用程序是否崩溃并报ClassNotFoundException 或者 NoSuchFieldException 或类似的异常,

即使编译是没有警告并运行成功。

这意味着以下两种可能:

  1. ProGuard 已经移除了类,枚举,方法,成员变量或注解,考虑是否是必要的。
  2. ProGuard 混淆了类,枚举,成员变量的名称,但是这些名字又被拿原始名称使用了,比如通过Java的反射。

检查 app/build/outputs/proguard/release/usage.txt 文件看有问题的对象是否被移除了。

检查 app/build/outputs/proguard/release/mapping.txt 文件看有问题的对象是否被混淆了。

In order to prevent ProGuard from stripping away needed classes or class members, add a keep options to your proguard config:

以防 ProGuard 剥离 需要的类和类成员,添加一个 keep 选项在你的 proguard 配置文件中:

-keep class com.futurice.project.MyClass { *; }

防止 ProGuard 混淆 一些类和成员,添加 keepnames :

-keepnames class com.futurice.project.MyClass { *; }

查看 this template’s ProGuard config 中的一些例子。

更多例子请参考 Proguard 。

在构建项目之初,发布一个版本来检查ProGuard规则是否正确的保持了重要的部分。

同时无论何时你添加了新的类库,做一个发布版本,同时apk在设备上跑起来测试一下。

不要等到你的app要发布 “1.0”版本了才做版本发布,那时候你可能会碰到好多意想不到的异常,需要一些时间去修复他们。

Tips每次发布新版本都要写 mapping.txt 。每发布一个版本,如果用户遇到一个bug,同时提交了一个混淆过的堆栈跟踪。

通过保留 mapping.txt 文件,来确定你可以调试的问题。

DexGuard若果你需要核心工具来优化,和专门混淆的发布代码,考虑使用DexGuard ,

一个商业软件,ProGuard 也是有他们团队开发的。

它会很容易将Dex文件分割,来解决65K个方法**问题。

致谢

感谢Antti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton 这些人和Futurice 开发者分享他们的Android开发经验。

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部