[Android进阶]Android 开发最佳实践

【跟着Cursor开发安卓APP】1. 配置安卓开发环境 根据他们的建议,我选择了同意并继续安装。您的 Homebrew、wget、curl 都已经配置好,没有任何问题,可以继续后续的开发环境配置或 Android 项目开发。它首先检查了JDK(Java开发工具包)的安装情况,发现需要安装JDK,并为我列出了具体的安装步骤。我按照他告诉我的方式执行了,上面几个代码都能正常输出,我想这个环境应该都配置完了。最后运行了他给的代码,但是执行完了没有反应,所以我就问他没有反应是正常吗?他说我的环境已经配置好了,但是我不确定是不是完全配置好,所以让他检查一下。 阅读详情

Android 开发最佳实践

从Futurice公司Android开发者中学到的经验。
遵循以下准则,避免重复发明轮子。若您对开发iOS或Windows Phone 有兴趣,
请看iOS Good Practices 和 Windows client Good Practices 这两篇文章。

摘要

  • 使用 Gradle 和它推荐的工程结构
  • 把密码和敏感数据放在gradle.properties
  • 不要自己写 HTTP 客户端,使用Volley或OkHttp库
  • 使用Jackson库解析JSON数据
  • 避免使用Guava同时使用一些类库来避免65k method limit(一个Android程序中最多能执行65536个方法)
  • 使用 Fragments来呈现UI视图
  • 使用 Activities 只是为了管理 Fragments
  • Layout 布局是 XMLs代码,组织好它们
  • 在layoutout XMLs布局时,使用styles文件来避免使用重复的属性
  • 使用多个style文件来避免单一的一个大style文件
  • 保持你的colors.xml 简短DRY(不要重复自己),只是定义调色板
  • 总是使用dimens.xml DRY(不要重复自己),定义通用常数
  • 不要做一个深层次的ViewGroup
  • 在使用WebViews时避免在客户端做处理,当心内存泄露
  • 使用Robolectric单元测试,Robotium 做UI测试
  • 使用Genymotion 作为你的模拟器
  • 总是使用ProGuard 和 DexGuard混淆来项目

Android SDK

将你的Android SDK放在你的home目录或其他应用程序无关的位置。
当安装有些包含SDK的IDE的时候,可能会将SDK放在IDE同一目录下,当你需要升级(或重新安装)IDE或更换的IDE时,会非常麻烦。
此外,若果你的IDE是在普通用户,不是在root下运行,还要避免吧SDK放到一下需要sudo权限的系统级别目录下。

构建系统

你的默认编译环境应该是Gradle.
Ant 有很多限制,也很冗余。使用Gradle,完成以下工作很方便:

  • 构建APP不同版本的变种
  • 制作简单类似脚本的任务
  • 管理和下载依赖
  • 自定义秘钥
  • 更多

同时,Android Gradle插件作为新标准的构建系统正在被Google积极的开发。

工程结构

有两种流行的结构:老的Ant & Eclipse ADT 工程结构,和新的Gradle & Android Studio 工程结构,
你应该选择新的工程结构,如果你的工程还在使用老的结构,考虑放弃吧,将工程移植到新的结构。

老的结构:

old-structure
├─ assets
├─ libs
├─ res
├─ src
│  └─ com/futurice/project
├─ AndroidManifest.xml
├─ build.gradle
├─ project.properties
└─ proguard-rules.pro

新的结构

new-structure
├─ library-foobar
├─ app
│  ├─ libs
│  ├─ src
│  │  ├─ androidTest
│  │  │  └─ java
│  │  │     └─ com/futurice/project
│  │  └─ main
│  │     ├─ java
│  │     │  └─ com/futurice/project
│  │     ├─ res
│  │     └─ AndroidManifest.xml
│  ├─ build.gradle
│  └─ proguard-rules.pro
├─ build.gradle
└─ settings.gradle

主要的区别在于,新的结构明确的分开了’source sets’ (main,androidTest),Gradle的一个理念。
你可以做到,例如,添加源组‘paid’和‘free’在src中,这将成为您的应用程序的付费和免费的两种模式的源代码。

你的项目引用第三方项目库时(例如,library-foobar),拥有一个顶级包名app从第三方库项目区分你的应用程序是非常有用的。
然后settings.gradle不断引用这些库项目,其中app/build.gradle可以引用。

Gradle 配置

常用结构 参考Google’s guide on Gradle for Android

小任务 除了(shell, Python, Perl, etc)这些脚本语言,你也可以使用Gradle 制作任务。
更多信息请参考Gradle’s documentation。

密码 在做版本release时你app的 build.gradle你需要定义 signingConfigs.此时你应该避免以下内容:

不要做这个 . 这会出现在版本控制中。

signingConfigs {
    release {
        storeFile file("myapp.keystore")
        storePassword "password123"
        keyAlias "thekey"
        keyPassword "password789"
    }
}

而是,建立一个不加入版本控制系统的gradle.properties文件。

KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

那个文件是gradle自动引入的,你可以在buld.gradle文件中使用,例如:

signingConfigs {
    release {
        try {
            storeFile file("myapp.keystore")
            storePassword KEYSTORE_PASSWORD
            keyAlias "thekey"
            keyPassword KEY_PASSWORD
        }
        catch (ex) {
            throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
        }
    }
}

使用 Maven 依赖方案代替使用导入jar包方案 如果在你的项目中你明确使用率
jar文件,那么它们可能成为永久的版本,如2.1.1.下载jar包更新他们是很繁琐的,
这个问题Maven很好的解决了,这在Android Gradle构建中也是推荐的方法。你可
以指定版本的一个范围,如2.1.+,然后Maven会自动升级到制定的最新版本,例如:

dependencies {
    compile 'com.netflix.rxjava:rxjava-core:0.19.+'
    compile 'com.netflix.rxjava:rxjava-android:0.19.+'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-core:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'
    compile 'com.squareup.okhttp:okhttp:2.0.+'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
}

IDEs and text editors

IDE集成开发环境和文本编辑器

无论使用什么编辑器,一定要构建一个良好的工程结构 编辑器每个人都有自己的
选择,让你的编辑器根据工程结构和构建系统运作,那是你自己的责任。

当下首推Android Studio,因为他是由谷歌开发,最接近Gradle,默认使用最新的工程结构,已经到beta阶段
(目前已经有release 1.0了),它就是为Android开发定制的。

你也可以使用Eclipse ADT ,但是你需要对它进行配置,因为它使用了旧的工程结构
和Ant作为构建系统。你甚至可以使用纯文版编辑器如Vim,Sublime Text,或者Emacs。如果那样的话,你需要使用Gardle和adb命令行。如果使用Eclipse集成Gradle
不适合你,你只是使用命令行构建工程,或迁移到Android Studio中来吧。

无论你使用何种开发工具,只要确保Gradle和新的项目结构保持官方的方式构建应用程序,避免你的编辑器配置文件加入到版本控制。例如,避免加入Ant build.xml文件。
特别如果你改变Ant的配置,不要忘记保持build.gradle是最新和起作用的。同时,善待其他开发者,不要强制改变他们的开发工具和偏好。

类库

Jackson 是一个将java对象转换成JSON与JSON转化java类的类库。Gson
是解决这个问题的流行方案,然而我们发现Jackson更高效,因为它支持替代的方法处理JSON:流、内存树模型,和传统JSON-POJO数据绑定。不过,请记住,
Jsonkson库比起GSON更大,所以根据你的情况选择,你可能选择GSON来避免APP 65k个方法限制。其它选择: Json-smart and Boon JSON

网络请求,缓存,图片 执行请求后端服务器,有几种交互的解决方案,你应该考虑实现你自己的网络客户端。使用 Volley
或Retrofit。Volley 同时提供图片缓存类。若果你选择使用Retrofit,那么考虑使用Picasso
来加载图片和缓存,同时使用OkHttp作为高效的网络请求。Retrofit,Picasso和OkHttp都是有同一家公司开发(注:
是由Square 公司开发),所以它们能很好的在一起运行。OkHttp 同样可以和Volley在一起使用 Volley.

RxJava 是函数式反应性的一个类库,换句话说,能处理异步的事件。
这是一个强大的和有前途的模式,同时也可能会造成混淆,因为它是如此的不同。
我们建议在使用这个库架构整个应用程序之前要谨慎考虑。
有一些项目是使用RxJava完成的,如果你需要帮助可以跟这些人取得联系:
Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen.
我们也写了一些博客:
[1], [2],
[3],
[4].

如若你之前有使用过Rx的经历,开始从API响应应用它。
另外,从简单的UI事件处理开始运用,如单击事件或在搜索栏输入事件。
若对你的Rx技术有信心,同时想要将它应用到你的整体架构中,那么请在复杂的部分写好Javadocs文档。
请记住其他不熟悉RxJava的开发人员,可能会非常难理解整个项目。
尽你的的全力帮助他们理解你的代码和Rx。

Retrolambda 是一个在Android和预JDK8平台上的使用Lambda表达式语法的Java类库。
它有助于保持你代码的紧凑性和可读性,特别当你使用如RxJava函数风格编程时。
使用它时先安装JDK8,在Android Studio工程结构对话框中把它设置成为SDK路径,同时设置JAVA8_HOME和JAVA7_HOME环境变量,
然后在工程根目录下配置 build.gradle:

dependencies {
    classpath 'me.tatarka:gradle-retrolambda:2.4.+'
}

同时在每个module 的build.gradle中添加

apply plugin: 'retrolambda'

android {
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

retrolambda {
    jdk System.getenv("JAVA8_HOME")
    oldJdk System.getenv("JAVA7_HOME")
    javaVersion JavaVersion.VERSION_1_7
}

Android Studio 提供Java8 lambdas表带是代码提示支持。如果你对lambdas不熟悉,只需参照以下开始学习吧:

  • 任何只包含一个接口的方法都是”lambda friendly”同时代码可以被折叠成更紧凑的语法
  • 如果对参数或类似有疑问,就写一个普通的匿名内部类,然后让Android Status为你生成一个lambda。

当心dex方法数限制,同时避免使用过多的类库 Android apps,当打包成一个dex文件时,有一个65535个应用方法强硬限制[1] [2] [3]。
当你突破65k限制之后你会看到一个致命错误。因此,使用一个正常范围的类库文件,同时使用dex-method-counts
工具来决定哪些类库可以再65k限制之下使用,特别的避免使用Guava类库,因为它包含超过13k个方法。

Activities and Fragments

Fragments应该作为你实现UI界面默认选择。你可以重复使用Fragments用户接口来
组合成你的应用。我们强烈推荐使用Fragments而不是activity来呈现UI界面,理由如下:

  • 提供多窗格布局解决方案 Fragments 的引入主要将手机应用延伸到平板电脑,所以在平板电脑上你可能有A、B两个窗格,但是在手机应用上A、B可能分别充满
    整个屏幕。如果你的应用在最初就使用了fragments,那么以后将你的应用适配到其他不同尺寸屏幕就会非常简单。

  • 屏幕间数据通信 从一个Activity发送复杂数据(例如Java对象)到另外一个Activity,Android的API并没有提供合适的方法。不过使用Fragment,你可以使用
    一个activity实例作为这个activity子fragments的通信通道。即使这样比Activity与Activity间的通信好,你也想考虑使用Event Bus架构,使用如
    Otto 或者 greenrobot EventBus作为更简洁的实现。
    如果你希望避免添加另外一个类库,RxJava同样可以实现一个Event Bus。

  • Fragments 一般通用的不只有UI 你可以有一个没有界面的fragment作为Activity提供后台工作。
    进一步你可以使用这个特性来创建一个fragment 包含改变其它fragment的逻辑
    而不是把这个逻辑放在activity中。

  • 甚至ActionBar 都可以使用内部fragment来管理 你可以选择使用一个没有UI界面的fragment来专门管理ActionBar,或者你可以选择使用在每个Fragment中
    添加它自己的action 来作为父Activity的ActionBar.参考.

很不幸,我们不建议广泛的使用嵌套的fragments,因为
有时会引起matryoshka bugs。我们只有当它有意义(例如,在水平滑动的ViewPager在
像屏幕一样fragment中)或者他的确是一个明智的选择的时候才广泛的使用fragment。

在一个架构级别,你的APP应该有一个顶级的activity来包含绝大部分业务相关的fragment。你也可能还有一些辅助的activity ,这些辅助的activity与主activity
通信很简单限制在这两种方法
Intent.setData() 或 Intent.setAction()或类似的方法。

Java 包结构

Android 应用程序在架构上大致是Java中的Model-View-Controller结构。
在Android 中 Fragment和Activity通常上是控制器类(http://www.informit.com/articles/article.aspx?p=2126865).
换句话说,他们是用户接口的部分,同样也是Views视图的部分。

正是因为如此,才很难严格的将fragments (或者 activities) 严格的划分成 控制器controlloers还是视图 views。
最还是将它们放在自己单独的 fragments 包中。只要你遵循之前提到的建议,Activities 则可以放在顶级目录下。
若果你规划有2到3个以上的activity,那么还是同样新建一个activities包吧。

然而,这种架构可以看做是另一种形式的MVC,
包含要被解析API响应的JSON数据,来填充的POJO的models包中。
和一个views包来包含你的自定义视图、通知、导航视图,widgets等等。
适配器Adapter是在数据和视图之间。然而他们通常需要通过getView()方法来导出一些视图,
所以你可以将adapters包放在views包里面。

一些控制器角色的类是应用程序级别的,同时是接近系统的。
这些类放在managers包下面。
一些繁杂的数据处理类,比如说”DateUtils”,放在utils包下面。
与后端交互负责网络处理类,放在network包下面。

总而言之,以最接近用户而不是最接近后端去安排他们。

com.futurice.project
├─ network
├─ models
├─ managers
├─ utils
├─ fragments
└─ views
   ├─ adapters
   ├─ actionbar
   ├─ widgets
   └─ notifications

资源文件 Resources

  • 命名 遵循前缀表明类型的习惯,形如type_foo_bar.xml。例如:fragment_contact_details.xml,view_primary_button.xml,activity_main.xml.

组织布局文件 若果你不确定如何排版一个布局文件,遵循一下规则可能会有帮助。

  • 每一个属性一行,缩进4个空格
  • android:id 总是作为第一个属性
  • android:layout_**** 属性在上边
  • style 属性在底部
  • 关闭标签/>单独起一行,有助于调整和添加新的属性
  • 考虑使用Designtime attributes 设计时布局属性,Android Studio已经提供支持,而不是硬编码android:text
    (译者注:墙内也可以参考stormzhang的这篇博客链接)。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="@string/name"
        style="@style/FancyText"
        />

    <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 emulatorlicense吧。
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开发经验。

License

Futurice Oy
Creative Commons Attribution 4.0 International (CC BY 4.0)

Translation

Translated to Chinese by andyiac

使用Kotlin进行Android开发:最佳实践和示例 在Kotlin中,函数的定义使用fun关键字。函数的参数和返回值都可以有类型推断,也可以显式指定类型。本篇博客介绍了在Android开发中使用Kotlin的最佳实践和示例。我们从选择Kotlin的优势开始,回顾了Kotlin的基础知识,然后深入探讨了Kotlin在Android开发中的应用。我们探讨了MVVM架构、分层架构、异步编程和协程、Kotlin的扩展函数、Kotlin标准库和Android KTX,以及数据类和委托的使用。 阅读详情

相关推荐

基于android studio实现通讯录管理系统源代码,安卓移动开发课程设计

使用android studio 导入项目,修改文件定制自己想要的布局风格以及功能 如果导入项目后报错,哪么自己先创建好项目,将下载好的项目的代码进行复制 Phone、Datebase、ListAdapter、为单独的类,不是active布局 AddPhoneNumber、EditPhone、属于active布局,创建文件时需要选择active布局文件 list_item.xml是单独的文件,创建时候需要选择创建xml文件下的layout xml file。 文件中的按钮背景文件在drawable文件夹下 所用到的icon资源位于mipmap文件夹下 values文件夹下声明了部分文字以及颜色样式。

Android开发最佳实践建议

注:本文转载自Android Best Practice 从Futurice公司Android开发者中学到的经验。 遵循以下准则,避免重复发明轮子。

Mrljdx的专栏 899

android studio实现安卓移动开发课程设计通讯录管理系统源代码.zip

安卓移动开发课程设计通讯录管理系统源代码 使用说明: 使用android studio 导入项目,修改文件定制自己想要的布局风格以及功能 如果导入项目后报错,哪么自己先创建好项目,将下载好的项目的代码进行复制 Phone、Datebase、ListAdapter、为单独的类,不是active布局 AddPhoneNumber、EditPhone、属于active布局,创建文件时需要选择active布局文件 list_item.xml是单独的文件,创建时候需要选择创建xml文件下的layout xml file。 文件中的按钮背景文件在drawable文件夹下 所用到的icon资源位于mipmap文件夹下 values文件夹下声明了部分文字以及颜色样式。

Android 9.0 AOSP源码目录介绍

本章节基于Android Version android-9.0.0。

501846585_QQAndroid_java 1458

vue中使用video-player视频插件,第一次无法监听父组件穿过来的值解决办法

需求: 页面![在这里插入图片描述](https://img-blog.csdnimg.cn/20201208141906802.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0FfOTg4OA==,size_16,color_FFFFFF,t_70) 作品清单是从后端请求回来的不同格式的url,前端需求根据后缀动态判断格式,然后对齐进行下载和

A_9888的博客 768

Python爬虫实战:用BeautifulSoup和Pandas轻松抓取去哪儿网景点数据(附完整代码)

本文详细介绍了如何使用Python的BeautifulSoup和Pandas库构建一个高效的旅游数据爬虫,从去哪儿网抓取景点数据。内容涵盖环境准备、网页结构分析、核心代码实现、反爬策略以及数据清洗与存储,提供完整代码示例,帮助开发者快速掌握数据采集技术。

river的博客 357

Android开发最佳实践手册全网独一份,知名大企都在用,建议收藏

本文是Futurice公司的Android开发人员总结的最佳实践,遵循这些准则可以避免重复制造轮子。如果你对iOS或者Windows Phone开发感兴趣,那么也请看看iOS最佳实践和Windows客户端开发最佳实践。使用 Gradle 和它推荐的工程结构把密码和敏感数据放在gradle.properties不要自己写 HTTP 客户端,使用Volley或OkHttp库使用Jackson库解析JSON数据。

2401_89872687的博客 919

关于海康网络摄像头使用VLC或者Opencv拉流有延迟的问题

先说结论,我用VLC或者Pyhton opencv直接拉取海康网络摄像头的rtsp流,会有1-2s延时,特别明显。环境:Windows + VLC / Openc-Python。如上面文章介绍,我使用的时候遇到一处错误,需要把代码中的。海康SDK:与网页视频相比,几乎是同步的。上面说的延时,也是与摄像头网页视频相比的。ffplay 去掉缓存:延时1s左右。这两处地方改成左斜杠,才能运行。opencv拉流使用的是。多线程:延时1s左右。

yljxh的博客 4498

Android程序性能设计最佳实践

Android应用应该要很快,更精确的说应该是要有效率。那就是说移动设备环境中有限的计算能力和数据存储,很小的屏幕,有限的电池寿命中要更有效率。 这篇博客我就会向你展示为性能而设计的最佳实践。

Xieisabug 1779

《深入浅出图神经网络:GNN原理解析》学习笔记

期末考完了,该上道了 目录一、图的概述1.基本概念2.图的存储和遍历3.应用分类二、神经网络基础1.机器学习2.神经网络三、卷积神经网络(CNN)1.卷积与池化2.卷积神经网络四、表示学习1.意义2.自编码器五、图信号处理与图卷积神经网络1.矩阵计算前置知识2.图信号与图的拉普拉斯矩阵3.图傅里叶变换4.图滤波器(Graph Filter)5.图卷积神经网络(GCN) 一、图的概述 1.基本概念 1.顶点(Vertex)表示研究的对象,边(Edge)表示两个对象之间特定的研究关系 2.图为顶点和边的集合.

且视他人之疑目如盏盏鬼火,大胆地去走你的夜路 2045

LTspice导入德州仪器SPICE模型的实用指南与常见问题解析

本文详细介绍了如何在LTspice中导入德州仪器的SPICE模型,包括模型文件获取、路径管理、导入步骤及常见问题解析。通过实用指南帮助工程师精确仿真电路性能,提升设计效率,重点涵盖了第三方模型的导入教程和最佳实践。

kk1234的博客 307

一文看懂现代 Android 开发最佳实践

What is MAD? MAD 的全称是 Modern Android Development , 它是一系列技术栈和工具链的集合,涵盖了从编程语言到开发框架等各个环节。 Android 自 08 年诞生之后的多年间 SDK 变化一直不大,开发方式较为固定。13 年起技术更新逐渐加速,特别是 17年之后, 随着 Kotlin 及 Jetpack 等新技术的出现 Android 开发方式发生了很大变化,去年推出的 Jetpack Compose 更是将这种变化推向了新阶段。Goolge 将这些新技术下的

移动端开发干货分享 1622

【ATC/DTC方法第一期】经典平均/昼夜温度周期ATC/DTC方法介绍(含Python代码实现)

【ATC/DTC方法第一期】经典平均/昼夜温度周期ATC/DTC方法介绍(含Python代码实现)

WW、forever的博客 484

Android开发进阶:Kotlin语言最佳实践

Kotlin中的函数定义非常灵活,可以使用简洁的语法。在定义函数时,尽量使用默认参数和命名参数,这样可以使函数调用更加清晰。示例println("你好,$name,你今年$age岁了。") greet(name = "李四") // 输出:你好,李四,你今年18岁了。 greet("李四", 28) // 输出:你好,李四,你今年28岁了。本文从Kotlin基础语法、高级特性以及Android开发最佳实践等方面,详细阐述了Android开发进阶:Kotlin语言最佳实践。

2501_92487957的博客 516

Coze实战:解锁多Bot协同与条件分支工作流的奥秘

本文详细介绍了在字节跳动Coze平台实现多Bot协同与条件分支工作流的方法。首先阐述了Coze平台的功能优势,包括丰富的插件、知识库和工作流功能。随后分步骤讲解了多Bot协同的实现:从准备工作、创建Bot到协同配置,并提供了电商客服的实例演示。在条件分支工作流部分,详细说明了条件节点的作用类型、条件设定方法以及具体配置操作,强调测试优化的重要性。最后通过电商平台综合案例,展示了多Bot协同与条件分支的实际应用效果,并针对常见问题提供解决方案。文章为开发者在Coze平台上构建智能应用提供了实用指导,有助于提升

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 449

单稳态触发器Multisim电路仿真——硬件工程师笔记

本文系统介绍了单稳态触发器的基础知识及其实现方式。主要内容包括:1)单稳态触发器的工作原理、电路结构、特点及应用;2)555定时器实现单稳态触发器的配置及工作过程;3)使用反相器和与非门实现积分型和微分型单稳态触发器的电路结构及工作原理。文章详细阐述了各种实现方式的特性、应用场景及设计考虑,为硬件工程师提供了实用的电路设计参考。最后还附有相关笔试面试题链接,便于读者进一步学习扩展。

XU157303764的博客 1875

Android开发进阶:性能优化与最佳实践

本文从布局优化、内存优化和绘制优化三个方面详细阐述了 Android 开发进阶中的性能优化与最佳实践。通过合理使用约束布局、Include 标签、内存缓存、图片压缩、硬件加速等技术,可以有效提高 Android 应用的性能。在未来的开发过程中,开发者还需不断学习新技术、新方法,紧跟 Android 开发的发展趋势。关注 Android 官方文档,了解最新性能优化技巧;学习业界优秀的性能优化框架和库;深入研究 Android 系统底层原理,探索更多性能优化方法;

2501_92489169的博客 458

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Android开发进阶:性能调优最佳实践

本文从多个方面详细阐述了Android开发进阶中的性能调优最佳实践,包括优化布局、内存使用、图片加载、数据库操作、动画效果以及应用启动速度。掌握这些最佳实践有助于开发者打造高性能的Android应用,提高用户体验。在实际开发过程中,开发者应不断积累经验,关注性能调优的最新技术动态,以适应日益变化的移动应用市场。同时,本文的目的和重要性在于为开发者提供一个全面的性能调优指南,希望开发者能够从中受益,为用户提供更好的应用体验。

emilio15979289的博客 461

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Android开发进阶:性能优化最佳实践

性能优化是Android开发中永恒的话题。通过布局优化、内存优化、绘制优化和网络优化等多个方面的努力,我们可以显著提升应用的性能,为用户提供更好的体验。在未来的Android开发中,性能优化将继续是开发者关注的焦点。我们应不断学习新的性能优化技术和方法,以应对日益复杂的应用需求。同时,我们还需要关注用户的需求和反馈,不断优化应用性能,提升用户体验。建议:开发者应定期进行性能分析,找出性能瓶颈,针对性地进行优化。此外,加强与其他开发者的交流,分享性能优化的经验和心得,也是提高自己技能的有效途径。

2501_92489105的博客 286

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【Android开发进阶必修】:Kotlin密封类定义与状态管理最佳实践

掌握Kotlin密封类定义技巧,高效解决状态管理难题。适用于Android多状态场景,结合when表达式实现类型安全、可维护性强的代码结构。核心方法清晰实用,提升开发效率与代码健壮性,值得收藏。

Instrustar的博客 1016

音视频开发进阶指南 - 基于Android与iOS平台的实践

音视频开发进阶指南 - 基于Android与iOS平台的实践 【下载地址】音视频开发进阶指南-基于Android与iOS平台的实践分享 欢迎来到《音视频开发进阶指南-基于Android与iOS平台的实践》资源页面。这份宝贵的PDF文档是专为那些希望深入理解并掌握移动平台上音视频技术开发者量身打造的。无论是对于初学者还是已...

gitblog_06644的博客 952

android开发字号设置最佳实践

👉80%用 style / dimens 统一管理,20%特殊情况单独设置也就是:用dimension定义字体大小,例如<dimen >然后用一个textview来引用这个dimen,这样一般的textview就不用设置大小了----------但是一般的textview本来默认大小就是对的啊,然后回复是:这样更加利于后期维护,因为看起来很直观:但是我想说的是:这样在代码里面用的话,那么多的constrainlayout就会非常麻烦。

220

【精华】安卓开发学习路线规划

  近一段时间经常被朋友问到如何从零开始学习安卓,成为一名安卓开发工程师。不得不感叹,现在各行各业都有不少人在涌向IT/互联网行业,希望从事程序开发工作,竞争越来越激烈了。借此机会,我梳理了一下自己所学所知的安卓知识,制定了这份安卓开发学习路线规划,希望能帮助到有志于安卓开发的伙伴能尽快找到学习的方向,进入安卓开发的大门! 一、安卓开发学习路线   安卓开发可以从深度和广度两个维度进行学习。大方向上看,Android在向诸如Flutter这样的跨平台技术演进,混合式开发、大前端等正成为移动端的发展方向和热门

time-space的博客 2万+

android-best-practices:安卓开发最佳实践指南

android-best-practices:安卓开发最佳实践指南 【免费下载链接】android-best-practices Do's and Don'ts for Android development, by Futurice developers ...

gitblog_00534的博客 973

安卓进阶之android系统架构

安卓进阶知识之android系统架构学习的笔记,结合了《进阶之光》、一些博客、官方文档和个人的理解

Suzy_MM的博客 3348

安卓开发—Android基础

安卓开发—Android基础 移动开发 移动开发也叫做移动互联网开发。是指以手机、PDA、UMPC等便携终端为基础,进行相应的开发工作,由于这些随身设备基本都采用无线上网的方式,业内也称作为无线开发。 移动应用包括早期的WM掌上助理设备,Web os设备、java设备、塞班设备,以及现在现在火热的安卓和苹果设备等移动应用的开发。 谷歌提供安卓平台,要开发,只需要掌握java语言,就可以在安卓平台上进行开发。 三大主流移动开发平台 以下是Android、IOS、Windows phone三大主流移

cs_loser的博客 1万+
上一篇: [Android进阶]Java、Android 内存泄漏总结
陶程
博客等级 码龄12年 360粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值