[
  {
    "path": "LICENSE",
    "content": "Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.\n\nUsing Creative Commons Public Licenses\n\nCreative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.\n\n    Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors.\n\n    Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public.\n\nCreative Commons Attribution 4.0 International Public License\n\nBy exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License (\"Public License\"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.\n\nSection 1 – Definitions.\n\n    Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.\n    Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.\n    Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.\n    Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.\n    Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.\n    Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.\n    Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.\n    Licensor means the individual(s) or entity(ies) granting rights under this Public License.\n    Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.\n    Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.\n    You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.\n\nSection 2 – Scope.\n\n    License grant.\n        Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:\n            reproduce and Share the Licensed Material, in whole or in part; and\n            produce, reproduce, and Share Adapted Material.\n        Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.\n        Term. The term of this Public License is specified in Section 6(a).\n        Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.\n        Downstream recipients.\n            Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.\n            No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.\n        No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).\n\n    Other rights.\n        Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.\n        Patent and trademark rights are not licensed under this Public License.\n        To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.\n\nSection 3 – License Conditions.\n\nYour exercise of the Licensed Rights is expressly made subject to the following conditions.\n\n    Attribution.\n\n        If You Share the Licensed Material (including in modified form), You must:\n            retain the following if it is supplied by the Licensor with the Licensed Material:\n                identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);\n                a copyright notice;\n                a notice that refers to this Public License;\n                a notice that refers to the disclaimer of warranties;\n                a URI or hyperlink to the Licensed Material to the extent reasonably practicable;\n            indicate if You modified the Licensed Material and retain an indication of any previous modifications; and\n            indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.\n        You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.\n        If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.\n        If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License.\n\nSection 4 – Sui Generis Database Rights.\n\nWhere the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:\n\n    for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;\n    if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and\n    You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.\n\nFor the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.\n\nSection 5 – Disclaimer of Warranties and Limitation of Liability.\n\n    Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.\n    To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.\n\n    The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.\n\nSection 6 – Term and Termination.\n\n    This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.\n\n    Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:\n        automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or\n        upon express reinstatement by the Licensor.\n    For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.\n    For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.\n    Sections 1, 5, 6, 7, and 8 survive termination of this Public License.\n\nSection 7 – Other Terms and Conditions.\n\n    The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.\n    Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.\n\nSection 8 – Interpretation.\n\n    For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.\n    To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.\n    No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.\n    Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.\n\nCreative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.\n\nCreative Commons may be contacted at creativecommons.org."
  },
  {
    "path": "README.md",
    "content": "# Best practices in Android development\n\nAvoid reinventing the wheel by following these guidelines. Lessons learned from Android developers in [Futurice](http://www.futurice.com). If you are interested in iOS or Windows Phone development, be sure to check also our [**iOS Good Practices**](https://github.com/futurice/ios-good-practices) and [**Windows App Development Best Practices**](https://github.com/futurice/windows-app-development-best-practices) documents.\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091) \n[![Spice Program Sponsored](https://img.shields.io/badge/chilicorn-sponsored-brightgreen.svg?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAPCAMAAADjyg5GAAABqlBMVEUAAAAzmTM3pEn%2FSTGhVSY4ZD43STdOXk5lSGAyhz41iz8xkz2HUCWFFhTFFRUzZDvbIB00Zzoyfj9zlHY0ZzmMfY0ydT0zjj92l3qjeR3dNSkoZp4ykEAzjT8ylUBlgj0yiT0ymECkwKjWqAyjuqcghpUykD%2BUQCKoQyAHb%2BgylkAyl0EynkEzmkA0mUA3mj86oUg7oUo8n0k%2FS%2Bw%2Fo0xBnE5BpU9Br0ZKo1ZLmFZOjEhesGljuzllqW50tH14aS14qm17mX9%2Bx4GAgUCEx02JySqOvpSXvI%2BYvp2orqmpzeGrQh%2Bsr6yssa2ttK6v0bKxMBy01bm4zLu5yry7yb29x77BzMPCxsLEzMXFxsXGx8fI3PLJ08vKysrKy8rL2s3MzczOH8LR0dHW19bX19fZ2dna2trc3Nzd3d3d3t3f39%2FgtZTg4ODi4uLj4%2BPlGxLl5eXm5ubnRzPn5%2Bfo6Ojp6enqfmzq6urr6%2Bvt7e3t7u3uDwvugwbu7u7v6Obv8fDz8%2FP09PT2igP29vb4%2BPj6y376%2Bu%2F7%2Bfv9%2Ff39%2Fv3%2BkAH%2FAwf%2FtwD%2F9wCyh1KfAAAAKXRSTlMABQ4VGykqLjVCTVNgdXuHj5Kaq62vt77ExNPX2%2Bju8vX6%2Bvr7%2FP7%2B%2FiiUMfUAAADTSURBVAjXBcFRTsIwHAfgX%2FtvOyjdYDUsRkFjTIwkPvjiOTyX9%2FAIJt7BF570BopEdHOOstHS%2BX0s439RGwnfuB5gSFOZAgDqjQOBivtGkCc7j%2B2e8XNzefWSu%2BsZUD1QfoTq0y6mZsUSvIkRoGYnHu6Yc63pDCjiSNE2kYLdCUAWVmK4zsxzO%2BQQFxNs5b479NHXopkbWX9U3PAwWAVSY%2FpZf1udQ7rfUpQ1CzurDPpwo16Ff2cMWjuFHX9qCV0Y0Ok4Jvh63IABUNnktl%2B6sgP%2BARIxSrT%2FMhLlAAAAAElFTkSuQmCC)](https://spiceprogram.org/)\n\n## Summary\n\n#### [Use Gradle and its default project structure](#build-system)\n#### [Put passwords and sensitive data in gradle.properties](#gradle-configuration)\n#### [Use the Jackson library to parse JSON data](#libraries)\n#### [Don't write your own HTTP client, use OkHttp libraries](#networklibs)\n#### [Avoid Guava and use only a few libraries due to the *65k method limit*](#methodlimitation)\n#### [Sail carefully when choosing between Activities and Fragments](#activities-and-fragments)\n#### [Layout XMLs are code, organize them well](#resources)\n#### [Use styles to avoid duplicate attributes in layout XMLs](#styles)\n#### [Use multiple style files to avoid a single huge one](#splitstyles)\n#### [Keep your colors.xml short and DRY, just define the palette](#colorsxml)\n#### [Also keep dimens.xml DRY, define generic constants](#dimensxml)\n#### [Do not make a deep hierarchy of ViewGroups](#deephierarchy)\n#### [Avoid client-side processing for WebViews, and beware of leaks](#webviews)\n#### [Use JUnit for unit tests, Espresso for connected (UI) tests, and AssertJ-Android for easier assertions in your Android tests](#test-frameworks)\n#### [Always use ProGuard or DexGuard](#proguard-configuration)\n#### [Use SharedPreferences for simple persistence, otherwise ContentProviders](#data-storage)\n#### [Use Stetho to debug your application](#use-stetho)\n#### [Use Leak Canary to find memory leaks](#use-leakcanary)\n#### [Use continuous integration](#use-continuous-integration-1)\n\n----------\n\n### Android SDK\n\nPlace your [Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools) somewhere in your home directory or some other application-independent location. Some distributions of IDEs include the SDK when installed, and may place it under the same directory as the IDE. This can be bad when you need to upgrade (or reinstall) the IDE, as you may lose your SDK installation, forcing a long and tedious redownload.\n\nAlso avoid putting the SDK in a system-level directory that might need root permissions, to avoid permissions issues.\n\n### Build system\n\nYour default option should be [Gradle](https://gradle.org) using the [Android Gradle plugin](https://developer.android.com/studio/build/index.html). \n\nIt is important that your application's build process is defined by your Gradle files, rather than being reliant on IDE specific configurations. This allows for consistent builds between tools and better support for continuous integration systems.\n\n### Project structure\n\nAlthough Gradle offers a large degree of flexibility in your project structure, unless you have a compelling reason to do otherwise, you should accept its [default structure](https://developer.android.com/studio/build/index.html#sourcesets) as this simplify your build scripts. \n\n### Gradle configuration\n\n**General structure.** Follow [Google's guide on Gradle for Android](https://developer.android.com/studio/build/index.html).\n\n**minSdkVersion: 21** We recommend to have a look at the [Android version usage chart](https://developer.android.com/about/dashboards/index.html#Platform) before defining the minimum API required. Remember that the statistics given are global statistics and may differ when targeting a specific regional/demographic market. It is worth mentioning that some material design features are only available on Android 5.0 (API level 21) and above. And also, from API 21, the multidex support library is not needed anymore.\n\n**Small tasks.** Instead of (shell, Python, Perl, etc) scripts, you can make tasks in Gradle. Just follow [Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF) for more details. Google also provides some helpful [Gradle recipes](https://developer.android.com/studio/build/gradle-tips.html), specific to Android.\n\n**Passwords.** In your app's `build.gradle` you will need to define the `signingConfigs` for the release build. Here is what you should avoid:\n\n_Don't do this_. This would appear in the version control system.\n\n```groovy\nsigningConfigs {\n    release {\n        // DON'T DO THIS!!\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nInstead, make a `gradle.properties` file which should _not_ be added to the version control system:\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nThat file is automatically imported by Gradle, so you can use it in `build.gradle` as such:\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**Prefer Maven dependency resolution to importing jar files.** If you explicitly include jar files in your project, they will be a specific frozen version, such as `2.1.1`. Downloading jars and handling updates is cumbersome and is a problem that Maven already solves properly. Where possible, you should attempt to use Maven to resolve your dependencies, for example:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp3:3.8.0'\n}\n```    \n\n**Avoid Maven dynamic dependency resolution**\nAvoid the use of dynamic dependency versions, such as `2.1.+` as this may result in different and unstable builds or subtle, untracked differences in behavior between builds. The use of static versions such as `2.1.1` helps create a more stable, predictable and repeatable development environment.\n\n**Use different package name for non-release builds**\nUse `applicationIdSuffix` for *debug* [build type](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types) to be able to install both *debug* and *release* apk on the same device (do this also for custom build types, if you need any). This will be especially valuable after your app has been published.\n\n```groovy\nandroid {\n    buildTypes {\n        debug {\n            applicationIdSuffix '.debug'\n            versionNameSuffix '-DEBUG'\n        }\n\n        release {\n            // ...\n        }\n    }\n}\n```\n\nUse different icons to distinguish the builds installed on a device—for example with different colors or an overlaid  \"debug\" label. Gradle makes this very easy: with default project structure, simply put *debug* icon in `app/src/debug/res` and *release* icon in `app/src/release/res`. You could also [change app name](http://stackoverflow.com/questions/24785270/how-to-change-app-name-per-gradle-build-type) per build type, as well as  `versionName` (as in the above example).\n\n**Share debug app keystore file**\nSharing the debug APK keystore file via the app repository saves time when testing on shared devices and avoids the uninstalling/reinstalling of the app. It also simplifies the processing of working with some Android SDKs, such as Facebook, which require the registration of a single key store hash. Unlike the release key file, the debug key file can safely be added to your repository.\n\n**Share code style formatting defintions**\nSharing the code style and formatting definitions via the app repository helps ensure a visually consistent code base and makes code comprehension and reviews easier.\n\n### Android Studio as your main IDE\n\nThe recommended IDE for Android development is [Android Studio](https://developer.android.com/sdk/installing/studio.html) because it is developed and constantly updated by Google, has good support for Gradle, contains a range of useful monitoring and analysis tools and is fully tailored for Android development.\n\nAvoid adding Android Studio's specific configuration files, such as `.iml` files to the version control system as these often contain configurations specific of your local machine, which won't work for your colleagues.\n\n### Libraries\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** is a Java library for JSON serialization and deserialization, it has a wide-scoped and versatile API, supporting various ways of processing JSON: streaming, in-memory tree model, and traditional JSON-POJO data binding. \n\n[Gson](https://code.google.com/p/google-gson/) is another popular choice and being a smaller library than Jackson, you might prefer it to avoid 65k methods limitation. Also, if you are using  \n\n[Moshi](https://github.com/square/moshi), another of [Square's](https://github.com/square) open source libraries, builds upon learnings from the development of Gson and also integrates well with Kotlin.\n\n<a name=\"networklibs\"></a>\n**Networking, caching, and images.** There are a couple of battle-proven solutions for performing requests to backend servers, which you should use rather than implementing your own client. We recommend basing your stack around [OkHttp](http://square.github.io/okhttp/) for efficient HTTP requests and using [Retrofit](http://square.github.io/retrofit/) to provide a typesafe layer. If you choose Retrofit, consider [Picasso](http://square.github.io/picasso/) for loading and caching images.\n\nRetrofit, Picasso and OkHttp are created by the same company, so they complement each other nicely and compatability issues are uncommon.\n\n[Glide](https://github.com/bumptech/glide) is another option for loading and caching images. It has support for animated GIFs, circular images and claims of better performance than Picasso, but also a bigger method count.\n\n**RxJava** is a library for Reactive Programming, in other words, handling asynchronous events. It is a powerful paradigm, but it also has a steep learning curve. We recommend taking some caution before using this library to architect the entire application. We have written some blog posts on it: [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift). For a reference app, our open source app [Freesound Android](https://github.com/futurice/freesound-android) makes extensive use of RxJava 2.\n\nIf you have no previous experience with Rx, start by applying it only for responses from app's backend APIs. Alternatively, start by applying it for simple UI event handling, like click events or typing events on a search field. If you are confident in your Rx skills and want to apply it to the whole architecture, then write documentation on all the tricky parts. Keep in mind that another programmer unfamiliar to RxJava might have a very hard time maintaining the project. Do your best to help them understand your code and also Rx.\n\nUse [RxAndroid](https://github.com/ReactiveX/RxAndroid) for Android threading support and [RxBinding](https://github.com/JakeWharton/RxBinding) to easily create Observables from existing Android components.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)** is a Java library for using Lambda expression syntax in Android and other pre-JDK8 platforms. It helps keep your code tight and readable especially if you use a functional style, such as in RxJava.\n\nAndroid Studio offers code assist support for Java 8 lambdas. If you are new to lambdas, just use the following to get started:\n\n- Any interface with just one method is \"lambda friendly\" and can be folded into the more tight syntax\n- If in doubt about parameters and such, write a normal anonymous inner class and then let Android Studio fold it into a lambda for you.\n\nNote that from Android Studio 3.0, [Retrolambda is no longer required](https://developer.android.com/studio/preview/features/java8-support.html).\n\n<a name=\"methodlimitation\"></a>\n**Beware of the dex method limitation, and avoid using many libraries.** Android apps, when packaged as a dex file, have a hard limitation of 65536 referenced methods [[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). You will see a fatal error on compilation if you pass the limit. For that reason, use a minimal amount of libraries, and use the [dex-method-counts](https://github.com/mihaip/dex-method-counts) tool to determine which set of libraries can be used in order to stay under the limit. Especially avoid using the Guava library, since it contains over 13k methods.\n\n### Activities and Fragments\n\nThere is no consensus among the community nor Futurice developers how to best organize Android architectures with Fragments and Activities. Square even has [a library for building architectures mostly with Views](https://github.com/square/mortar), bypassing the need for Fragments, but this still is not considered a widely recommendable practice in the community.\n\nBecause of Android API's history, you can loosely consider Fragments as UI pieces of a screen. In other words, Fragments are normally related to UI. Activities can be loosely considered to be controllers, they are especially important for their lifecycle and for managing state. However, you are likely to see variation in these roles: activities might take UI roles ([delivering transitions between screens](https://developer.android.com/about/versions/lollipop.html)), and [fragments might be used solely as controllers](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). We suggest you sail carefully, making informed decisions since there are drawbacks for choosing a fragments-only architecture, or activities-only, or views-only. Here is some advice on what to be careful with, but take them with a grain of salt:\n\n- Avoid using [nested fragments](https://developer.android.com/about/versions/android-4.2.html#NestedFragments) extensively, because [matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/) can occur. Use nested fragments only when it makes sense (for instance, fragments in a horizontally-sliding ViewPager inside a screen-like fragment) or if it's a well-informed decision.\n- Avoid putting too much code in Activities. Whenever possible, keep them as lightweight containers, existing in your application primarily for the lifecycle and other important Android-interfacing APIs. Prefer single-fragment activities instead of plain activities - put UI code into the activity's fragment. This makes it reusable in case you need to change it to reside in a tabbed layout, or in a multi-fragment tablet screen. Avoid having an activity without a corresponding fragment, unless you are making an informed decision.\n\n### Java packages structure\n\nWe recommend using a *feature based* package structure for your code. This has the following benefits:\n\n- Clearer feature dependency and interface boundaries.\n- Promotes encapsulation.\n- Easier to understand the components that define the feature.  \n- Reduces risk of unknowingly modifying unrelated or shared code.\n- Simpler navigation: most related classes will be in the one package.\n- Easier to remove a feature.\n- Simplifies the transition to module based build structure (better build times and Instant Apps support)\n\nThe alternative approach of defining your packages by *how* a feature is built (by placing related Activities, Fragments, Adapters etc in separate packages) can lead to a fragmented code base with less implementation flexibility. Most importantly, it hinders your ability to comprehend your code base in terms of its primary role: to provide features for your app.   \n\n### Resources\n\n**Naming.** Follow the convention of prefixing the type, as in `type_foo_bar.xml`. Examples: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**Organizing layout XMLs.** If you're unsure how to format a layout XML, the following convention may help.\n\n- One attribute per line, indented by 4 spaces\n- `android:id` as the first attribute always\n- `android:layout_****` attributes at the top\n- `style` attribute at the bottom\n- Tag closer `/>` on its own line, to facilitate ordering and adding attributes.\n- Rather than hard coding `android:text`, consider using [Designtime attributes](http://tools.android.com/tips/layout-designtime-attributes) available for Android Studio.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\nAs a rule of thumb, attributes `android:layout_****` should be defined in the layout XML, while other attributes `android:****` should stay in a style XML. This rule has exceptions, but in general works fine. The idea is to keep only layout (positioning, margin, sizing) and content attributes in the layout files, while keeping all appearance details (colors, padding, font) in styles files.\n\nThe exceptions are:\n\n- `android:id` should obviously be in the layout files\n- `android:orientation` for a `LinearLayout` normally makes more sense in layout files\n- `android:text` should be in layout files because it defines content\n- Sometimes it will make sense to make a generic style defining `android:layout_width` and `android:layout_height` but by default these should appear in the layout files\n\n<a name=\"styles\"></a>\n**Use styles.** Almost every project needs to properly use styles, because it is very common to have a repeated appearance for a view. At least you should have a common style for most text content in the application, for example:\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nApplied to TextViews:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\nYou probably will need to do the same for buttons, but don't stop there yet. Go beyond and move a group of related and repeated `android:****` attributes to a common style.\n\n<a name=\"splitstyles\"></a>\n**Split a large style file into other files.** You don't need to have a single `styles.xml` file. Android SDK supports other files out of the box, there is nothing magical about the name `styles`, what matters are the XML tags `<style>` inside the file. Hence you can have files `styles.xml`, `styles_home.xml`, `styles_item_details.xml`, `styles_forms.xml`. Unlike resource directory names which carry some meaning for the build system, filenames in `res/values` can be arbitrary.\n\n<a name=\"colorsxml\"></a>\n**`colors.xml` is a color palette.** There should be nothing in your `colors.xml` other than a mapping from a color name to an RGBA value. This helps avoid repeating RGBA values and as such will make it easy to change or refactor colors, and also will make it explicit how many different colors are being used. Normally for a aesthetic UI, it is important to reduce the variety of colors being used.\n \n*So, don't define your colors.xml like this:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n</resources>    \n```\n\nInstead, do this:\n\n```xml\n<resources>\n    <!-- grayscale -->\n    <color name=\"white\">#FFFFFF</color>\n   \n    <!-- basic colors -->\n    <color name=\"blue\">#2A91BD</color>\n</resources>\n```\n\nAsk the designer of the application for this palette. The names do not need to be plain color names as \"green\", \"blue\", etc. Names such as \"brand_primary\", \"brand_secondary\", \"brand_negative\" are totally acceptable as well.\n\nBy referencing the color palette from your styles allows you to abstract the underlying colors from their usage in the app, as per:\n\n- `colors.xml` - defines only the color palette.\n- `styles.xml` - defines styles which reference the color palette and reflects the color usage. (e.g. the button foreground is white).\n- `activity_main.xml` - references the appropriate style in `styles.xml` to color the button.\n\nIf needed, even further separation between underlying colors and style usage can be achieved by defined an additional color resource file which references the color palette. As per:\n\n```xml\n<color name=\"button_foreground\">@color/white</color> \n<color name=\"button_background\">@color/blue</color> \n```\n\nThen in styles.xml:\n\n```xml\n<style name=\"AcceptButton\">\n    <item name=\"android:foreground\">@color/button_foreground</item>\n    <item name=\"android:background\">@color/button_background</item>\n</style>\n```\n\nThis approach offers improved color refactoring and more stable style definitions when multiple related styles share similar color and usage properties. However, it comes at the cost of maintaining another set of color mappings. \n\n<a name=\"dimensxml\"></a>\n**Treat dimens.xml like colors.xml.** You should also define a \"palette\" of typical spacing and font sizes, for basically the same purposes as for colors. A good example of a dimens file:\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\nYou should use the `spacing_****` dimensions for layouting, in margins and paddings, instead of hard-coded values, much like strings are normally treated. This will give a consistent look-and-feel, while making it easier to organize and change styles and layouts.\n\n**strings.xml**\n\nName your strings with keys that resemble namespaces, and don't be afraid of repeating a value for two or more keys. Languages are complex, so namespaces are necessary to bring context and break ambiguity.\n\n**Bad**\n```xml\n<string name=\"network_error\">Network error</string>\n<string name=\"call_failed\">Call failed</string>\n<string name=\"map_failed\">Map loading failed</string>\n```\n\n**Good**\n```xml\n<string name=\"error_message_network\">Network error</string>\n<string name=\"error_message_call\">Call failed</string>\n<string name=\"error_message_map\">Map loading failed</string>\n```\n\nDon't write string values in all uppercase. Stick to normal text conventions (e.g., capitalize first character). If you need to display the string in all caps, then do that using for instance the attribute [`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) on a TextView.\n\n**Bad**\n```xml\n<string name=\"error_message_call\">CALL FAILED</string>\n```\n\n**Good**\n```xml\n<string name=\"error_message_call\">Call failed</string>\n```\n\n<a name=\"deephierarchy\"></a>\n**Avoid a deep hierarchy of views.** Sometimes you might be tempted to just add yet another LinearLayout, to be able to accomplish an arrangement of views. This kind of situation may occur:\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nEven if you don't witness this explicitly in a layout file, it might end up happening if you are inflating (in Java) views into other views.\n\nA couple of problems may occur. You might experience performance problems, because there is a complex UI tree that the processor needs to handle. Another more serious issue is a possibility of [StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views).\n\nTherefore, try to keep your views hierarchy as flat as possible: learn how to use [ConstraintLayout](https://developer.android.com/training/constraint-layout/index.html), how to [optimize your layouts](http://developer.android.com/training/improving-layouts/optimizing-layout.html) and to use the [`<merge>` tag](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts).\n\n<a name=\"webviews\"></a>\n**Beware of problems related to WebViews.** When you must display a web page, for instance for a news article, avoid doing client-side processing to clean the HTML, rather ask for a \"*pure*\" HTML from the backend programmers. [WebViews can also leak memory](http://stackoverflow.com/questions/3130654/memory-leak-in-webview) when they keep a reference to their Activity, instead of being bound to the ApplicationContext. Avoid using a WebView for simple texts or buttons, prefer the platform's widgets.\n\n\n### Test Frameworks\n\n**Use [JUnit](https://developer.android.com/training/testing/unit-testing/local-unit-tests.html) for unit testing** Plain, Android dependency-free unit testing on the JVM is best done using [Junit](https://junit.org). \n\n**Avoid [Robolectric](http://robolectric.org/)** Prior to the improved support for JUnit in the Android build system, Robolectric was promoted as a test framework seeking to provide tests \"disconnected from device\" for the sake of development speed. However, testing under Robolectric is inaccurate and incomplete as it works by providing mock implementations of the Android platform, which provides no guarantees of correctness. Instead, use a combination of JVM based unit tests and dedicated on-device integration tests.\n\n**[Espresso](https://developer.android.com/training/testing/ui-testing/espresso-testing.html) makes writing UI tests easy.**\n\n**[AssertJ-Android](http://square.github.io/assertj-android/) an AssertJ extension library making assertions easy in Android tests**  Assert-J comes modules easier for you to test Android specific components, such as the Android Support, Google Play Services and Appcompat libraries.\n\nA test assertion will look like:\n\n```java\n// Example assertion using AssertJ-Android\nassertThat(layout).isVisible()\n    .isVertical()\n    .hasChildCount(5);\n```\n\n### Emulators\n\nThe performance of the Android SDK emulator, particularly the x86 variant, has improvement markedly in recent years and is now adequate for most day-to-day development scenarios. However, you should not discount the value of ensuring your application behaves correctly on real devices. Of course, testing on all possible devices is not practical, so rather focus your efforts on devices with a large market share and those most relevant to your app.\n\n### Proguard configuration\n\n[ProGuard](http://proguard.sourceforge.net/) is normally used on Android projects to shrink and obfuscate the packaged code.\n\nWhether you are using ProGuard or not depends on your project configuration. Usually you would configure Gradle to use ProGuard when building a release APK.\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\n\nIn order to determine which code has to be preserved and which code can be discarded or obfuscated, you have to specify one or more entry points to your code. These entry points are typically classes with main methods, applets, midlets, activities, etc.\nAndroid framework uses a default configuration which can be found from `SDK_HOME/tools/proguard/proguard-android.txt`. Using the above configuration, custom project-specific ProGuard rules, as defined in `my-project/app/proguard-rules.pro`, will be appended to the default configuration.\n\nA common problem related to ProGuard is to see the application crashing on startup with `ClassNotFoundException` or `NoSuchFieldException` or similar, even though the build command (i.e. `assembleRelease`) succeeded without warnings.\nThis means one out of two things:\n\n1. ProGuard has removed the class, enum, method, field or annotation, considering it's not required.\n2. ProGuard has obfuscated (renamed) the class, enum or field name, but it's being used indirectly by its original name, i.e. through Java reflection.\n\nCheck `app/build/outputs/proguard/release/usage.txt` to see if the object in question has been removed.\nCheck `app/build/outputs/proguard/release/mapping.txt` to see if the object in question has been obfuscated.\n\nIn order to prevent ProGuard from *stripping away* needed classes or class members, add a `keep` options to your ProGuard config:\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nTo prevent ProGuard from *obfuscating* classes or class members, add a `keepnames`:\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\nRead more at [Proguard](https://www.guardsquare.com/en/proguard/manual/examples) for examples.\n\n**Early in your project, make and test release build** to check whether ProGuard rules are correctly retaining your dependencies. Also whenever you include new libraries or update their dependencies, make a release build and test the APK on a device. Don't wait until your app is finally version \"1.0\" to make a release build, you might get several unpleasant surprises and a short time to fix them.\n\n**Tip.** Save the `mapping.txt` file for every release that you publish to your users. By retaining a copy of the `mapping.txt` file for each release build, you ensure that you can debug a problem if a user encounters a bug and submits an obfuscated stack trace.\n\n**DexGuard**. If you need hard-core tools for optimizing, and specially obfuscating release code, consider [DexGuard](http://www.saikoa.com/dexguard), a commercial software made by the same team that built ProGuard. It can also easily split Dex files to solve the 65k methods limitation.\n\n### Data storage\n\n\n#### SharedPreferences\n\nIf you only need to persist simple values and your application runs in a single process SharedPreferences is probably enough for you. It is a good default option. \n\nThere are some situations where SharedPreferences are not suitable:\n\n* *Performance*: Your data is complex or there is a lot of it\n* *Multiple processes accessing the data*: You have widgets or remote services that run in their own processes and require synchronized data\n* *Relational data* Distinct parts of your data are relational and you want to enforce that those relationships are maintained.\n\nYou can also store more complex objects by serializing them to JSON to store them and deserializing them when retrieving. You should consider the tradeoffs when doing this as it may not be particularly performant, nor maintainable.\n\n#### ContentProviders\n\nIn case SharedPreferences are not enough, you should use the platform standard ContentProviders, which are fast and process safe.\n\nThe single problem with ContentProviders is the amount of boilerplate code that is needed to set them up, as well as low quality tutorials. It is possible, however, to generate the ContentProvider by using a library such as [Schematic](https://github.com/SimonVT/schematic), which significantly reduces the effort.\n\nYou still need to write some parsing code yourself to read the data objects from the Sqlite columns and vice versa. It is possible to serialize the data objects, for instance with Gson, and only persist the resulting string. In this way you lose in performance but on the other hand you do not need to declare a column for all the fields of the data class.\n\n#### Using an ORM\n\nWe generally do not recommend using an Object-Relation Mapping library unless you have unusually complex data and you have a dire need. They tend to be complex and require time to learn. If you decide to go with an ORM you should pay attention to whether or not it is _process safe_ if your application requires it, as many of the existing ORM solutions surprisingly are not.\n\n### Use Stetho \n\n[Stetho](http://facebook.github.io/stetho/) is a debug bridge for Android applications from Facebook that integrates with the Chrome desktop browser's Developer Tools. With Stetho you can easily inspect your application, most notably the network traffic. It also allows you to easily inspect and edit SQLite databases and the shared preferences in your app. You should, however, make sure that Stetho is only enabled in the debug build and not in the release build variant. \n\nAnother alternative is [Chuck](https://github.com/jgilfelt/chuck) which, although offering slightly more simplified functionality, is still useful for testers as the logs are displayed on the device, rather than in the more complicated connected Chrome browser setup that Stetho requires.\n\n### Use LeakCanary\n\n[LeakCanary](https://github.com/square/leakcanary) is a library that makes runtime detection and identification of memory leaks a more routine part of your application development process. See the library [wiki](https://github.com/square/leakcanary/wiki) for details on configuration and usage. Just remember to configure only the \"no-op\" dependency in your release build!\n\n### Use continuous integration\n\nContinuous integration systems let you automatically build and test your project every time you push updates to version control. Continuous integration also runs static code analysis tools, generates the APK files and distributes them.\n[Lint](https://developer.android.com/studio/write/lint.html) and [Checkstyle](http://checkstyle.sourceforge.net/) are tools that ensure the code quality while [Findbugs](http://findbugs.sourceforge.net/) looks for bugs in the code.\n   \nThere is a wide variety of continuous integration software which provide different features. Pricing plans might be for free if your project is open-sourced.\n[Jenkins](https://jenkins.io/) is a good option if you have a local server at your disposal, on the other hand [Travis CI](https://travis-ci.org/) is also a recommended choice if you plan to use a cloud-based continuous integration service.\n\n### Thanks to\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton and other Futurice developers for sharing their knowledge on Android development.\n\n### Acknowledgements\n\n<p align=\"center\">\n  <img alt=\"logo\" src=\"https://raw.githubusercontent.com/futurice/spiceprogram/gh-pages/assets/img/logo/chilicorn_no_text-256.png\" width=\"220\"/>\n</p>\n\nThis project is sponsored by [**Spice Program**](http://spiceprogram.org/chilicorn-history/), our open source and social impact program made with love by [**Futurice**](http://www.futurice.com).\n\n### License\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n"
  },
  {
    "path": "translations/Chinese/README.cn.md",
    "content": "# Android 开发最佳实践\n\n从[Futurice](http://www.futurice.com)公司Android开发者中学到的经验。\n遵循以下准则，避免重复发明轮子。若你对开发iOS或Windows Phone 有兴趣，\n请看[**iOS Good Practices**](https://github.com/futurice/ios-good-practices) 和 [**Windows client Good Practices**](https://github.com/futurice/win-client-dev-good-practices) 这两篇文章。\n\n## 摘要\n\n* 使用 Gradle 和它推荐的工程结构\n* 把密码和敏感数据放在gradle.properties\n* 不要自己写 HTTP 客户端,使用Volley或OkHttp库\n* 使用Jackson库解析JSON数据\n* 避免使用Guava同时使用一些类库来避免*65k method limit*（一个Android程序中最多能执行65536个方法）\n* 使用 Fragments来呈现UI视图\n* 使用 Activities 只是为了管理 Fragments\n* Layout 布局是 XMLs代码，组织好它们\n* 在layoutout XMLs布局时，使用styles文件来避免使用重复的属性\n* 使用多个style文件来避免单一的一个大style文件\n* 保持你的colors.xml 简短DRY(不要重复自己)，只是定义调色板\n* 总是使用dimens.xml DRY(不要重复自己)，定义通用常数\n* 不要做一个深层次的ViewGroup\n* 在使用WebViews时避免在客户端做处理，当心内存泄露\n* 使用Robolectric单元测试，Robotium 做UI测试\n* 使用Genymotion 作为你的模拟器\n* 总是使用ProGuard 和 DexGuard混淆来项目\n\n### Android SDK\n\n将你的[Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools)放在你的home目录或其他应用程序无关的位置。\n当安装有些包含SDK的IDE的时候，可能会将SDK放在IDE同一目录下，当你需要升级（或重新安装）IDE或更换的IDE时，会非常麻烦。\n此外，如果你的IDE是在普通用户下运行，而不是在root下运行，还要避免把SDK放到一下需要sudo权限的系统级别目录下。\n\n### 构建系统\n\n你的默认编译环境应该是[Gradle](http://tools.android.com/tech-docs/new-build-system).\nAnt 有很多限制，也很冗余。使用Gradle，完成以下工作很方便：\n\n- 构建APP不同版本的变种\n- 制作简单类似脚本的任务\n- 管理和下载依赖\n- 自定义秘钥\n- 更多\n\n同时，Android Gradle插件作为新标准的构建系统正在被Google积极的开发。\n\n### 工程结构\n\n有两种流行的结构：老的Ant & Eclipse ADT 工程结构，和新的Gradle & Android Studio 工程结构，\n你应该选择新的工程结构，如果你的工程还在使用老的结构，考虑放弃吧，将工程移植到新的结构。\n\n\n老的结构:\n\n```\nold-structure\n├─ assets\n├─ libs\n├─ res\n├─ src\n│  └─ com/futurice/project\n├─ AndroidManifest.xml\n├─ build.gradle\n├─ project.properties\n└─ proguard-rules.pro\n```\n\n新的结构\n\n```\nnew-structure\n├─ library-foobar\n├─ app\n│  ├─ libs\n│  ├─ src\n│  │  ├─ androidTest\n│  │  │  └─ java\n│  │  │     └─ com/futurice/project\n│  │  └─ main\n│  │     ├─ java\n│  │     │  └─ com/futurice/project\n│  │     ├─ res\n│  │     └─ AndroidManifest.xml\n│  ├─ build.gradle\n│  └─ proguard-rules.pro\n├─ build.gradle\n└─ settings.gradle\n```\n\n主要的区别在于，新的结构明确的分开了'source sets' (`main`,`androidTest`)，这是Gradle的一个理念。\n通过这个你可以做到，例如，添加源组‘paid’和‘free’在src中，让你的应用程序具有付费和免费的两种模式的源代码。\n\n你的项目引用第三方项目库时（例如，library-foobar），拥有一个顶级包名`app`从第三方库项目区分你的应用程序是非常有用的。\n然后`settings.gradle`不断引用这些库项目，其中`app/build.gradle`可以引用。\n\n### Gradle 配置\n\n**常用结构** 参考[Google's guide on Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)\n\n\n**小任务** 除了(shell, Python, Perl, etc)这些脚本语言，你也可以使用Gradle 制作任务。\n更多信息请参考[Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF)。\n\n\n**密码** 在做版本release时你app的 `build.gradle`你需要定义 `signingConfigs`.此时你应该避免以下内容：\n\n\n_不要做这个_ . 这会出现在版本控制中。\n\n```groovy\nsigningConfigs {\n\trelease {\n\t\tstoreFile file(\"myapp.keystore\")\n\t\tstorePassword \"password123\"\n\t\tkeyAlias \"thekey\"\n\t\tkeyPassword \"password789\"\n\t}\n}\n```\n\n而是，建立一个不加入版本控制系统的`gradle.properties`文件。\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\n\n那个文件是gradle自动引入的，你可以在`buld.gradle`文件中使用，例如：\n\n```groovy\nsigningConfigs {\n\trelease {\n\t\ttry {\n\t\t\tstoreFile file(\"myapp.keystore\")\n\t\t\tstorePassword KEYSTORE_PASSWORD\n\t\t\tkeyAlias \"thekey\"\n\t\t\tkeyPassword KEY_PASSWORD\n\t\t}\n\t\tcatch (ex) {\n\t\t\tthrow new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n\t\t}\n\t}\n}\n```\n\n\n**使用 Maven 依赖方案代替使用导入jar包方案** 如果在你的项目中你明确使用某些\njar文件，那么它们可能成为固定的版本，如`2.1.1`.下载jar包更新他们是很繁琐的，\n这个问题Maven很好的解决了，这在Android Gradle构建中也是推荐的方法。你可\n以指定版本的一个范围，如`2.1.+`,然后Maven会自动升级到制定的最新版本，例如：\n\n```groovy\ndependencies {\n\timplementation 'com.netflix.rxjava:rxjava-core:0.19.+'\n\timplementation 'com.netflix.rxjava:rxjava-android:0.19.+'\n\timplementation 'com.fasterxml.jackson.core:jackson-databind:2.4.+'\n\timplementation 'com.fasterxml.jackson.core:jackson-core:2.4.+'\n\timplementation 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'\n\timplementation 'com.squareup.okhttp:okhttp:2.0.+'\n\timplementation 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'\n}\n```\n\n### IDEs and text editors\n\n### IDE集成开发环境和文本编辑器\n\n\n**无论使用什么编辑器，一定要构建一个良好的工程结构。** 编辑器每个人都有自己的\n选择，让你的编辑器根据工程结构和构建系统运作，那是你自己的责任。\n\n当下首推[Android Studio](https://developer.android.com/sdk/installing/studio.html),因为他是由谷歌开发，很好地支持Gradle，包含很多有用的检测和分析工具，默认使用最新的工程结构，它就是为Android开发定制的。\n\n你也可以使用纯文版编辑器如Vim，Sublime Text，或者Emacs。如果那样的话，你需要使用Gradle和`adb`命令行。\n\n不再推荐使用Eclipse和ADT开发，因为[谷歌在2015年年末结束了对ADT的支持](https://android-developers.googleblog.com/2015/06/an-update-on-eclipse-android-developer.html)，并呼吁开发者尽快迁移到Android Studio。\n\n无论你使用何种开发工具，避免将你的编辑器配置文件（比如Android Studio的iml文件）加入到版本控制，因为这些文件通常包含与本地机器有关的配置，可能会影响你的同事。\n\n最后，善待其他开发者，不要强制改变他们的开发工具和偏好。\n\n### 类库\n\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** 是一个将java对象转换成JSON与JSON转化java类的类库。[Gson](https://code.google.com/p/google-gson/)\n是解决这个问题的流行方案，然而我们发现Jackson更高效,因为它支持替代的方法处理JSON:流、内存树模型,和传统JSON-POJO数据绑定。不过，请记住，\nJsonkson库比起GSON更大，所以根据你的情况选择，你可能选择GSON来避免APP 65k个方法的限制。其它选择: [Json-smart](https://code.google.com/p/json-smart/) and [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)\n\n\n**网络请求，缓存，图片** 执行请求后端服务器，有几种交互的解决方案，你应该考虑实现你自己的网络客户端。使用 [Volley](https://android.googlesource.com/platform/frameworks/volley)\n或[Retrofit](http://square.github.io/retrofit/)。Volley 同时提供图片缓存类。如果你选择使用Retrofit,那么考虑使用[Picasso](http://square.github.io/picasso/)\n来加载图片和缓存，同时使用[OkHttp](http://square.github.io/okhttp/)作为高效的网络请求。Retrofit，Picasso和OkHttp都是同一家公司开发（注：\n是由[Square](https://github.com/square) 公司开发），所以它们能很好的在一起运行。[OkHttp 同样可以和Volley在一起使用 Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n\n**RxJava** 是函数式反应性的一个类库，换句话说，能处理异步的事件。\n这是一个强大的和有前途的模式，同时也可能会造成混淆，因为它是如此的不同。\n我们建议在使用这个库架构整个应用程序之前要谨慎考虑。\n有一些项目是使用RxJava完成的，如果你需要帮助可以跟这些人取得联系：\nTimo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen.\n我们也写了一些博客：\n[[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android),\n[[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754),\n[[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\n\n如若你之前有使用过Rx的经历，开始从API响应应用它。\n另外，从简单的UI事件处理开始运用，如单击事件或在搜索栏输入事件。\n若对你的Rx技术有信心，同时想要将它应用到你的整体架构中，那么请在复杂的部分写好Javadocs文档。\n请记住其他不熟悉RxJava的开发人员，可能会非常难理解整个项目。\n尽你的的全力帮助他们理解你的代码和Rx。\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)** 是一个在Android和预JDK8平台上的使用Lambda表达式语法的Java类库。\n它有助于保持你代码的紧凑性和可读性，特别当你使用如RxJava函数风格编程时。\n使用它时先安装JDK8，在Android Studio工程结构对话框中把它设置成为SDK路径，同时设置`JAVA8_HOME`和`JAVA7_HOME`环境变量，\n然后在工程根目录下配置 build.gradle：\n\n```groovy\ndependencies {\n\tclasspath 'me.tatarka:gradle-retrolambda:2.4.+'\n}\n```\n\n同时在每个module 的build.gradle中添加\n\n```groovy\napply plugin: 'retrolambda'\n\nandroid {\n\tcompileOptions {\n\tsourceCompatibility JavaVersion.VERSION_1_8\n\ttargetCompatibility JavaVersion.VERSION_1_8\n}\n\nretrolambda {\n\tjdk System.getenv(\"JAVA8_HOME\")\n\toldJdk System.getenv(\"JAVA7_HOME\")\n\tjavaVersion JavaVersion.VERSION_1_7\n}\n```\n\nAndroid Studio 提供Java8 lambdas表带是代码提示支持。如果你对lambdas不熟悉，只需参照以下开始学习吧：\n\n- 任何只包含一个接口的方法都是\"lambda friendly\"同时代码可以被折叠成更紧凑的语法\n- 如果对参数或类似有疑问，就写一个普通的匿名内部类，然后让Android Studio 为你生成一个lambda。\n\n**当心dex方法数限制，同时避免使用过多的类库** Android apps，当打包成一个dex文件时，有一个65535个应用方法强硬限制[[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/)。\n当你突破65k限制之后你会看到一个致命错误。因此，使用一个正常范围的类库文件，同时使用[dex-method-counts](https://github.com/mihaip/dex-method-counts)\n工具来决定哪些类库可以再65k限制之下使用，特别的避免使用Guava类库，因为它包含超过13k个方法。\n\n### Activities and Fragments\n\n[Fragments](http://developer.android.com/guide/components/fragments.html)应该作为你实现UI界面默认选择。你可以重复使用Fragments用户接口来\n组合成你的应用。我们强烈推荐使用Fragments而不是activity来呈现UI界面，理由如下：\n\n-  **提供多窗格布局解决方案** Fragments 的引入主要将手机应用延伸到平板电脑，所以在平板电脑上你可能有A、B两个窗格，但是在手机应用上A、B可能分别充满\n  整个屏幕。如果你的应用在最初就使用了fragments，那么以后将你的应用适配到其他不同尺寸屏幕就会非常简单。\n\n- **屏幕间数据通信** 从一个Activity发送复杂数据(例如Java对象)到另外一个Activity，Android的API并没有提供合适的方法。不过使用Fragment，你可以使用\n一个activity实例作为这个activity子fragments的通信通道。即使这样比Activity与Activity间的通信好，你也想考虑使用Event Bus架构，使用如\n[Otto](https://square.github.io/otto/) 或者 [greenrobot EventBus](https://github.com/greenrobot/EventBus)作为更简洁的实现。\n如果你希望避免添加另外一个类库，RxJava同样可以实现一个Event Bus。\n\n\n- **Fragments 一般通用的不只有UI** 你可以有一个没有界面的fragment作为Activity提供后台工作。\n进一步你可以使用这个特性来创建一个[fragment 包含改变其它fragment的逻辑](http://stackoverflow.com/questions/12363790/how-many-activities-vs-fragments/12528434#12528434)\n而不是把这个逻辑放在activity中。\n\n- **甚至ActionBar 都可以使用内部fragment来管理** 你可以选择使用一个没有UI界面的fragment来专门管理ActionBar,或者你可以选择使用在每个Fragment中\n添加它自己的action 来作为父Activity的ActionBar.[参考](http://www.grokkingandroid.com/adding-action-items-from-within-fragments/).\n\n很不幸，我们不建议广泛的使用嵌套的[fragments](https://developer.android.com/about/versions/android-4.2.html#NestedFragments)，因为\n有时会引起[matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/)。我们只有当它有意义(例如，在水平滑动的ViewPager在\n像屏幕一样fragment中)或者他的确是一个明智的选择的时候才广泛的使用fragment。\n\n在一个架构级别，你的APP应该有一个顶级的activity来包含绝大部分业务相关的fragment。你也可能还有一些辅助的activity ，这些辅助的activity与主activity\n通信很简单限制在这两种方法\n[`Intent.setData()`](http://developer.android.com/reference/android/content/Intent.html#setData(android.net.Uri)) 或 [`Intent.setAction()`](http://developer.android.com/reference/android/content/Intent.html#setAction(java.lang.String))或类似的方法。\n\n\n### Java 包结构\n\nAndroid 应用程序在架构上大致是Java中的[Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)结构。\n在Android 中 Fragment和Activity通常上是控制器类(http://www.informit.com/articles/article.aspx?p=2126865).\n换句话说，他们是用户接口的部分，同样也是Views视图的部分。\n\n\n正是因为如此，才很难严格的将fragments (或者 activities) 严格的划分成 控制器controlloers还是视图 views。\n最还是将它们放在自己单独的 `fragments` 包中。只要你遵循之前提到的建议，Activities 则可以放在顶级目录下。\n如果你规划有2到3个以上的activity，那么还是同样新建一个`activities`包吧。\n\n然而，这种架构可以看做是另一种形式的MVC，\n包含要被解析API响应的JSON数据，来填充的POJO的`models`包中。\n和一个`views`包来包含你的自定义视图、通知、导航视图，widgets等等。\n适配器Adapter是在数据和视图之间。然而他们通常需要通过`getView()`方法来导出一些视图，\n所以你可以将`adapters`包放在`views`包里面。\n\n一些控制器角色的类是应用程序级别的，同时是接近系统的。\n这些类放在`managers`包下面。\n一些繁杂的数据处理类，比如说\"DateUtils\",放在`utils`包下面。\n与后端交互负责网络处理类，放在`network`包下面。\n\n\n总而言之，以最接近用户而不是最接近后端去安排他们。\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n\n### 资源文件 Resources\n\n\n- **命名** 遵循前缀表明类型的习惯，形如`type_foo_bar.xml`。例如：`fragment_contact_details.xml`,`view_primary_button.xml`,`activity_main.xml`.\n\n**组织布局文件** 如果你不确定如何排版一个布局文件，遵循一下规则可能会有帮助。\n\n- 每一个属性一行，缩进4个空格\n- `android:id` 总是作为第一个属性\n- `android:layout_****` 属性在上边\n- `style` 属性在底部\n- 关闭标签`/>`单独起一行，有助于调整和添加新的属性\n- 考虑使用[Designtime attributes 设计时布局属性](http://tools.android.com/tips/layout-designtime-attributes)，Android Studio已经提供支持，而不是硬编码`android:text`\n(译者注：墙内也可以参考stormzhang的这篇博客[链接](http://stormzhang.com/devtools/2015/01/11/android-studio-tips1/))。\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n\txmlns:android=\"http://schemas.android.com/apk/res/android\"\n\txmlns:tools=\"http://schemas.android.com/tools\"\n\tandroid:layout_width=\"match_parent\"\n\tandroid:layout_height=\"match_parent\"\n\tandroid:orientation=\"vertical\"\n\t>\n\n\t<TextView\n\t\tandroid:id=\"@+id/name\"\n\t\tandroid:layout_width=\"match_parent\"\n\t\tandroid:layout_height=\"wrap_content\"\n\t\tandroid:layout_alignParentRight=\"true\"\n\t\tandroid:text=\"@string/name\"\n\t\tstyle=\"@style/FancyText\"\n\t\t/>\n\n\t<include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\n作为一个经验法则,`android:layout_****`属性应该在 layout XML 中定义,同时其它属性`android:****` 应放在 styler XML中。此规则也有例外，不过大体工作\n的很好。这个思想整体是保持layout属性(positioning, margin, sizing) 和content属性在布局文件中，同时将所有的外观细节属性（colors, padding, font）放\n在style文件中。\n\n\n例外有以下这些:\n\n- `android:id` 明显应该在layout文件中\n- layout文件中`android:orientation`对于一个`LinearLayout`布局通常更有意义\n- `android:text` 由于是定义内容，应该放在layout文件中\n- 有时候将`android:layout_width` 和 `android:layout_height`属性放到一个style中作为一个通用的风格中更有意义，但是默认情况下这些应该放到layout文件中。\n\n**使用styles** 几乎每个项目都需要适当的使用style文件，因为对于一个视图来说有一个重复的外观是很常见的。\n在应用中对于大多数文本内容，最起码你应该有一个通用的style文件，例如：\n\n```xml\n<style name=\"ContentText\">\n\t<item name=\"android:textSize\">@dimen/font_normal</item>\n\t<item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\n应用到TextView 中:\n\n```xml\n<TextView\n\tandroid:layout_width=\"wrap_content\"\n\tandroid:layout_height=\"wrap_content\"\n\tandroid:text=\"@string/price\"\n\tstyle=\"@style/ContentText\"\n\t/>\n```\n\n\n你或许需要为按钮控件做同样的事情，不要停止在那里。将一组相关的和重复`android:****`的属性放到一个通用的style中。\n\n\n**将一个大的style文件分割成多个文件** 你可以有多个`styles.xml` 文件。Android SDK支持其它文件，`styles`这个文件名称并没有作用，起作用的是在文件\n里xml的`<style>`标签。因此你可以有多个style文件`styles.xml`,`style_home.xml`,`style_item_details.xml`,`styles_forms.xml`。\n不用于资源文件路径需要为系统构建起的有意义，在`res/values`目录下的文件可以任意命名。\n\n\n\n**`colors.xml`是一个调色板** 在你的`colors.xml`文件中应该只是映射颜色的名称一个RGBA值，而没有其它的。不要使用它为不同的按钮来定义RGBA值。\n\n*不要这样做*\n\n```xml\n<resources>\n\t<color name=\"button_foreground\">#FFFFFF</color>\n\t<color name=\"button_background\">#2A91BD</color>\n\t<color name=\"comment_background_inactive\">#5F5F5F</color>\n\t<color name=\"comment_background_active\">#939393</color>\n\t<color name=\"comment_foreground\">#FFFFFF</color>\n\t<color name=\"comment_foreground_important\">#FF9D2F</color>\n\t...\n\t<color name=\"comment_shadow\">#323232</color>\n```\n\n\n使用这种格式，你会非常容易的开始重复定义RGBA值，这使如果需要改变基本色变的很复杂。同时，这些定义是跟一些环境关联起来的，如`button`或者`comment`,\n应该放到一个按钮风格中，而不是在`color.xml`文件中。\n\n\n相反，这样做:\n\n```xml\n<resources>\n\n\t<!-- grayscale -->\n\t<color name=\"white\"     >#FFFFFF</color>\n\t<color name=\"gray_light\">#DBDBDB</color>\n\t<color name=\"gray\"      >#939393</color>\n\t<color name=\"gray_dark\" >#5F5F5F</color>\n\t<color name=\"black\"     >#323232</color>\n\n\t<!-- basic colors -->\n\t<color name=\"green\">#27D34D</color>\n\t<color name=\"blue\">#2A91BD</color>\n\t<color name=\"orange\">#FF9D2F</color>\n\t<color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\n向应用设计者那里要这个调色板，名称不需要跟\"green\", \"blue\", 等等相同。\n\"brand_primary\", \"brand_secondary\", \"brand_negative\" 这样的名字也是完全可以接受的。\n像这样规范的颜色很容易修改或重构，会使应用一共使用了多少种不同的颜色变得非常清晰。\n通常一个具有审美价值的UI来说，减少使用颜色的种类是非常重要的。\n\n\n**像对待colors.xml一样对待dimens.xml文件** 与定义颜色调色板一样，你同时也应该定义一个空隙间隔和字体大小的“调色板”。\n一个好的例子，如下所示：\n\n```xml\n<resources>\n\n\t<!-- font sizes -->\n\t<dimen name=\"font_larger\">22sp</dimen>\n\t<dimen name=\"font_large\">18sp</dimen>\n\t<dimen name=\"font_normal\">15sp</dimen>\n\t<dimen name=\"font_small\">12sp</dimen>\n\n\t<!-- typical spacing between two views -->\n\t<dimen name=\"spacing_huge\">40dp</dimen>\n\t<dimen name=\"spacing_large\">24dp</dimen>\n\t<dimen name=\"spacing_normal\">14dp</dimen>\n\t<dimen name=\"spacing_small\">10dp</dimen>\n\t<dimen name=\"spacing_tiny\">4dp</dimen>\n\n\t<!-- typical sizes of views -->\n\t<dimen name=\"button_height_tall\">60dp</dimen>\n\t<dimen name=\"button_height_normal\">40dp</dimen>\n\t<dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\n布局时在写 margins 和 paddings 时，你应该使用`spacing_****`尺寸格式来布局，而不是像对待String字符串一样直接写值。\n这样写会非常有感觉，会使组织和改变风格或布局是非常容易。\n\n**避免深层次的视图结构** 有时候为了摆放一个视图，你可能尝试添加另一个LinearLayout。你可能使用这种方法解决：\n\n```xml\n<LinearLayout\n\tandroid:layout_width=\"match_parent\"\n\tandroid:layout_height=\"match_parent\"\n\tandroid:orientation=\"vertical\"\n\t>\n\n\t<RelativeLayout\n\t\t...\n\t\t>\n\n\t\t<LinearLayout\n\t\t\t...\n\t\t\t>\n\n\t\t\t<LinearLayout\n\t\t\t\t...\n\t\t\t\t>\n\n\t\t\t\t<LinearLayout\n\t\t\t\t\t...\n\t\t\t\t\t>\n\t\t\t\t</LinearLayout>\n\n\t\t\t</LinearLayout>\n\n\t\t</LinearLayout>\n\n\t</RelativeLayout>\n\n</LinearLayout>\n```\n\n\n即使你没有非常明确的在一个layout布局文件中这样使用，如果你在Java文件中从一个view inflate（这个inflate翻译不过去，大家理解就行） 到其他views当中，也是可能会发生的。\n\n\n可能会导致一系列的问题。你可能会遇到性能问题，因为处理起需要处理一个复杂的UI树结构。\n还可能会导致以下更严重的问题[StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views).\n\n\n因此尽量保持你的视图tree：学习如何使用[RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html),\n如何 [optimize 你的布局](http://developer.android.com/training/improving-layouts/optimizing-layout.html) 和如何使用\n[`<merge>` 标签](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts).\n\n\n**小心关于WebViews的问题.** 如果你必须显示一个web视图，\n比如说对于一个新闻文章，避免做客户端处理HTML的工作，\n最好让后端工程师协助，让他返回一个 \"*纯*\" HTML。\n当绑定WebViews到引用它的Activity,而不是绑定到ApplicationContext时。\n[WebViews 也能导致内存泄露](http://stackoverflow.com/questions/3130654/memory-leak-in-webview)。\n当使用简单的文字或按钮时，避免使用WebView，这时使用TextView或Buttons更好。\n\n### 测试框架\n\n\nAndroid SDK的测试框架还处于初级阶段，特别是关于UI测试方面。Android Gradle\n目前实现了一个叫[`connectedAndroidTest`](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing)的测试，\n它[使用一个JUnit 为Android提供的扩展插件 extension of JUnit with helpers for Android](http://developer.android.com/reference/android/test/package-summary.html).可以跑你生成的JUnit测试，\n\n\n**只当做单元测试时使用 [Robolectric](http://robolectric.org/) ，views 不用**\n它是一个最求提供\"不连接设备的\"为了加速开发的测试，\n非常时候做 models 和 view models 的单元测试。\n然而，使用Robolectric测试时不精确的，也不完全对UI测试。\n当你对有关动画的UI元素、对话框等，测试时会有问题，\n这主要是因为你是在 “在黑暗中工作”（在没有可控的界面情况下测试）\n\n\n**[Robotium](https://code.google.com/p/robotium/) 使写UI测试非常简单。\n** 对于UI测试你不需 Robotium 跑与设备连接的测试。\n但它可能会对你有益，是因为它有许多来帮助类的获得和分析视图，控制屏幕。\n测试用例看起来像这样简单：\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // searches for the first occurence of \"More\" and clicks on it\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n\n### 模拟器\n\n如果你全职开发Android App,那么买一个[Genymotion emulator](http://www.genymotion.com/)license吧。\nGenymotion 模拟器运行更快的秒帧的速度，比起典型的AVD模拟器。他有演示你APP的工具，高质量的模拟网络连接，GPS位置，等等。它同时还有理想的连接测试。\n你若涉及适配使用很多不同的设备，买一个Genymotion 版权是比你买很多真设备便宜多的。\n\n注意：Genymotion模拟器没有装载所有的Google服务，如Google Play Store和Maps。你也可能需\n要测试Samsung指定的API，若这样的话你还是需要购买一个真实的Samsung设备。\n\n\n### 混淆配置\n\n[ProGuard](http://proguard.sourceforge.net/) 是一个在Android项目中广泛使用的压缩和混淆打包的源码的工具。\n\n你是否使用ProGuard取决你项目的配置，当你构建一个release版本的apk时，通常你应该配置gradle文件。\n\n```groovy\nbuildTypes {\n\tdebug {\n\t\tminifyEnabled false\n\t}\n\trelease {\n\t\tsigningConfig signingConfigs.release\n\t\tminifyEnabled true\n\t\tproguardFiles 'proguard-rules.pro'\n\t}\n}\n```\n\n为了决定哪些代码应该被保留，哪些代码应该被混淆，你不得不指定一个或多个实体类在你的代码中。\n这些实体应该是指定的类包含main方法，applets，midlets，activities，等等。\nAndroid framework 使用一个默认的配置文件，可以在`SDK_HOME/tools/proguard/proguard-android.txt`\n目录下找到。自定义的工程指定的 project-specific 混淆规则，如在`my-project/app/proguard-rules.pro`中定义，\n会被添加到默认的配置中。\n\n\n关于 ProGuard 一个普遍的问题，是看应用程序是否崩溃并报`ClassNotFoundException` 或者 `NoSuchFieldException` 或类似的异常，\n即使编译是没有警告并运行成功。\n这意味着以下两种可能：\n\n1. ProGuard 已经移除了类，枚举，方法，成员变量或注解，考虑是否是必要的。\n2. ProGuard 混淆了类，枚举，成员变量的名称，但是这些名字又被拿原始名称使用了，比如通过Java的反射。\n\n检查`app/build/outputs/proguard/release/usage.txt`文件看有问题的对象是否被移除了。\n检查 `app/build/outputs/proguard/release/mapping.txt` 文件看有问题的对象是否被混淆了。\n\nIn order to prevent ProGuard from *stripping away* needed classes or class members, add a `keep` options to your proguard config:\n以防 ProGuard *剥离* 需要的类和类成员，添加一个 `keep`选项在你的 proguard 配置文件中：\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\n防止 ProGuard *混淆* 一些类和成员，添加 `keepnames`:\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\n更多例子请参考[Proguard](http://proguard.sourceforge.net/#manual/examples.html)。\n\n**在构建项目之初，发布一个版本** 来检查ProGuard规则是否正确的保持了重要的部分。\n同时无论何时你添加了新的类库，做一个发布版本，同时apk在设备上跑起来测试一下。\n不要等到你的app要发布 \"1.0\"版本了才做版本发布，那时候你可能会碰到好多意想不到的异常，需要一些时间去修复他们。\n\n**Tips**每次发布新版本都要写 `mapping.txt`。每发布一个版本，如果用户遇到一个bug，同时提交了一个混淆过的堆栈跟踪。\n通过保留`mapping.txt`文件，来确定你可以调试的问题。\n\n**DexGuard** 如果你需要核心工具来优化，和专门混淆的发布代码，考虑使用[DexGuard](http://www.saikoa.com/dexguard),\n一个商业软件，ProGuard 也是有他们团队开发的。\n它会很容易将Dex文件分割，来解决65K个方法限制问题。\n\n###数据存储\n\n**SharedPreferences**\n\n如果你只是需要持久化存储简单的标记位，并且你的应用运行在单一进程，那么SharedPreferences可能就满足了你的需求。它是一个非常好的选择。\n\n这里有两个使你可能不使用SharedPreferences的原因：\n\n- Performance: Your data is complex or there is a lot of it\n- 性能问题：你的很多数据结构负责的数据需要存储。\n- Multiple processes accessing the data: You have widgets or remote services that run in their own processes and require synchronized data\n- 多线程访问数据：你有多个控件或者运行在各自线程上的远程的服务需要同步数据。\n\n**ContentProviders**\n\n如果SharedPreferences不足以满足你的需求，那么你可以使用平台标准的ContentProviders，它不仅快速，并且线程安全。\n\n使用ContentProviders的唯一问题是建立他们需要大量的模板代码，并且少有高质量的教程。如果可以，我们可以通过使用第三方库Schematic，极大降低了冗余操作，去生成ContentProviders.\n\n你可能仍然需要亲自写一些解析代码去从Sqlite读取数据对象，或者进行相反的操作。如果可以序列化数据对象，例如通过Gson，只持久化存储最终是字符串。通过这种方式虽然会降低性能，但是从另一个角度来讲，你不需要为每一个数据结构声明表结构。\n\n**使用ORM**我们通常不推荐使用对象关系映射第三方库除非你有非常复杂的数据结构，并且你确定你真的需要它。他们通常比较复杂，并且需要时间去学习。如果你决定了在你的应用中使用ORM，你应该注意它是否是线程安全的，而对于目前大多数ORM解决方案都是非线程安全的。\n\n**使用Stetho**Stetho 是一个Facebook 开源的Android调试工具，它是Chrome Developer Tools的扩展。通过它可以检测应用的网络情况。它也允许你可以检测应用的数据库，shared preferences。但是，你应该确保Stetho只有在Debug状态下得以开启，而不是在正式发布版本中。\n\n**使用LeakCanary**LeakCanary 是可以在应用运行中检测，定位内存泄露的Java库。使用它应是你开发应用过程中的一部分。更多详细的配置和使用情况请参照wiki。你只需要记得它在你的正式版本中你是不需要配置的。\n\n### 致谢\n\n感谢Antti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton 这些人和Futurice 开发者分享他们的Android开发经验。\n\n### License\n\n[Futurice Oy](www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n\n### Translation\n\nTranslated to Chinese by [andyiac](https://github.com/andyiac)\n"
  },
  {
    "path": "translations/French/README.fr.md",
    "content": "# Les bonnes pratiques du développement Android\n\nLeçons apprises par les developpeurs Android de [Futurice](http://www.futurice.com). Ne réinventez plus la roue en suivant ces bonnes pratiques. Si vous êtes intéressé par le développement iOS ou Windows Phone, n'hésitez pas à regarder nos documents [**Bonnes pratiques iOS**](https://github.com/futurice/ios-good-practices) et [**Bonnes pratiques Windows Phone**](https://github.com/futurice/windows-app-development-best-practices).\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n\n## Sommaire\n\n#### Utiliser Gradle et sa structure de projet recommandée\n#### Mettre les mots de passe et les données sensibles dans le fichier gradle.properties\n#### Ne pas écrire son propre client HTTP, utiliser les bibliothèques Volley ou OkHttp\n#### Utiliser la librairie Jackson pour parser les données au format JSON\n#### Eviter d'utiliser Guava et ne pas trop utiliser de libraries à cause de la *limite des 65k méthodes*\n#### Utiliser des fragments pour représenter une interface graphique\n#### Utiliser les activités uniquement pour gérer les fragments\n#### Les fichiers XMLs sont aussi du code, penser à bien les organiser\n#### Utiliser des styles pour éviter des duplicatas d'attributs dans les fichiers XMLs\n#### Utiliser plusieurs fichiers de style pour éviter d'en avoir un seul trop gros\n#### Garder le fichier colors.xml court et propre, se contenter de définir la palette de couleurs\n#### Garder aussi le fichier dimens.xml concis, définir des constantes génériques\n#### Ne pas imbriquer trop de ViewGroups les uns dans les autres\n#### Eviter le traitement côté client pour les WebViews, et faire attention aux fuites\n#### Utiliser Robolectric pour les tests unitaires, Robotium pour les tests graphiques\n#### Utiliser Genymotion comme émulateur\n#### Toujours utiliser Proguard et DexGuard\n\n\n----------\n\n### Android SDK\n\nMettre le [SDK Android](https://developer.android.com/sdk/installing/index.html?pkg=tools) dans votre répertoire utilisateur (home) ou à un autre endroit indépendant des applications. Certains IDEs inclus le SDK à leur installation, et peuvent le placer dans le même dossier que celui de l'IDE. Cela peut être problématique lorsqu'il faut mettre à jour (ou réinstaller) l'IDE, ou lorsque l'on change d'IDE. De plus éviter de mettre le SDK dans un dossier système qui pourrait nécessiter des permissions administrateurs si votre IDE n'est pas lancé en tant qu'administrateur.\n\n### Système de build\n\nVotre option par défaut devrait être [Gradle](http://tools.android.com/tech-docs/new-build-system). Ant est bien plus limité and aussi plus verbeux. Avec Gradle, il est simple de :\n\n- Builder différentes _flavours_ ou variantes de votre application\n- Ecrire des scripts pour réaliser des tâches.\n- Gérer et télécharger les dépendences\n- Customiser les clés de Store\n- Et plus\n\nDe plus le plugin développé par Google, Android Gradle, a pour but de devenir le nouveau standard de système de build.\n\n### Structure d'un projet\n\nIl a deux options populaires : l'ancienne structure de projet Ant & Eclipse ADT et la nouvelle Gradle & Android Studio. Vous devriez choisir la nouvelle structure de projet. Si votre projet utilise la vieille structure, vous devriez migrer vers la nouvelle.\n\nAncienne structure:\n\n```\nancienne-structure\n├─ assets\n├─ libs\n├─ res\n├─ src\n│  └─ com/futurice/project\n├─ AndroidManifest.xml\n├─ build.gradle\n├─ project.properties\n└─ proguard-rules.pro\n```\n\nNouvelle structure:\n\n```\nnouvelle-structure\n├─ library-foobar\n├─ app\n│  ├─ libs\n│  ├─ src\n│  │  ├─ androidTest\n│  │  │  └─ java\n│  │  │     └─ com/futurice/project\n│  │  └─ main\n│  │     ├─ java\n│  │     │  └─ com/futurice/project\n│  │     ├─ res\n│  │     └─ AndroidManifest.xml\n│  ├─ build.gradle\n│  └─ proguard-rules.pro\n├─ build.gradle\n└─ settings.gradle\n```\n\nLa principale différence est que la nouvelle structure sépare explicitement `source sets` (`main`, `androidTest`), résultant d'un des concepts de Gradle. Vous pourriez par exemple ajouter deux dossiers `payant` `gratuit` dans le dossier `src`qui aura donc le code source de la version payante et de la version gratuite de votre application.\n\nLe fait d'avoir un dossier global `app` permet de distinguer facilement votre application d'autre libraries (ex.: `library-foobar`) qui seraient référencées dans votre application. Le fichier `settings.gradle` garde les références de ces bibliothèques qui pourront ensuite être référencées dans `app/build.gradle`.\n\n### Configuration de Gradle\n\n**Structure générale.** Se référencer à la documentation [Google's guide on Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)\n\n**Petites tâches.** A la place d'écrire des scripts (shell, Python, Perl, etc), faites des tâches dans Gradle. Se référencer à la documation [Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF) pour plus de détails.\n\n**Mots de passe.** Dans le fichier `build.gradle` de votre application, vous aurez besoin de définir `signingConfigs` pour votre Release. Voici ce que vous devez éviter de faire :\n\n_Ne faites pas ça_. Ceci apparaitrait dans le système de contrôle de version (Git par exemple).\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nA la place, faites un fichier `gradle.properties` qui ne devrait _pas_ apparaître dans le système de contrôle de version.\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nCe fichier est automatiquement importer par gradle, donc vous pouvez l'utiliser dans `build.gradle` comme ceci:\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**Préférez la résolution de dépendences Maven plutôt que l'importation de fichiers .jar.** Si vous importez explicitement des fichiers .jars dans votre projet, ceux-ci seront fixés dans une version, par exemple `2.1.1`. Télécharger et s'occuper des mises à jour est un tâche lourde et rébarbative à effectuer, Maven résoud ce problème d'une facçon élégante. Par exemple:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp:2.2.0'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'\n}\n```\n\n**Eviter les résolutions dynamiques de dépendence Maven**\nEvitez l'utilisation de versions dynamiques des bibliothèques comme `2.1.+` car cela pourrait mener à des builds de votre application instables ou à des différénces subtiles du comportement de votre application entre vos différents builds. L'utilisation de versions statiques des bibliothèques comme `2.1.1` permet de créer des environnements de développement plus stables et prédictibles.\n\n### IDEs et éditeurs de texte/code\n\n**Vous pouvez utiliser n'importe quel éditeur de code, il doit juste pouvoir respecter la structure du projet.** Utiliser tel ou tel éditeur de texte/code est un choix personnel, et il en va de votre responsabilité de choisir un étideur compatible avec la structure de projet et le système de build.\n\nL'IDE le plus recommendé en ce moment est : [Android Studio](https://developer.android.com/sdk/installing/studio.html), car il est développé par Google, a bien intégré Gradle, et utilise la nouvelle structure de projet par défaut. De plus il est enfin en version stable et est conçu exprès pour le développement Android.\n\nVous pouvez utiliser [Eclipse ADT](https://developer.android.com/sdk/installing/index.html?pkg=adt) si vous le souhaitez, mais vous devrez le configurer car de base il utilise l'ancienne structure de projet et Ant pour builder votre application. Dans ce cas vous devrez utiliser Gradle et `adb` en ligne de commande. Si l'intégration de Gradle dans Eclipse ne marche pas chez vous, vos options sont d'utiliser les lignes de commande juste pour builder ou bien de migrer vers Android Studio. Cette dernière est la meilleure car le plugin ADT est devenu déprécié récemment.\n\nPeu importe ce que vous utilisez, veuillez vous assurer que vous avez la nouvelle structure de projet, que vous utilisez Gradle et que vous n'introduisez pas de fichiers de configuation spécifique à votre éditeur de code dans le système de contrôle de version. Par exemple évitez d'ajouter un fichier de configuration Ant `build.xml`. Notamment n'oubliez pas de mettre à jour `build.gradle` si vous changez de configuration Ant. Enfin soyez sympas avec les autres développeurs et ne les forcez pas à changer leurs outils de développement ou leurs préférences.\n\n### Bibliothèques\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** est une librairie capable de convertir les Objets en JSON et vice-versa. [Gson](https://code.google.com/p/google-gson/) est une librairie similaire et aussi populaire cependant nous trouvons que Jackson est plus performante car elle supporte différentes façons de traiter le JSON : en streaming, avec une structure d'arbre et le mapping traditionnel JSON-POJO. Garder en tête toutefois que Jackson est une librairie plus conséquente que GSON donc selon votre cas vous serez peut-être amené à choisir GSON pour éviter la limitation des 65k méthodes. Autres alternatives : [Json-smart](https://code.google.com/p/json-smart/) et [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)\n\n**Réseaux, cache et images.** Il existe plusieurs solutions pour faire des requètes sur un backend. Vous pouvez utiliser [Volley](https://android.googlesource.com/platform/frameworks/volley) ou [Retrofit](http://square.github.io/retrofit/). Volley apporte aussi des helpers permettant de charger et mettre en cache des images. Si vous choisissez Retrofit, nous vous conseillons d'utiliser [Picasso](http://square.github.io/picasso/) pour charger et mettre en cache les images et [OkHttp](http://square.github.io/okhttp/) pour faire des requètes HTTP performantes. Les trois bibliothèques Retrofit, Picasso et OkHttp ont été créees par la même entreprise donc elles se complètent plutôt bien. [OkHttp can also be used in connection with Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n\n**RxJava** est une librairie pour faire de la programmation réactive, en d'autres termes, elle permet de gérer des évènements asynchrones. C'est un paradigme puissant et prometteur bien qu'il puisse être déroutant du fait de ses différences. Nous vous recommandons de faire très attention avant d'utiliser cette librairie pour réaliser l'architecture de votre application. Parmi nous projets, certains ont été réalisés avec RxJava. Si vous avez besoin d'aide adressez vous à l'une de ces personnes : Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. Nous avons écris des articles dessus : [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\nSi vous n'avez aucune expérience antérieure avec Rx, commencez par mettre en oeuvre cette librairie uniquement sur les réponses des API. Une autre alternative serait de l'utiliser pour les évènements simples liés à l'interface graphique comme les clics ou l'ajout de caractères dans un champ de recherche. Si vous êtes confiants à propos de vos compétences en Rx et que vous souhaitez l'appliquer à l'architecture de votre projet, n'oubliez pas d'écrire des Javadocs au niveau de toutes les parties difficiles. Gardez en tête qu'un autre développeur qui ne connait pas RxJava aura probablement beaucoup de mal à maintenir votre projet. Faites de votre mieux pour les aider à comprendre votre code et Rx.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)** est une librairie Java faite pour utiliser la syntaxe Lambda avec Android et d'autre plateformes antérieures au JDK8. Elle vous permet de garder votre code concis et lisible surtout si vous utilisez un style de programmation fonctionnel avec par exemple RxJava. Pour l'utiliser, installez le JDK8, le mettre en tant que SDK par défaut dans votre projet Android Studio et ajoutez les variables d'environnement `JAVA8_HOME` et `JAVA7_HOME`. Enfin ajout à votre build.gradle :\n\n```groovy\ndependencies {\n    classpath 'me.tatarka:gradle-retrolambda:2.4.1'\n}\n```\n\net dans chacun de vos fichiers build.gradle ajoutez :\n\n```groovy\napply plugin: 'retrolambda'\n\nandroid {\n    compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n}\n\nretrolambda {\n    jdk System.getenv(\"JAVA8_HOME\")\n    oldJdk System.getenv(\"JAVA7_HOME\")\n    javaVersion JavaVersion.VERSION_1_7\n}\n```\n\nAndroid Studio propose un support pour l'utilisation de lambdas Java8. Si vous débutez avec les lambdas, suivez ces conseils pour démarrer :\n\n- Toute interface qui comporte uniquement une méthode est compatible lambda et peut être réduite dans la syntaxe la plus compacte.\n- Si vous avez des doutes concernant les paramètres ou autre, écrivez une classe interne normale et laissez Android Studio la compacter en un lambda pour vous.\n\n**Faites attention à la limiation des méthodes dex et évitez d'utiliser beaucoup de bibliothèques.** Lorsque les applications Android sont packagées en un fichier Dex, elles ont une limitation de 65536 méthodes référencées [[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). Vous verrez une erreur fatale si jamais vous dépassez cette limite. Pour cette raison utilisez un minimum de bibliothèques et utilisez l'outil [dex-method-counts](https://github.com/mihaip/dex-method-counts) pour déterminer quelles bibliothèques peuvent être utilisées pour rester en dessous de cette limite. Evitez d'utiliser la librairie Guava car elle contient plus de 13k méthodes.\n\n### Les activités et les fragments\n\nIl n'y a pas d'accord global sur la meilleure façon d'oganiser une architecture Android avec des activités et des fragments ni au sein de la communauté Android ni au sein des développeurs Futurice. Square a même [une librairie pour contruire une architecture à partir de Views principalement](https://github.com/square/mortar), ce qui supprime le besoin d'utiliser des fragments. Cela n'est cependant pas considéré comme une pratique largement recommandable par la communauté Android.\n\nDe part l'histoire de l'API Android, vous pouvez considérer les Fragments comme des petites parties graphiques de l'écran. En d'autres termes, les Fragments sont en temps normal liés à l'interface graphique. Les Activities peuvent être considérées comme des controlleurs, elles sont particulièrement importante grâce à leurs cycles de vie et pour gérer les changements d'états. Vous allez cependant pouvoir constater certaines variations dans ces rôles : les activités peuvent être liées à l'interface graphique ([delivering transitions between screens](https://developer.android.com/about/versions/lollipop.html)), et [les fragments peuvent prendre le rôle d'un controlleur](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). Nous vous suggérons d'agir consciencieusement de vous informer avant de prendre des décisions car il y a des avantages et des inconvénients à chaque méthode. Voici quelques conseils à prendre avec des pincettes sur lesquels il faut rester vigilant :\n\n- Evitez de [mettre trop de fragments les uns dans les autres](https://developer.android.com/about/versions/android-4.2.html#NestedFragments) à cause du [bug matryoshka](http://delyan.me/android-s-matryoshka-problem/). Utilisez donc des fragments à l'intérieur d'autres lorsque cela a du sens (par exemple des fragments dans un ViewPager horizontal) ou lorsque vous savez ce que vous faites.\n- Evitez de mettre trop de code dans les activités. Lorsque cela est possible, laissez les aussi légers que possible en tant que conteneurs et utilisez les majoritairement pour gérer les cycles de vie ou d'autres évènement importants liés à l'API android. Préférez utiliser des fragments seuls plutôt que des activités seules - mettez le code lié à l'interface graphique dans l'activité du fragment. Cela vous permet de le rendre réutilisable dans le cas ou vous souhaiteriez le mettre dans une interface avec des onglets par exemple ou dans une interface contenant plusieurs fragments sur une tablette. Evitez d'avoir des activités sans un fragment qui leur correspond sauf si vous savez ce que vous faites.\n- N'abusez pas sur l'utilisation des API android comme les Intent pour le fonctionement interne de votre application. Cela pourrait avoir de facheuses conséquences comme des bugs ou des lags. Par exemple, il a été prouvé que l'utilisation des Intent pour communiquer entre les packages de votre application peut créer des lags de plusieurs secondes si votre application a été ouverte juste après le démarrage du téléphone.\n\n### L'architecture des packages java\n\nL'architecture java des applications android peut être vue approximativement comme du [Model-Vue-Controlleur](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). Avec Android, [les fragments et les activités sont des controlleurs](http://www.informit.com/articles/article.aspx?p=2126865). D'un autre côté, ils sont une partie intégrante de l'interface utilisateur, ceux sont donc aussi des vues.\n\nC'est pour cette raison qu'il est dur de classifier les fragments (ou les activités) comme uniquement des controlleurs ou des vues. Il est préférable de les laisser dans leur package `fragments`. Les activités peuvent rester dans le package de plus au niveau tant que vous suivez les conseils de la section précédente. Si vous comptez utiliser plus de 2 ou 3 activités, faites un package `activities`.\n\nAutrement, l'architecture ressemble à celle d'un MVC typique avec un package `models` contenant les objects POJOs à être remplis à partir des réponses des API et à l'aide d'un parser JSON. Mettre aussi un package `views` contenant toutes vos vues customisées, les notifications, les bar d'actions, les widgets, etc. Les Adapters sont une autre paire de manche, car ils se situent entre les data et les vues. Cependant ils ont besoin d'exporter une vue via la méthode `getView()` donc vous pouvez inclure les Adapters dans un sous package `adapters` dans le package `views`.\n\nCertains controlleurs ont une porté au niveau de l'application et sont proche du système Android. Ceux-ci peuvent être placés dans le package `managers`. D'autres classes diverses manipulant des données comme \"DateUtils\" peuvent être placées dans le package `utils`. Les classes qui s'occupent d'interagir avec le backend restent dans le package `network`.\n\nPour résumer, ordonés du plus proche du back au plus proche de l'utilisateur :\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n### Ressources\n\n**Règles de nommage.** Suivez les conventions en préfixant vos noms du type comme `type_foo_bar.xml`. Exemples: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**Organisation des fichiers XMLs.** Si vous n'êtes pas sûr(e) de l'organisation de vos fichiers XMLs, les conventions suivantes pourraient vous aider :\n\n- Un attribut par ligne, indenté d'espaces\n- `android:id` toujours en tant que premier attribut\n- les `android:layout_****` toujours en haut après `android:id`\n- l'attribut `style` tout en bas\n- le tag `/>` de fermeture doit être sur sa propre ligne pour faciliter l'ajout d'attributs et l'ordonnancement.\n- plutôt que de hardcoder l'attribut `android:text`, pensez à utiliser les [attributs Designtime](http://tools.android.com/tips/layout-designtime-attributes) disponibles dans Android Studio.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\nEn règle générale, les attributs `android:layout_****` doivent être placés dans les fichiers layouts XML et les autres attributs `android:****` dans les fichiers de style XML. Cette règle a des exceptions mais s'applique bien la plupart du temps. L'idée est de garder uniquement les attributs de contenu et de layout (positionnement, marges, tailles) dans les fichiers de layout XML et de mettre tous les autres liés aux détails de l'apparence (couleurs, padding, police) dans des fichiers de style.\n\nLes exceptions sont :\n\n- `android:id` doit évidement se trouver dans les fichiers layout XML\n- l'attribut `android:orientation` pour un `LinearLayout` a normalement plus de sens dans les fichiers layout XML\n- l'attribut `android:text` devrait être dans les fichiers layout XML car il définit du contenu\n- De temps en temps il est judicieux de mettre un style générique pour définir `android:layout_width` et `android:layout_height` mais par défaut ils devraient apparaitre dans les fichiers de layout XML.\n\n**Utilisez des styles.** Quasiment tous les projets ont besoin d'utiliser correctement des styles, car il est très commun d'avoir des vues dont l'apparence est similaire. Vous devriez au moins avoir un style commun pour la plupart des contenu textuels dans votre application, par exemple :\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nAppliqué aux TextViews:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\nVous aurez probablement besoin de faire la même chose pour les boutons, mais ne vous arretez pas là. Allez plus loin et mettez les groupes d'attributs qui se répètent dans un style commun.\n\n**Séparez les fichiers de style très gros en plusieurs petits fichiers de style.** Vous n'êtes pas contraints d'avoir qu'un seul fichier `styles.xml`. Le SDK Android supporte plusieurs fichiers de style, il n'y a rien de magique avec le nom `styles`, ce qui importe ce sont les tags XML `<style>` à l'intérieur du fichier. Donc vous pouvez très bien avoir les fichiers `styles.xml`, `styles_home.xml`, `styles_item_details.xml`, `styles_forms.xml`. A l'opposé des fichiers dans le dossier de ressources qui doivent être nommés précisément pour que le système de build Android puisse les comprendre, les noms de fichier dans `res/values` sont arbitraires.\n\n**`colors.xml` est une palette de couleurs.** Il ne devrait avoir rien d'autre à part des correspondances entre un nom de couleur et une valeur RGBA dans le fichier `colors.xml`. N'utilisez pas ce fichier pour définir différents types de boutons.\n\n*Ne faites pas ça:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\nAvec ce format il est facile de devoir se répéter et il est difficile de changer une couleur de base si besoin. De plus ces définitions sont liés à un contexte, comme \"button\" ou \"comment\" et devrait être placés dans un style de bouton et non dans le fichier `colors.xml`.\n\nA la place, faites ceci:\n\n```xml\n<resources>\n\n    <!-- grayscale -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- basic colors -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\nDemandez cette palette de couleur à votre designer. Les noms n'ont pas besoin d'être des noms de couleur comme \"vert\", \"bleu\", etc. Les noms comme \"brand_primary\", \"brand_secondary\", \"brand_negative\" sont tout à fait acceptables. Le fait d'arranger les couleurs comme ceci vous permettra de les changer facilement et permettra de voir explicitement le nombre de couleurs différentes utilisées dans votre application. Normalement pour une interface graphique agréable à regarder, il faut minimiser le nombre de couleurs différentes utilisées.\n\n**Traitez dimens.xml comme colors.xml.** Vous devriez aussi définir une \"palette\" de dimensions, d'espacements et de tailles de police typiques à votre application. Un bon exemple de fichier dimens.xml est :\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\nVous devriez utiliser les dimensions `spacing_****` pour le layout, les marges et les padding au lieu d'harcoder les valeurs. Il s'agit de traiter les dimensions comme les strings. Cela donnera à votre application de la consistence au niveau de l'apparence tout en facilitant l'organisation des styles et des layouts.\n\n**strings.xml**\n\nNommez vos strings avec des clés qui ressemblent aux espaces de noms et n'ayez pas peur de répéter les valeurs pour deux ou plusieurs clés car les espaces de noms sont nécessaire pour apporter un contexte et enlever toute ambiguité.\n\n**Pas bien**\n```xml\n<string name=\"network_error\">Erreur de réseau</string>\n<string name=\"call_failed\">L'appel a échoué</string>\n<string name=\"map_failed\">Le chargement de la carte a échoué</string>\n```\n\n**Bien**\n```xml\n<string name=\"error.message.network\">Erreur de réseau</string>\n<string name=\"error.message.call\">L'appel a échoué</string>\n<string name=\"error.message.map\">Le chargement de la carte a échoué</string>\n```\n\nN'écrivez pas les strings en majuscules. Basez vous sur les conventions des textes (ex.: en mettant une majuscule à la première lettre). Si vous avez besoin d'afficher le texte tout en majuscules, faites le en utilisant l'attribut [`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) dans une TextView.\n\n**Pas bien**\n```xml\n<string name=\"error.message.call\">L'APPEL A ECHOUE</string>\n```\n\n**Bien**\n```xml\n<string name=\"error.message.call\">L'appel a échoué</string>\n```\n\n**Evitez d'avoir une hiérarchie trop profonde de vues.** De temps à autres vous serez tenté d'ajouter simplement un autre LinearLayout pour accomplir l'arrangement des vues que vous souahité. Ce genre de situation peut arriver :\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nMême si vous ne voyez pas explicitement ceci dans un fichier de layout, cela arrivera peut être lorsque vous ajouterez des vues (en Java) dans d'autres vues.\n\nPlusieurs problèmes pourront alors survenir. Vous pourrez par exemple rencontrer des problèmes de performances parce que le processeur doit gérer une arborescence de vues complexe. Une autre erreur aux conséquences grave serait : [StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views).\n\nEssayez donc de garder vos vues aussi plates que possible: apprenez à utiliser le [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html), comment [optimize your layouts](http://developer.android.com/training/improving-layouts/optimizing-layout.html) et comment utiliser [`<merge>` tag](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts).\n\n**Faites attention aux problèmes liés aux WebViews.** Lorsque vous devez afficher une page web, par exemple pour un article de presse, évitez de faire des manipulations sur la page du coté client, demandez plutôt aux développeurs backend de vous fournir une version \"*pure*\" de leur page HTML. [Les WebViews peuvent aussi provoquer des fuites de mémoire](http://stackoverflow.com/questions/3130654/memory-leak-in-webview) lorsqu'elles gardent en référence leur activité à la place d'être référencées à l'ApplicationContext. Evitez d'utiliser les WebViews pour afficher des simple textes ou des boutons, préferez des TextViews ou des Buttons.\n\n### Emulateurs\n\nSi votre métier est de développer des applications Android, achetez une license de [l'émulateur Genymotion](http://www.genymotion.com/). Les émulateurs Genymotion ont un taux de rafraichissement plus rapide que les machines virtuelles AVD. Ils ont aussi des outils qui permettent de faire des démos de votre application, de simuler tel ou tel type de connection internet, de simuler des positions GPS, etc. Ils sont aussi idéals pour faire des tests connectés. Vous aurez accès à beaucoup de différents périphériques (pas tous mais beaucoup) donc le coup d'achat d'une license de Genymotion revient moins cher qu'acheter le nombre équivalent de périphériques.\n\nLes inconvénients sont : les émulateurs Genymotion ne contiennent pas tous les services Google comme Google Play Store ou Maps. Vous aurez aussi probablement besoin de tester des APIs spécifiques aux téléphones samsung donc vous aurez besoin d'acheter un vrai téléphone pour ça.\n\n### Configuration Proguard\n\n[ProGuard](http://proguard.sourceforge.net/) est utiliser en temps normal pour diminuer la taille des applications Android et pour obfuscer le code packagé.\n\n<!-- Le fait d'utiliser ou nom Proguard dépend de la configuration de votre projet. Normalement on configure gradle pour utiliser Proguard lorsqu'on build la version release de l'apk. -->\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\n\nPour déterminer quels bouts de code doivent être gardés tel quel et lesquels doivent ête supprimés ou obfusqués, vous devez spécifier un ou plusieurs points d'entrée dans votre code.\n\nLa configuration par défaut du framework Android se trouve ici : `SDK_HOME/tools/proguard/proguard-android.txt`. Les règles spécifiques à chaque projet seront ajoutées automatiquement à la configuration par défaut à partir du fichier `my-project/app/proguard-rules.pro`.\n\nUn problème récurrent lié à l'utilisation de Proguard est le crash de l'application à son démarrage avec `ClassNotFoundException` ou `NoSuchFieldException` ou autre erreur similaire même si la commande de build a réussi (i.e.: `assembleRelease`) sans avertissements.\nCela peut dire deux choses :\n\n1. ProGuard a supprimé la class, l'enum, la méthode, le champ ou l'annotation en pensant qu'il/qu'elle n'était pas nécessaire.\n2. ProGuard a obfusqué (renommé) la classe, l'enum ou le champ alors qu'il/qu'elle est utilisé indirectement avec son nom d'origine, i.e. à travers la réflexion Java.\n\nVérifiez `app/build/outputs/proguard/release/usage.txt` pour voir si l'objet en question a été supprimé.\nVérifiez `app/build/outputs/proguard/release/mapping.txt` pour voir si l'objet en question a été obfusqué (renommé).\n\nAfin d'empêcher ProGuard de *supprimer* les classes qui sont nécessaires ou les champs qui sont nécessaires au bon fonctionement de l'application, ajoutez l'option `keep` à votre configuration ProGuard :\n\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nPour empêcher ProGuard *d'obfusquer* les classes ou les champs des calsses, ajoutez l'option `keepnames`:\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\nLisez [Proguard](http://proguard.sourceforge.net/#manual/examples.html) pour obtenir plus d'exemples.\n\n**Faites un build de la release tôt dans le développement de votre application** pour vérifier si ProGuard garde correctement ce qui est important. De plus dès que vous ajoutez une nouvelle librairie dans votre projet, faites une build de la release et testez l'apk sur votre périphérique. N'attendez pas que votre application soit finalisée en version \"1.0\" pour faire ce build de la release car vous risquez de tomber sur de mauvaises surprises et d'avoir peu de temps pour les corriger.\n\n**Conseil.** Sauvegardez le fichier `mapping.txt` pour chaque release que vous publiez aux utilisateurs. En gardant une copie de ce fichier pour chaque build de release, vous vous assurez de pouvoir débugguer le problème si un utilisateur rencontre un bug et vous envoie le rapport avec le code obfusqué.\n\n**DexGuard**. Si vous avez besoin d'outils surpuissants pour optimiser votre application et surtout pour obfusquer votre code, utilisez [DexGuard](http://www.saikoa.com/dexguard), un logiciel commercial fait par la même équipe que ProGuard. Ce logiciel est aussi capable de couper les fichiers Dex en plusieurs fichiers afin de contourner la limite des 65k méthodes.\n\n### Remerciements\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton et les autres développeurs à Futurice pour le partage de leur connaissances sur le développement Android.\n\n### License\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n"
  },
  {
    "path": "translations/Japanese/README.ja.md",
    "content": "# Androidの開発におけるベストプラクティス\n\n以下は[Futurice](http://www.futurice.com)で働くAndroidアプリ開発者が学んだ教訓である. これらをしっかり読んで車輪の再開発はやめよう. もしiOSやWindows Phoneの開発に興味があるなら,[**iOS Good Practices**](https://github.com/futurice/ios-good-practices)と[**Windows client Good Practices**](https://github.com/futurice/win-client-dev-good-practices)を必ず確認しよう。\n\nフィードバックは歓迎しているが、まずは[ガイドライン](https://github.com/futurice/android-best-practices/tree/master/CONTRIBUTING.md)を読んでほしい.\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n\n## Summary\n\n#### Gradleで推奨されるプロジェクト構成で開発しよう\n#### パスワードや注意を要するデータはgradle.propertiesに書こう\n#### 自分でHTTP Clientは作らず、VolleyやOkHttpを使おう\n#### JSONをパースするならJacksonを使おう\n#### メソッド数に65kの制限があるので、Guavaは避けて、かつライブラリは最小限に抑えよう\n#### UIの描画はFragmentを使おう\n#### ActivityはFragmentをただ管理するために使おう\n#### Layout xmlをうまく整理しよう\n#### Layout xmlの属性が重複するのを避けるためStyleを使おう\n#### 大きなStyleを定義するよりも複数のStyleを定義しよう\n#### colors.xmlは短くDRY（「Don't Repeat Yourself」意味が重複しないよう）にして、パレットで定義しよう\n#### dimens.xmlもDRYにして、一般の定数を定義しよう\n#### ViewGroupのネストは深くせずに浅くしよう\n#### WebViewはメモリリークするため、クライアント側での処理は避けよう\n#### ユニットテストにはRobolectricを、結合テストにはRobotiumを使おう\n#### emulatorはGenymotionで決まり\n#### 必ずProGuardもしくはDexGuardを使おう\n\n\n----------\n\n### Android SDK\n\n[Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools)はホームディレクトリか他のアプリから独立した場所に置こう。いくつかのIDEはSDKを含んでいて、インストール時にSDKをIDEと同じディレクトリに置く事がある。このままではIDEをアップグレードや再インストールする場合、またIDEを変更する場合に面倒になる。\nまた、IDEがrootでないアカウントで動いている場合に、sudoが必要な他のシステムレベルのディレクトリにSDKを置く事も避けよう。\n\n### Build system\n\nデフォルトオプションに[Gradle](http://tools.android.com/tech-docs/new-build-system)を使おう。Antは制限が多く、コストが大きい。しかし、Gradleなら下記のことがシンプルに可能だ。\n\n- あなたのアプリの異なるFlavorやVariantをビルドできる\n- スクリプトのようにタスクを作る事ができる\n- 依存関係を管理しつつダウンロードできる\n- keystoreをカスタマイズできる\n- その他諸々\n\nそして、Googleは、AndroidのGradleプラグインを標準のビルドシステムとして盛んに開発している。\n\n### プロジェクト構成\n\nプロジェクト構成については、これまでのAnt & Eclipse ADTのプロジェクト構成と 新しいGradle & Android Studioのプロジェク構成の二つが有名であるが、後者の新しいプロジェクト構成を選ぶべきだ。もし前者の古いプロジェクト構成をつかっているなら、それは遺産だと考えて、新しいプロジェクト構成に変える事を考えた方がいい。\n\n古い構成:\n\n```\nold-structure\n├─ assets\n├─ libs\n├─ res\n├─ src\n│  └─ com/futurice/project\n├─ AndroidManifest.xml\n├─ build.gradle\n├─ project.properties\n└─ proguard-rules.pro\n```\n\n新しい構成:\n\n```\nnew-structure\n├─ library-foobar\n├─ app\n│  ├─ libs\n│  ├─ src\n│  │  ├─ androidTest\n│  │  │  └─ java\n│  │  │     └─ com/futurice/project\n│  │  └─ main\n│  │     ├─ java\n│  │     │  └─ com/futurice/project\n│  │     ├─ res\n│  │     └─ AndroidManifest.xml\n│  ├─ build.gradle\n│  └─ proguard-rules.pro\n├─ build.gradle\n└─ settings.gradle\n```\n\n一番の違いは新しいプロジェクト構成では'Source sets'(main, androidTest)が明確に分けられている事だ。これはGradleのコンセプトでもある。\nこれによって例えば`paid`と`free`というSource setを`src`の中に追加すると、'paid'と'free'というFlavorができる。\n\nさらに`app`がtop-levelにあると、アプリで参照される`library-foobar`などの他のライブラリプロジェクトを区別するのに役立つ。`setting.gradle`が各ライブラリへの参照をもち、`app/build.gradle`から参照する事ができる。\n\n### Gradleの設定\n\n**一般的な構成** \n[Google's guide on Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)を参照の事。\n\n**小さなタスク** \nshell, Python, Perlなどのスクリプトの代わりに、Gradleの中にタスクをつくることができる。詳細は[Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF)を参照の事。\n\n**パスワード** \nリリースビルドのために`build.gradle`の中で`signingConfigs`を定義しなければならないときがある。\n\n下記はダメなケース。これではバージョン管理システムで管理されてしまう。\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nその代わりに、`gradle.properties`に下記のように書いて、このファイルをバージョン管理の管理外としよう。\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nこのファイルはgradleによって自動でimportされるので、このときの`build.gradle`は下記のように書くとよい。\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**jarファイルを直接importするよりMavenを使う方が良い** \njarファイルをプロジェクトに直接includeしている場合、version`2.1.1`のようにversionが固定されてしまう。さらに、jarファイルをダウンロードして、手動でアップデートするはめになり効率が悪い。Mavenならこれを解決できるし、Android StudioもMevenの使用をすすめている。`2.1.+`というようにversionの範囲を指定することもでき、指定した範囲の中での最新にアップデートしてくれる。\nたとえば下記のように書く。\n\n```groovy\ndependencies {\n    implementation 'com.netflix.rxjava:rxjava-core:0.19.+'\n    implementation 'com.netflix.rxjava:rxjava-android:0.19.+'\n    implementation 'com.fasterxml.jackson.core:jackson-databind:2.4.+'\n    implementation 'com.fasterxml.jackson.core:jackson-core:2.4.+'\n    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'\n    implementation 'com.squareup.okhttp:okhttp:2.0.+'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'\n}\n```\n\n### IDEとテキストエディタ\n\n**エディターは何を使っても良いが、例のプロジェクト構成のまま扱えるものが良い** \nエディターはプロジェクト構成、ビルドシステムにあったものを選べば良い。\n\n一番推奨されるIDEは[Android Studio](https://developer.android.com/sdk/installing/studio.html)である。Google が開発しており、Gradleと親和性が高いうえ、プロジェクト構成もデフォルトで推奨されているものを採用しているからだ。\n\nもしお望みなら[Eclipse ADT](https://developer.android.com/sdk/installing/index.html?pkg=adt)をつかってもいいが、デフォルトで古いプロジェクト構成でかつAntを採用しているので設定が必要である。EclipseのGradleプラグインが動かない場合はコマンドラインでやるか、Android Studioに移行するかしかない。\nまたVim、Sublime TextやEmacsといった純粋なテキストエディタを使用することさえできる。その場合は、コマンドラインからGradleとadbを使えるよう準備する必要がある。\n\n何を使っても良いが、Gradleを使う事と新しいプロジェクト構成で開発する事がオフィシャルな方法である事を頭に入れておかねばならない。またAntの`build.xml`などのエディタ特有の設定ファイルなどはバージョン管理外とすることもお忘れなく。特に、Antのビルド設定を変更した際は`build.gradle`が最新であり機能する事を確認することを怠ってはならない。また他の開発者が使っているツールの設定を強要することがないようにしよう。\n\n### Libraries\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** はObjectをJSONに変換、またその逆を行うライブラリである。[GSON](https://code.google.com/p/google-gson/)もJsonのライブラリとして有名だが、streaming、in-memory tree model, Json data binding等をサポートしている点でJacksonの方がいくらか優れていると判断した。ただ覚えておいてほしいのはJacksonがGsonよりボリュームの大きなライブラリである事だ。65k制限を避ける為にGSONの方が有効なケースもあり得る。また他には[json-smart](https://code.google.com/p/json-smart/)、[Boon JSON](https://github.com/boonproject/boon/wiki/Boon-JSON-in-five-minutes)という選択肢もある。\n\n**ネットワーク、キャッシュ、画像処理について。**バックエンドへのリクエスト処理の実装についていろいろ試した結果言えるのは、自分でクライアントを実装しない方がいいということだ。[Volley](https://android.googlesource.com/platform/frameworks/volley)や[Retrofit](http://square.github.io/retrofit/)を使おう。Volleyはまた画像のロード、キャッシュのヘルパーを提供してくれている。Retrofitを選ぶ人は、[Picasso](http://square.github.io/picasso/)という画像ライブラリ、またHttpリクエストに有効な[OkHttp](http://square.github.io/okhttp/)の導入も考えると良い。この三つのRetrofit、Picasso、OkHttpは一つの会社で作られている。そのため、これらのライブラリは互いをよく補っている。現に[OkHttpはVolleyと共に使われることがよくある。](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835)\n\n**RxJava**はリアクティブプログラミングを行う、つまり非同期イベントを扱う為のライブラリだ。これは強力で有望なものだが、通常のプログラミングと異なりすぎる為に困惑をもたらす事がある。私たちはこのライブラリをアプリ全体のアーキテクチャに使う前に注意して扱うことをお勧めする。RxJavaを用いて作った我々のプロジェクトがいくつかあった。もし助力が必要なら次のメンバに話してみると良いかもしれない: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen\nまたいくつかブログの記事も書いている。[\\[1\\]](http://futurice.com/blog/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android) [\\[2\\]](http://futurice.com/blog/top-7-tips-for-rxjava-on-android) [\\[3\\]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) [\\[4\\]](http://futurice.com/blog/android-development-has-its-own-swift)\n\nもしRxを使った経験が以前にないのなら、まずはAPIのレスポンスのみ、もしくはクリックイベントや検索フィールドのテキスト変更イベントなどのUIのイベントハンドリングのみに適用するところから始めると良い。\n逆にRxに自信があってプロジェクト全体で使いたい場合は、トリッキーな場所にJavadocを書くと良い。RxJavaのようなよく知られていない他のプログラミング手法を使用する場合はメンテナンスが大変であることを忘れてはいけない。あなたのRxで書かれたコードが他の人も理解できるようにベストを尽くそう。\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)**はAndroidやJDK8以前のプラットフォームでlambda記法を使う事ができるようになるライブラリである。特にRxJavaなど関数型スタイルを採用する場合において、これはコードを短く、見やすくする。\nJDK8をインストールして、SDKのときと同じようにAndroid Studioに設定する必要がある。\n`JAVA8_HOME`と`JAVA7_HOME`を設定後、ルートのbuild.gradleを下記のように書き\n\n```groovy\ndependencies {\n    classpath 'me.tatarka:gradle-retrolambda:2.4.+'\n}\n```\n\nそしてそれぞれのモジュールをbuild.gradleに追加する\n\n```groovy\napply plugin: 'retrolambda'\n\nandroid {\n    compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n}\n\nretrolambda {\n    jdk System.getenv(\"JAVA8_HOME\")\n    oldJdk System.getenv(\"JAVA7_HOME\")\n    javaVersion JavaVersion.VERSION_1_7\n}\n```\n\nAndroid StudioはJava8のlambda記法のためのコードアシストをサポートしている。もし、あなたがlambdaのビギナーであれば、下記にならって使ってみよう\n\n- 一つだけメソッドがあるインターフェイスはどれも“lambdaに親和性あり“で、構文をより短くできる\n- もしパラメータなどに迷ったときは、普通のインナークラスを書いて、Android Studioでそれをlambdaに盛り込ませてみよう\n\n**65k制限に注意して、たくさんのライブラリを使うのを避けよう。** \nAndroidアプリはdexファイルにパッケージングする際に関数の参照は65536個までという厳格な制限がある。[\\[1\\]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [\\[2\\]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [\\[3\\]](http://jakewharton.com/play-services-is-a-monolith/)。制限を超えた場合はFatal Errorが起きる、そのため、ライブラリは最小限とし、制限内に収まるよう[dex-method-counts](https://github.com/mihaip/dex-method-counts)ツールを使って使用するライブラリを決めよう。特にGuavaは13kも関数があるので避けた方がいい。\n\n### Activities and Fragments\n\nAndroidにおいてはUIの実装は[Fragments](http://developer.android.com/guide/components/fragments.html)で行うべきである。Fragmentsは、アプリ内で構成出来る再利用可能なUIである。ActiivtyではUIの実装をせずにFragmentsで行うことをすすめる。理由は下記である。\n\n- **multi-pane layoutの解決について。** Fragmentは元はphoneアプリケーションをTableアプリケーションへ拡張するためのものとして紹介された。phoneアプリでAもしくはBというpaneが占めている場合に、TabletではAとBを表示することができる。はじめからfragmentを使っているなら、あとで異なるフォームファクタへ変更する事が簡単になる。\n\n- **スクリーン間のコミニケーションについて。** AndroidはActivity間の通信として複雑なデータ(たとえばJava Object)を送るAPIを提供していない。Fragmentであれば、その子Fragment間の通信経路としてActivityのインスタンスを使う事ができる。とはいえ、[Otto](https://square.github.io/otto/)や[greenrobot-EventBus](https://github.com/greenrobot/EventBus)を使ってEventBusを使いたいと思うだろう。他のライブラリの追加を避けたい場合はRxJavaを用いてEventBusを実装する事も可能である。\n\n- **FragmentはUIだけじゃなくても十分につかえる。** ActivityのbackgroundワーカとしてfragmentをUIなしでもつこともできる。Activityにロジックを持たせる代わりに、[複数のfragmentを変更するロジックを持ったfragmentを作ることも可能である](http://stackoverflow.com/questions/12363790/how-many-activities-vs-fragments/12528434#12528434)。\n\n- **FragmentからActionBarを管理できる。** ActionBarを管理するだけのUIを持っていないFragmentをもっても良いし、また現在表示されているFragmentにActionBarの振る舞いをまかせても良い。詳しくは[こちら](http://www.grokkingandroid.com/adding-action-items-from-within-fragments/)を参考にしてほしい。\n\n[matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/)が起きるので、[Fragmentを大規模にネスト](https://developer.android.com/about/versions/android-4.2.html#NestedFragments)すべきではない。例えば、横スライドするViewPagerをもったfragmentのなかに表示するfragmentといった理にかなったケースもしくは十分に考えられている場合のみ使用すべきである。\n\n設計レベルの話をすると、アプリは一つのトップレベルのActivityを持つべきである。他のActivityは[`Intent.setData()`](http://developer.android.com/reference/android/content/Intent.html#setData(android.net.Uri))や[`Intent.setAction()`](http://developer.android.com/reference/android/content/Intent.html#setAction(java.lang.String))などで簡単に遷移でき、メインのActivityをサポートするくらいにすると良い。\n\n### Java package 構成\n\nAndroidにおける設計はおおよそ[Model-View-controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)である。[Androidにおいては、FragmentとActivityがControllerに相当する](http://www.informit.com/articles/article.aspx?p=2126865)が、一方で、これらは明らかにユーザインターフェイスであり、Viewでもある。\n\n以上のことから、FragmentまたはActivityを厳格にControllerかViewかに分類する事は難しい。そのため分類せずにfragmentは`fragments`というパッケージに納めると良い。Activityはトップレベルのパッケージに置いても良いが、もし2つ３つ以上あるなら`activities`というパッケージを作ると良い。\n\nその他は典型的なMVCだ。`models`パッケージはAPIレスポンスをJSONパースした結果のPOJOを入れ、`views`にはカスタムView,Notifications,ActionBar View, ウィジェットなどを配置する。Adapterはviewとデータの間にいるので微妙だが、`getView()`メソッドからViewを生成する必要がよくあるので、`views`パッケージのサブパッケージとして`adapters`を作りそこに配置すると良い。\n\nアプリ内で多様に使われAndroidシステムに密接なコントローラクラスは`managers`パッケージへ、各Dataを混ぜこぜにつかうDataUtilのようなクラスは`utils`へ、バックエンドとインタラクティブに反応するクラスは`network`パッケージに配置しよう。\n\nバックエンドに最も近いところからユーザに最も近いところへという順で並べると下記のような構成になる。\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n### Resources\n\n**命名規則について。** \nたとえば、`fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`といったように、`type_foo_bar.xml`というタイプを接頭辞とする慣習に従おう。\n\n**Layout xmlを整理しよう。** \nもしLayout xmlのフォーマット方法が不明確なら下記の慣習が役立つと思われる。\n\n- 1 attribute につき 1 lineでインデントは4スペース\n- `android:id`は常に一番始めに\n- `android:layout_****`は上に\n- `style`は一番下\n- attributeを追加しやすいように`/>`のみで1 line\n- `android:text`をハードコーディングするよりは、[Designtime attributes](http://tools.android.com/tips/layout-designtime-attributes)を使う事を考えた方が良い\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\n大雑把に言うと、`android:layout_****`はLayout xmlで定義して、それ以外の`android:****`はStyle xmlの中で定義すると良い。下記を除くと大抵この方法でうまくいく。\n\n- `android:id`は確実にLayout xml内に\n- LinearLayoutの'android:orientation`はLayout xml内に\n- `android:text`はLayout xmlに\n- 時々Style xmlに`android:layout_width`と`android:layout_height`を定義してうまく行く事がある。(しかし、デフォルトではこれらはlayout filesの中にある)\n\n**Styleを使おう。** \nViewに統一感を持たせる為にStyleを適切に使う必要がある。Viewが繰り返し出ることはよくあることだからだ。少なくとも下記のようにText用のStyleは持っておいた方が良い。\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nこのスタイルはTextViewで下記の用に使う事ができる。\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\n同じことをボタンにもする必要があるが、そこで終わりにせず、関連性のあるまたは繰り返されたグループを移動して、`android:****`を共通のStyleに書き出そう。\n\n**大きなStyle Fileを避け、複数に分けよう。** \n１つの`styles.xml`だけを持つ事は止めた方が良い。styleファイルは`style_home.xml`、`style_item_details.xml`、`styles_forms.xml`と言ったように複数持つ事ができる。`res/values`の中のファイル名は任意である。\n\n**`color.xml`はカラーパレットである。** \ncolors.xmlは色の名前で定義しよう。下記のように各ボタンによって定義するといったようなことはすべきじゃない。\n\n*下記は良くない例。*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\nこういう書き方をしてしまうと基本色を変更する場合などに対応しづらい。\"button\"や\"comment\"といった内容はbutton styleで定義すればよく、`colors.xml`の中に定義すべきではない。\n\n`colors.xml`は下記のように定義しよう。\n\n```xml\n<resources>\n\n    <!-- grayscale -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- basic colors -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\nnameは色の名前でなく\"brand_primary\", \"brand_secondary\", \"brand_negative\"などとしても良い。そうする事で色の変更がしやすくなり、またどれだけの色が使われているかがわかりやすい。通常、きれいなUIの為には使用する色を減らす事も重要だ。\n\n**dimens.xmlもcolors.xmlのように扱おう。** \n典型的なスペースやフォントサイズをcolors.xmlのパレットのように定義しよう。下記は良い例である。\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\nmarginやpaddingをハードコードするのではなく、`spacing_****`を使用するようにしよう。そうする事で簡単に全体に統一感を持たす事ができ、また整理も簡単にできる。\n\n**Viewの深いネストは止めよう。** \n下記のようにLinearLayoutを組み合わせてViewを作ろうとすることがある。\nそうするとLayout xmlは下記のようになる。\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nもし、一つのLayout ファイルに書いていなくてもJava側でinflateした際に同じ状況になる事もあり得る。\n\nこれはいくつかの問題起こす。まずはきっとあなたも経験しただろう、UIの煩雑さによるパフォーマンス低下の問題である。他にも深刻な[StackOverFlow](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views)を起こす可能性もある。\n\n以上の理由から、Viewの階層はなるべくフラットにするべきである。そのために[RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html)の使い方、[Layoutの最適化](http://developer.android.com/training/improving-layouts/optimizing-layout.html)の方法、[\\<merge\\>タグ](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts)の使い方を知っておこう。\n\n**WebViewの参照問題に気をつけよう。** \n例えばNewsの記事などのweb pageを表示する必要がある場合、クライアントサイドでHTMLを整形する事は止めた方が良い。HTMLはバックグラウンドプログラマに用意してもらおう。また[WebViewはActivityの参照を持つときにメモリリークしうる](http://stackoverflow.com/questions/3130654/memory-leak-in-webview)。Activityの代わりにApplicationContextを使用しよう。単純なテキストやボタンを表示するのにTextViewやButtonではなくWebViewを使用する事も避けた方がいい。\n\n\n### テストフレームワーク\n\nAndroid SDKのテストフレームワークは特にUIテストにおいてまだまだ未熟なところがある。\nAndroid Gradleに、あなたがAndroidのJUnitのヘルパーを使って書いたJUnitのテストを走らせる[connectedAndroidTest](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing)がある。これはdeviceもしくはemulatorをつなぐ必要がある。次のテストガイドを見ておこう。[\\[1\\]](http://developer.android.com/tools/testing/testing_android.html) [\\[2\\]] (http://developer.android.com/tools/testing/activity_test.html)\n\n**viewを使わないUnitテストには[Robolectric](http://robolectric.org/)を使おう。** \nこのテストフレームワークはデバイスにつなぐ必要がないため開発効率があがる。UIのテストには向いていないがモデルとViewモデルのテストに適している。\n\n**[Robotium](https://code.google.com/p/robotium/)は簡単にUIテストを作る事ができる。** \nこのテストフレームワークにはViewの取得、解析する為のヘルパーメソッド、スクリーンをコントロールする為のヘルパーメソッドが多く用意されている。テストケースも下記のようにシンプルに書く事ができる。\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // searches for the first occurence of \"More\" and clicks on it\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n### Emulator\n\nAndroidアプリを専門で開発していくなら[Genymotion emulator](http://www.genymotion.com/)のライセンスは買っておいた方が良い。Genymotionは通常のAVD Emulatorよりも早い。またアプリのデモ、ネットワーク接続品質のエミュレート、GPS、などなどを行う為のツールがそろっている。\nテストはたくさんの端末で行わなければならないが、実際にたくさんの端末を買うよりはGenymotionのライセンスを買う方がコスパが良い。\n\n注: GenymotionはGoogle Play StoreやMapなどがインストールされていない。またSamsungの特定のAPIをテストしたい場合は、実際のSamsungの端末を使う必要がある。\n\n### Proguardの設定\n\n[ProGuard](http://proguard.sourceforge.net/)はAndroid Projectでコードを圧縮、難読化するために使われる。\n\nProguardを使用するか否かはプロジェクトの設定に依る。通常リリースapkをビルドする際にProguardを使う場合gradleを下記のように設定する。\n\n```groovy\nbuildTypes {\n    debug {\n        runProguard false\n    }\n    release {\n        signingConfig signingConfigs.release\n        runProguard true\n        proguardFiles 'proguard-rules.pro'\n    }\n}\n```\n\nどのコードを保存し、どのコードを捨て難読化するかをを明確に示さなければならない。デフォルトの設定では`SDK_HOME/tools/proguard/proguard-android.txt`を使用する。また`my-project/app/proguard-rules.pro`に定義する事でデフォルトのものに追加することができる。\n\nProGuard関連のよくある問題でビルドが成功したにもかかわらず、アプリの起動で`ClassNotFoundException`や`NoSuchFieldException`などのExceptionを発生してアプリがクラッシュすることがある。これは以下の二つのどちらかを意味する。\n\n1. ProGuardが必要なクラス、enum、関数、フィールド、アノテーションを削除してしまった。\n2. リフレクションなどを使っており難読化によってリネームされたクラスへの参照ができない。\n\nもしあるオブジェクトが削除されている疑いがあるなら`app/build/outputs/proguard/release/usage.txt`を確認しよう。オブジェクトの難読化結果を見るなら`app/build/outputs/proguard/release/mapping.txt`を確認しよう。\n\n必要なクラスや関数の削除を防ぐには`keep`オプションをproguard configに追加しよう。\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\n難読化を防ぐには`keepnames`を使う。\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\n**Tip** \nリリースするたびに`mapping.txt`を保存しておこう。ユーザがバグを踏み、難読化されたスタックトレースを送ってきた際にデバッグする事ができる。\n\n**DexGuard**\nさらに最適化され、さらに難読化されたものを考えるならDexGuardの採用を考えよう。DexGuardはProGuardを作った同じチームが開発している商用のものである。さらにDexGuardなら簡単にDexファイルを分割し65k制限を解決する。\n\n### Thanks to\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton and other Futurice developers for sharing their knowledge on Android development.\n\n### License\n\n[Futurice Oy](www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n\n\nTranslation\n===========\n\nTranslated to Japanese (`ja`) by **Shinnosuke Kugimiya, Aska Kadowaki**.\n\nOriginal content by [Futurice Oy](http://www.futurice.com).\n\n"
  },
  {
    "path": "translations/Korean/README.ko.md",
    "content": "# Android 개발 모범 사례\n\n다음은 [Futurice](http://www.futurice.com)의 Android 개발자들로부터 학습한 내용들이다. 이 가이드를 따라가면서 이미 했던 작업을 되풀이(Reinventing the wheel)하지 않도록 하자. iOS나 Windows Phone 개발에도 관심이 있다면, [**iOS Good Practices**](https://github.com/futurice/ios-good-practices) 혹은 [**Windows App Development Best Practices**](https://github.com/futurice/windows-app-development-best-practices) 문서들도 확인해보자.\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n\n## 요약\n\n#### Gradle을 사용하자. 이는 권장되는 프로젝트 구조이다.\n#### gradle.properties에 비밀번호나 민감한 데이터들을 넣어두자.\n#### HTTP 클라이언트를 직접 작성하지 말고, Volley나 OkHttp 라이브러리들을 사용하자.\n#### JSON 데이터를 파싱하는 데에는 Jackson 라이브러리를 사용하자.\n#### 65,000 메소드 수 제한을 방지하기 위해 Guava는 피하고 몇 가지의 라이브러리들만을 사용하자.\n#### UI 화면을 표현하는 데에 Fragment들을 사용하자.\n#### Fragment들을 관리하는 것은 Activity들이 맡도록 하자.\n#### 레이아웃 XML들 또한 코드이다. 그 것들을 잘 관리하자.\n#### 레이아웃 XML에서 중복된 속성들을 피하기 위해 style을 사용하자.\n#### 하나의 style이 방대해지는 것을 피하기 위해 여러가지 style 파일들을 사용하자.\n#### colors.xml을 짧게, 중복 없이 유지하고, 팔렛트처럼 정의해두자.\n#### dimens.xml 또한 중복 없이, 일반 상수로 정의하자.\n#### ViewGroup에 계층을 깊게 형성하지 않도록 하자.\n#### WebView에 클라이언트 측 프로세싱을 피하고, 여러 누수들에 유의하자.\n#### 유닛 테스트에는 Robolectric를 사용하고, UI 테스트에는 Robotium을 사용하자.\n#### 에뮬레이터로는 Genymotion를 사용하자.\n#### 항상 ProGuard 혹은 DexGuard를 사용하자.\n\n\n----------\n\n### Android SDK\n\n[Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools)를 홈 디렉토리나 다른 애플리케이션에 독립적인 위치에 두자. 몇몇 IDE들은 설치시에 SDK를 해당 IDE와 같은 경로에 포함시키는데, 이는 IDE를 업그레이드(혹은 재설치)하거나 IDE가 변경될 때 불편하다. 또한 IDE가 root 아래에 있지 않고 user 아래에서 동작할 경우, SDK를 sudo 권한을 요구하는 시스템 레벨의 디렉토리에 두지 않도록 하자.\n\n### 빌드 시스템\n\n기본 옵션은 [Gradle](http://tools.android.com/tech-docs/new-build-system)이다. Ant는 상당히 제한적이고 내용이 장황하다. Gradle을 사용하면, 다음 항목들이 간단해진다.\n\n- 앱의 각기 다른 Flavor들과 Varient들을 빌드할 수 있다.\n- Task들을 간단한 스크립트처럼 만들 수 있다.\n- 여러 Dependency들을 관리하고 다운로드할 수 있다.\n- Keystore들을 커스터마이즈할 수 있다.\n- 기타 등등\n\nAndroid의 Gradle 플러그인은 새로운 표준 빌드 시스템으로서 구글에 의해 활발하게 개발되고 있다.\n\n### 프로젝트 구조\n\n두 가지 많이 쓰이는 옵션들이 있다: 낡은 Ant & Eclipse ADT 프로젝트 구조, 새로운 Gradle & Android Studio 프로젝트 구조가 있는데, 새로운 프로젝트 구조를 선택하자. 만약 낡은 구조를 사용하고 있다면, 레거시로 판단하고 새로운 구조로 포팅하는 작업을 시작하자.\n\nOld structure:\n\n```\nold-structure\n├─ assets\n├─ libs\n├─ res\n├─ src\n│  └─ com/futurice/project\n├─ AndroidManifest.xml\n├─ build.gradle\n├─ project.properties\n└─ proguard-rules.pro\n```\n\nNew structure:\n\n```\nnew-structure\n├─ library-foobar\n├─ app\n│  ├─ libs\n│  ├─ src\n│  │  ├─ androidTest\n│  │  │  └─ java\n│  │  │     └─ com/futurice/project\n│  │  └─ main\n│  │     ├─ java\n│  │     │  └─ com/futurice/project\n│  │     ├─ res\n│  │     └─ AndroidManifest.xml\n│  ├─ build.gradle\n│  └─ proguard-rules.pro\n├─ build.gradle\n└─ settings.gradle\n```\n\n주된 차이점은 Gradle에서 온 개념인데, 새로운 구조가 'source sets' (`main`, `androidTest`)를 명시적으로 분리시켜둔다는 것이다. 예를 들어 `src`에 paid와 free라는 각기 다른 Flavor에 해당하는 소스코드를 갖는 'paid'라는 소스 셋과 'free'라는 소스 셋을 추가할 수 있다.\n\n최상위 레벨 `app`을 갖는 것은 앱과 앱에서 참조된 다른 라이브러리 프로젝트들(e.g., `library-foobar`)을 구별하는 데에 유용하다. `settings.gradle`은 `app/build.gradle`에서 참조할 수 있는 이러한 라이브러리 프로젝트들을 보관한다.\n\n### Gradle 설정\n\n**일반적인 구조.** [Google's guide on Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)를 확인하자.\n\n**작은 Task들.** 스크립트들(shell, Python, Perl, etc) 대신, Gradle의 Task들을 만들 수 있다. [Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF)에서 더 자세한 내용을 확인하자.\n\n**비밀번호** 앱의 `build.gradle`에 릴리즈 빌드를 위한 `signingConfigs` 정의가 필요할 것이다. 다음은 피하자.\n\n_아래 방법처럼 작업하지 않도록 한다_. 이는 버전 관리 시스템에서 나타날 것이다.\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\n대신, `gradle.properties` 파일을 만들자. 이는 버전 관리 시스템에 추가되어선 _안된다_:\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\n위 파일은 gradle에 자동으로 임포트되어, `build.gradle`에 이렇게 사용할 수 있다:\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**jar 파일 임포트 대신 Maven을 선호하자.** 프로젝트에 jar 파일을 명시적으로 포함시킬 경우, 이들은 `2.1.1`처럼 특정하게 고정된 버전이 된다. jar를 다운로드하고, 업데이트하는 것은 귀찮은 일이다. 그러나 Maven은 이 문제를 적절하게 해결해줄 것이고, 또한 이는 Android Gradle 빌드에서 장려되는 방식이다. 예를 들자면 이렇다:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp:2.2.0'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'\n}\n```\n\n**Maven의 동적 의존성 해결을 피하라**\n`2.1.+`과 같이 동적으로 버전을 정하는 방식은 불안정하고, 빌드 사이에 미묘하고 이해하기 어려운 차이를 초래할 수 있어 피하도록 하자. `2.1.1`처럼 정적으로 고정된 버전을 사용하는 것이 보다 안정적이고, 예측 가능하고, 반복적인 개발 환경을 구성하는 데에 도움이 될 것이다.\n\n### IDE와 텍스트 에디터\n\n**프로젝트 구조를 다루는 데에 용이한 에디터라면 무엇이든 사용해도 좋다.** 에디터는 개인적인 선택이고, 그 에디터가 프로젝트 구조와 프로젝트 빌드 시스템에 따라 기능하도록 하는 것은 개발자의 몫이다.\n\n현재 가장 추천하는 IDE는 [Android Studio](https://developer.android.com/sdk/installing/studio.html)이다. Google이 개발했고, Gradle에 가장 밀접하며, 기본적으로 새로운 프로젝트 구조를 사용하는데다가 안정화 단계에 들어가 Android 개발에 잘 맞추어져 있기 때문이다.\n\n원한다면 [Eclipse ADT](https://developer.android.com/sdk/installing/index.html?pkg=adt)를 사용해도 좋지만, 빌드하는 데에 낡은 프로젝트 구조와 Ant를 사용하기 때문에 이에 대한 설정이 필요하다. Vim, Sublime Text, Emacs같은 플레인 텍스트 에디터를 사용할 수도 있다. 이 경우에는 Gradle과 `adb`를 커맨드라인에서 사용해야 한다. Eclipse의 Gradle 사용이 제대로 작동하지 않는다면, 커맨드라인으로 빌드하거나 Android Studio로 옮기자. ADT 플러그인이 deprecate되었기 때문에, 이 것이 가장 좋은 옵션일 것이다.\n\n무엇을 사용하든, 애플리케이션 빌드의 공식적인 방법인 Gradle과 새로운 프로젝트 구조를 따르고, 특정 에디터를 따르는 설정 파일을 버전 관리 시스템에 추가하는 것을 피하는 것만 명심하자. 예를 들면, Ant의 `build.xml` 파일들은 추가하지 않도록 한다. 특히 Ant의 빌드 설정을 변경하고 있다면 `build.gradle`을 최신의 상태로 기능하도록 하는 것을 잊지말자. 또한 다른 개발자들에게 친절해지자. 그들의 설정을 바꾸도록 강요하지 않아야한다.\n\n### 라이브러리\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)**은 Object를 JSON으로, 혹은 그 반대로 변환해주는 Java 라이브러리이다. [Gson](https://code.google.com/p/google-gson/)이 이 문제를 해결하는 데에 많이 쓰이긴 하지만, 스트리밍, 인메모리 트리 모델, 전통적인 JSON-POJO 데이터 바인딩과 같은 여러 대안들을 지원하는 Jackson이 더 고성능일 것이다. 하지만 명심하자. Jackson이 GSON보다 더 큰 라이브러리이기 때문에, 65,000 메소드 수 제한에 부딪힌 경우라면 GSON을 사용하는 것이 나을 수도 있다. 다른 대안으로는 [Json-smart](https://code.google.com/p/json-smart/)과 [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)이 있다.\n\n**네트워킹, 캐싱, 이미지.** 백엔드 서버로의 요청 처리에 대해 클라이언트를 구현하고 처리하는 두 가지 검증된 해결책이 있다. [Volley](https://android.googlesource.com/platform/frameworks/volley) 혹은 [Retrofit](http://square.github.io/retrofit/)을 사용하자. Volley는 이미지를 불러오고 캐싱하는 도우미를 제공한다. Retrofit을 선택한다면, 이미지 로딩과 캐싱에는 [Picasso](http://square.github.io/picasso/)를, 효율적인 HTTP 요청에는 [OkHttp](http://square.github.io/okhttp/)를 고려해보자. 이 모든 세가지의 라이브러리들은 같은 회사에서 개발되어 서로 상호보완이 매우 용이하다. [OkHttp can also be used in connection with Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n\n**RxJava** 비동기 이벤트를 처리하는 Reactive Programming을 위한 라이브러리이다. 이는 매우 강력하고 유망한 패러다임으로, 너무 다른 점이 많아 혼란스러울 수 있다. 모든 애플리케이션에서 아키텍트들에게 이 라이브러리를 쓰기 전 주의할 것을 추천한다. RxJava를 이용한 몇 가지 프로젝트가 있는데, 필요하다면 이 사람들에게서 도움을 구하자: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. 작성된 블로그 포스트도 있다: [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\nRx에 대한 경험이 없다면, API 응답 처리에만 적용해보자. 다른 방법으로는 클릭 이벤트나 검색 타이핑 이벤트와 같은 간단한 UI 이벤트 처리에 적용해볼 수도 있다. Rx 기술에 자신감이 생겨 모든 설계에 적용하고 싶다면, 모든 까다로운 부분들에 Javadocs를 작성하자. RxJava에 익숙하지 않은 다른 프로그래머가 프로젝트를 유지, 보수하는 데에 어려움이 있을 수 있다는 것을 명심해야 한다. 그들의 Rx와 코드 이해에 대해 최선을 다해 도움을 주자.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)**는 Android 혹은 다른 pre-JDK8 플랫폼에서 Lambda 표현 문법을 사용할 수 있도록 하는 Java 라이브러리이다. 이 라이브러리는 특히 RxJava와 같이 기능 위주 스타일의 코드를 더욱 타이트하고 읽기 좋게 만들어준다. 사용하려면, JDK8을 설치하고 이를 Android Studio 프로젝트 대화상자에서 SDK 경로로 설정한 후, `JAVA8_HOME`과 `JAVA7_HOME` 환경변수를 설정한 뒤 프로젝트 root의 build.gradle을 이렇게 설정한다:\n\n```groovy\ndependencies {\n    classpath 'me.tatarka:gradle-retrolambda:2.4.1'\n}\n```\n\n그리고 각각 모듈들의 build.gradle에 아래 내용을 추가하자.\n\n```groovy\napply plugin: 'retrolambda'\n\nandroid {\n    compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n}\n\nretrolambda {\n    jdk System.getenv(\"JAVA8_HOME\")\n    oldJdk System.getenv(\"JAVA7_HOME\")\n    javaVersion JavaVersion.VERSION_1_7\n}\n```\n\nAndroid Studio는 Java8 lambda의 코드 지원을 제공한다. 만약 lambda가 처음이라면, 다음 항목들을 따라 시작해보자:\n\n- 하나의 메소드를 갖는 모든 인터페이스들은 \"lambda와 밀접\"하고, 더욱 타이트한 문법으로 묶일 수 있다.\n- 만약 파라메터들이 의심스럽다면, 일반 익명 내부 클래스를 작성하고 Android Studio가 lambda로 묶어주도록 해보자.\n\n**Dex 메소드 제한을 유의하고, 많은 라이브러리 사용을 피하자.** Android 앱들이 dex 파일로 패키징될 때, 65,536개의 참조 메소드 수 제한을 갖는다[[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). 제한된 메소드 수를 넘어서면 컴파일시 Fatal error를 보게될 것이다. 그렇기 때문에, 최소한의 라이브러리들을 사용하고, [dex-method-counts](https://github.com/mihaip/dex-method-counts) 툴을 사용하여 제한된 수보다 적게 유지하기 위해 어떤 라이브러리들을 사용할지 결정하자. 특히 Guava 라이브러리는 피하자. 이 라이브러리는 13,000개가 넘는 메소드를 가지고 있다.\n\n### Activity와 Fragment\n\nFragment와 Activity를 이용하여 Android의 구조를 가장 좋은 방법으로 설계하는 방법은 커뮤니티나 Futurice 개발자들 사이에서도 합의된 바가 없다. Square는 Fragment의 우회 대안으로 [a library for building architectures mostly with Views](https://github.com/square/mortar)를 제공하는데, 이 또한 커뮤니티 사이에서 널리 추천할만한 방식은 아니라고 생각된다.\n\nAndroid API의 히스토리로 인해, 막연히 Fragment가 화면상의 UI 조각이라고 떠올릴 수 있을 것이다. 즉, Fragment는 일반적으로 UI와 연관되어 있다는 것이다. Activity 또한 막연하게 그들의 라이프사이클과 상태를 관리하는 데에 중요한 컨트롤러라고 생각할 수 있다. 그러나, 다음 역할들에서 차이를 쉽게 찾아볼 수 있다: Activity는 UI 역할을 수행하고([delivering transitions between screens](https://developer.android.com/about/versions/lollipop.html)), [Fragment는 독립적으로 컨트롤러의 역할을 수행한다](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). 그래서 우리는 Fragment 혹은 Activity, 또는 View 셋 중 하나만을 이용한 구조를 선택함에 있어서 결함이 있다는 점을 파악하고 정확한 근거를 갖는 결정을 하여 조심스럽게 시작하기를 권한다. 다음은 주의해야 할 것들에 대한 조언인데, 적당히 걸러서 수용하자:\n\n- [Nested fragments](https://developer.android.com/about/versions/android-4.2.html#NestedFragments)를 널리 사용하는 것은 피해야 하는데, [matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/)가 발생할 수 있기 때문이다. 중첩된 Fragment는 꼭 타당한 경우(예를 들면, 수평으로 슬라이딩하는 ViewPager 내부의 Fragment들)나 잘 설명할 수 있을 만한 경우에만 사용하자.\n- Activity에 너무 많은 코드를 넣는 것을 피해야 한다. 가능하면 언제든지 가벼운 컨테이너로서 유지하고, 주로 라이프사이클과 다른 중요한 Android와의 인터페이싱 API를 위해서만 존재하도록 하자. 순수 Activity 보다는 단일 Fragment로 구성된 Activity가 좋다 - UI 코드를 Activity의 Fragment에 넣자. 이는 다른 잘 구성된 레이아웃, 혹은 여러 Fragment로 구성된 타블렛 화면으로 옮길 필요가 있을 때에 재사용이 가능하도록 만든다. 정확한 근거가 없는 결정이라면 Fragment와 상호 작용하지 않는 Activity는 피하자.\n- 앱의 내부적 동작이 Intent에 강하게 의존적인 Android 레벨의 API를 남용해서는 안된다. 이는 버그와 렉을 유발하여 Android OS나 다른 애플리케이션들에 영향을 줄 수 있다. 예를 들어, 만약 앱이 당신의 패키지 사이에서 내부적인 커뮤니케이션을 위해 Intent를 사용한다면, 앱이 OS 부팅 바로 후에 실행되었을 때 사용자 경험 상에서 몇 초간의 렉을 발생시킬 수 있다고 알려져 있다.\n\n### Java 패키지 설계\n\nAndroid 애플리케이션을 위한 Java 설계 간단히 [Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) 간략화할 수 있다. Android에서는, [Fragment and Activity are actually controller classes](http://www.informit.com/articles/article.aspx?p=2126865) 라고 설명되는데, 다른 면에서 Fragment와 Activity들은 명시적으로 사용자 인터페이스, 즉 View 이기도 하다.\n\n그렇기 때문에, Fragment(혹은 Activity)를 정확히 Conteroller나 View 구분할 수 없다. 그래서 그에 해당하는 `fragments` 패키지에 두는 것이 낫다. Activity는 이전 섹션에서의 조언에 따라 최상위 패키지에 둘 수 있다. 2, 3개 이상의 Activity들을 계획하고 있다면, `activities` 패키지를 만들어 두자.\n\n다른 경우에는, API 응답에 대한 JSON 파서에 의해 채워진 POJO들을 담는 `models` 패키지, 커스텀 View, Notification, Action bar view, Widget 등을 담는 `views` 패키지를 두어 설계가 일반적인 MVC로 표현될 수 있다. Adapter들은 데이터와 View들 사이에 존재하는 gray matter라고 할 수 있지만, 일반적으로 `getView()`를 통해 View들을 추출하는 데에 필요하기 때문에 `views` 패키지 안에 `adapters`라는 서브패키지로 둘 수 있다.\n\nController 클래스들은 애플리케이션 전체에, Android 시스템에 가깝게 존재한다. 이들은 `managers` 패키지에 둘 수 있다. \"DateUtils\"와 같은 다양한 데이터 처리 클래스들은 `utils` 패키지에, 백엔드와 인터랙션하는 역할을 맡는 클래스들은 `network` 패키지에 두자.\n\n종합적으로, 백엔드와 가까운 것부터 유저와 가까운 순서대로 정렬해보면 이렇다:\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n### 리소스\n\n**이름 정하기.** `type_foo_bar.xml`과 같이 타입을 접두어로 두는 컨벤션을 따르자. 예시: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**레이아웃 XML을 체계화하기.** 레이아웃 XML을 어떤 형태로 만들지 확실치 않다면, 다음 컨벤션이 도움이 될 것이다.\n\n- 한 속성당 한 줄, 들여쓰기는 4칸의 스페이스\n- `android:id`를 항상 첫 속성으로\n- `android:layout_****` 속성들을 윗쪽에\n- `style` 속성은 맨 아래에\n- 태그를 닫는 `/>`는 정렬과 새 속성 추가를 위해 독립적인 줄에\n- Rather than hard coding `android:text`에 하드코딩하는 것보다, Android Studio에서 사용 가능한 [Designtime attributes](http://tools.android.com/tips/layout-designtime-attributes)를 고려하자.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\n가장 중요한 것은, `android:layout_****`를 레이아웃 XML에 두고 `android:****`를 스타일 XML에 정의하는 것이다. 이 규칙은 예외가 있지만, 일반적으로 잘 동작한다. 이는 레이아웃(위치, 여백, 크기)과 내용에 관한 속성을 레이아웃 파일에 두고, 상세한 모양(색, 안쪽 여백, 폰트)에 대한 내용은 스타일 파일에 두기 위함이다.\n\n예외는 이런 경우가 있다:\n\n- `android:id`는 정확히 레이아웃 파일에 두어야 한다. should obviously be in the layout files\n- `LinearLayout`의 `android:orientation` 속성은 일반적으로 레이아웃 파일에 있는 것이 타당하다.\n- `android:text`는 내용을 정의하는 속성이기 때문에 레이아웃 파일에 두어야 한다.\n- 가끔 일반적인 스타일로 `android:layout_width`와 `android:layout_height` 속성들을 두어야 말이 될 것 같지만, 기본적으로 이들은 레이아웃 파일에 보여진다.\n\n**스타일을 사용하자.** View에 중복되는 모양이 사용되는 것은 매우 일반적인 일이기 때문에, 거의 모든 프로젝트들이 스타일을 적절히 사용해야한다. 적어도 애플리케이션에서 대부분의 텍스트 내용들은 일반 스타일을 가져야한다. 예를 들면 이렇다:\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nTextView에 적용해보면:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\n아마 버튼들에도 같은 일을 해주어야 하겠지만, 멈추지 말자. 계속 진행하면서 연관되어있고 중복된 `android:****` 속성들을 일반 스타일로 묶자.\n\n**큰 스타일 파일은 다른 파일들로 나누자.** 단 하나의 `styles.xml` 파일을 가질 필요는 없다. Android SDK는 박스 외부의 파일들도 지원하는데, `styles`라는 이름엔 전혀 마법같은 무언가가 없이 파일 안에 `<style>` XML 태그가 있다면 상관없다. 그렇기 때문에 파일 이름은 `styles.xml`, `styles_home.xml`, `styles_item_details.xml`, `styles_forms.xml` 등과 같이 정할 수 있다. 빌드 시스템에서 의미를 갖는 리소스 디렉토리와는 다르게 `res/values` 안의 파일명은 임의로 설정 가능하다.\n\n**`colors.xml`는 색 팔렛트이다.** `colors.xml`에는 색 이름과 RGBA 값을 매핑해놓는 일 외에 더 해야할 일은 없다. 각각 다른 버튼 타입들에 RGBA 값들을 정의하지 않도록 하자.\n\n*아래의 방식은 피하자:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\n이러한 형식으로 RGBA 값들을 반복하기 쉬운데, 이는 기본 색깔을 필요에 따라 변경하기 복잡하게 만든다. 또한 이러한 방식의 정의는 \"button\" 혹은 \"comment\" 처럼 특정 문맥에 관계되어있어 `colors.xml`이 아닌 스타일에 더 적합하다.\n\n대신, 이렇게 하자:\n\n```xml\n<resources>\n\n    <!-- grayscale -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- basic colors -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\n애플리케이션의 디자이너에게 이 팔렛트를 요청해보자. 이름이 꼭 \"green\", \"blue\" 처럼 색의 이름일 필요는 없다. \"brand_primary\", \"brand_secondary\", \"brand_negative\" 같은 이름들이 더욱 받아들이기 쉽다. 이렇게 색의 형식을 지정하게 되면 색 값들을 리팩토링하기 쉬워지고, 얼마나 많은 색들이 사용되고 있는지 명시적으로 알 수 있다. 보통 심미감을 중요시하는 앱에서는, 사용되는 색의 종류를 줄이는 것이 중요하다.\n\n**dimens.xml을 colors.xml처럼 다루자.** 기본적으로 색과 같은 목적을 위해 일반적인 여백과 폰트 크기 등의 \"팔렛트\"를 정의하자. 다음은 dimens.xml 파일의 좋은 예시이다:\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\n문자열들이 일반적으로 다루어지듯이, 레이아웃, 바깥쪽/안쪽 여백에 하드코딩된 값들 대신 `spacing_****`을 사용하자. 이는 스타일과 레이아웃을 체계화하고 변경하는 것을 쉽게 해줌과 동시에 일관된 룩앤필(Look-and-feel)을 제공한다.\n\n**strings.xml**\n\nstrings.xml의 문자열들은 네임스페이스의 형태와 비슷하게 이름을 짓고, 2개 이상의 Key에 값을 중복해서 사용하는 것을 두려워하지 않도록 하자. 언어는 복잡하기 때문에, 네임스페이스가 문맥을 갖고 애매함을 없애는 것이 필수이다.\n\n**잘못된 예**\n```xml\n<string name=\"network_error\">Network error</string>\n<string name=\"call_failed\">Call failed</string>\n<string name=\"map_failed\">Map loading failed</string>\n```\n\n**좋은 예**\n```xml\n<string name=\"error.message.network\">Network error</string>\n<string name=\"error.message.call\">Call failed</string>\n<string name=\"error.message.map\">Map loading failed</string>\n```\n\n문자열 값을 모두 대문자로 쓰지 않도록 한다. 일반적인 텍스트 컨벤션을 따르되(e.g., 첫 글자만 대문자로), 만약 문자열을 모두 대문자로 표시해야 한다면, TextView의 [`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) 속성을 이용하자.\n\n**잘못된 예**\n```xml\n<string name=\"error.message.call\">CALL FAILED</string>\n```\n\n**좋은 예**\n```xml\n<string name=\"error.message.call\">Call failed</string>\n```\n\n**깊은 View 계층을 피하자.** 가끔 View를 편성하기 위해 LinearLayout을 하나 더 추가하려할 것이다. 이 상황은 이러한 문제를 일으킨다:\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\n레이아웃 파일에서 명시적으로 이런 형태를 보지 못했다 하더라도, 결국 다른 View에 또 다른 View들을 채울 때(Java에서) 이렇게 끝나게 될 것이다.\n\n두 가지 문제가 발생한다. 프로세서가 다루어야 할 UI 트리가 복잡해지면서 퍼포먼스 문제를 경험하게 될 것이다. 또 하나의 심각한 문제는 [StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views)의 가능성이다.\n\n그러므로, 최대한 View 계층을 수평하게 유지하자: [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html)를 사용하는 방법, [optimize your layouts](http://developer.android.com/training/improving-layouts/optimizing-layout.html) 방법과 [`<merge>` tag](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts)를 사용하는 방법을 확인하자.\n\n**WebView와 관련된 문제들에 유의하자.** 뉴스 기사와 같은 웹페이지를 보여주어야 할 때, 백엔드 프로그래머들에게 \"*순수한*\" HTML을 요청하지 않고 HTML을 정리하기 위해 클라이언트단에서 프로세싱하는 것을 피하자. ApplicationContext가 아닌 Activity로의 참조를 유지할 때, [WebViews can also leak memory](http://stackoverflow.com/questions/3130654/memory-leak-in-webview). 간단한 텍스트와 버튼을 사용할 때에는 WebView를 피하고 TextView와 Button을 사용하도록 한다.\n\n\n### 테스트 프레임워크\n\nAndroid SDK의 테스팅 프레임워크는 여전히 미흡한데, 특히 UI 테스트에 관해서는 더더욱 그렇다. Android Gradle은 현재 [extension of JUnit with helpers for Android](http://developer.android.com/reference/android/test/package-summary.html)을 사용하여 만들어진 JUnit 테스트들을 실행하는 [`connectedAndroidTest`](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing)라는 테스트 Task를 구현하고 있다. 이는 기기 혹은 에뮬레이터에 연결된 테스트를 실행해야 할 것을 의미한다. 공식 가이드인 [[1]](http://developer.android.com/tools/testing/testing_android.html) [[2]](http://developer.android.com/tools/testing/activity_test.html)를 따라 테스트하자.\n\n**View가 아닌 유닛 테스트에는 [Robolectric](http://robolectric.org/)를 사용하자.** 이는 개발 속도의 만족을 위해 \"기기에 연결되지 않은\" 테스트의 제공을 추구하는 테스트 프레임워크이다. 특히 모델과 View 모델들의 유닛 테스트에 적합하다. 하지만, UI 테스트에서의 Robolectric를 사용한 테스트는 부정확하고 불완전하다. 애니메이션, 대화 상자 등에 관한 UI 요소들의 테스트에서는 문제를 보일 것이고, 이는 \"어둠 속에서 걷는 것\"(조작할 만한 화면을 보지 않고 테스트)처럼 매우 복잡할 것이다.\n\n**[Robotium](https://code.google.com/p/robotium/)은 UI 테스트 작성을 쉽게 해준다.** UI의 연결된 테스트를 실행하는 데에 Robotium이 필요하지 않지만, View를 가져와 분석하고, 화면을 조작할 수 있게 해주는 Robotium의 많은 도우미들이 유용하게 작용할 것이다. 테스트 케이스는 이처럼 쉽게 표현된다:\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // searches for the first occurence of \"More\" and clicks on it\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n### 에뮬레이터\n\n전문적으로 Android 앱을 개발하고 있다면, [Genymotion emulator](http://www.genymotion.com/)의 라이센스를 구매하자. Genymotion 에뮬레이터는 일반적인 AVD 에뮬레이터에 비해 빠른 FPS로 실행된다. 앱을 데모하고, 네트워크 연결 품질, GPS 포지션을 시험해보는 툴들을 제공한다. 또한 연결된 테스트에 이상적으로 작동한다. 많은(전부는 아님) 다른 기기들을 접할 때, Genymotion의 라이센스는 실제 여러가지 기기를 구매하는 것 보다 훨씬 저렴하다.\n\n주의할 점: Genymotion 에뮬레이터는 Google Play Store와 Maps과 같은 모든 Google 서비스들을 포함하고 있지는 않다. 삼성의 특정 API를 테스트해야 한다면, 실제 삼성 기기가 필요하다.\n\n### Proguard 설정\n\n[ProGuard](http://proguard.sourceforge.net/)는 일반적으로 Android 프로젝트의 패키징된 코드를 축소하고, 난독화하기 위해 사용된다.\n\nProGuard를 사용하고 있는지 아닌지는 해당 프로젝트 설정에 달려있다. 보통 릴리즈 apk를 빌드할 때 gradle을 설정하고 ProGuard를 사용할 것이다.\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\n\n어떤 코드가 보존되어야 하고 어떤 코드가 버려지거나 난독화되어야할 지 결정하기 위해, 코드에 한 개 이상의 엔트리 포인트를 설정해야한다. 이 엔트리 포인트는 일반적으로 main 메소드, applets, midlets, Activity와 같은 것들이다.\nAndroid 프레임워크는 `SDK_HOME/tools/proguard/proguard-android.txt`에서 찾아볼 수 있는 기본 설정을 사용한다. 위의 설정을 사용하여, `my-project/app/proguard-rules.pro`의 사용자화된 특정 프로젝트 ProGuard 규칙은 기본 설정에 추가로 설정될 것이다.\n\nProGuard와 관련된 일반적인 문제는 어떠한 Warning도 없이 빌드 커맨드가 성공했는데도 애플리케이션이 시작시에  `ClassNotFoundException`나 `NoSuchFieldException`와 비슷한 예외로 크래시가 발생하는 것이다.\n이는 두 가지 중 하나를 의미한다:\n\n1. ProGuard가 클래스, Enum, 메소드, 필드 혹은 어노테이션들을 필요하지 않다고 여겨 제거한 것이다.\n2. ProGuard가 클래스, Enum, 필드 이름들이 간접적으로 고유의 이름대로 사용되고 있음에도 불구하고(예를 들면 Java reflection을 통해) 이들을 난독화(이름 변경)한 것이다.\n\n물음의 객체가 제거되었는지 보려면 `app/build/outputs/proguard/release/usage.txt`을 확인하자.\n물음의 객체가 난독화되었는지 보려면 `app/build/outputs/proguard/release/mapping.txt`을 확인하자.\n\nProGuard가 필요한 클래스 혹은 클래스 멤버들을 *벗겨내는 것*을 막기 위해서는, ProGuard 설정에 `keep` 옵션을 추가하자:\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nProGuard가 클래스 혹은 클래스 멤버들의 *난독화*을 막고싶다면, `keepnames`을 추가하자:\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\n또 다른 예시로 [Proguard](http://proguard.sourceforge.net/#manual/examples.html)를 읽어보자.\n\n**프로젝트의 초기에, 릴리즈 빌드를 만들자.** 이는 ProGuard 규칙들이 중요한 것들을 정확하게 보관하고 있는지 확인하기 위함이다. 또한 언제든지 새로운 라이브러리를 포함시켰을 때, 릴리즈 빌드를 만들고 기기에서 apk를 테스트해보자. 릴리즈 빌드를 만들기 위해 앱이 \"1.0\" 버전이 되기까지 기다리지 말고, 수 차례 의외의 문제들을 발견하고 수정하는 짧은 시간을 갖자.\n\n**팁.** 배포시에 `mapping.txt` 파일들은 매 릴리즈마다 저장하자. 각 릴리즈 빌드마다 `mapping.txt` 파일을 보관해두면, 사용자가 버그를 만나고 알아보기 힘든 스택 트레이스를 보내왔을 때 문제를 확실하게 디버깅할 수 있다.\n\n**DexGuard**. 릴리즈 코드를 최적화하고, 특히 알기 어렵게 만들기 위해 하드코어한 툴이 필요하다면, ProGuard를 빌드한 같은 팀에서 만든 상업 소프트웨어인 [DexGuard](http://www.saikoa.com/dexguard)를 고려해보자. 이는 65,000 메소드 수 제한을 해결하기 위해 Dex 파일들을 쉽게 나눈다.\n\n### Thanks to\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton and other Futurice developers for sharing their knowledge on Android development.\n\n### License\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n\nTranslation\n===========\n\nTranslated to Korean (`ko`) by **[Minsoo Park](http://www.github.com/minsoopark)**.\n\nOriginal content by [Futurice Oy](http://www.futurice.com).\n"
  },
  {
    "path": "translations/Portuguese/README.pt.md",
    "content": "# As melhores práticas no desenvolvimento Android\n\nLições aprendidas por programadores Android na [Futurice](http://www.futurice.com). Evite reinventar a roda seguindo estas recomendações. Se está interessado em desenvolver aplicações para iOS ou Windows Phone, não se esqueça de verificar também nossas [**iOS Good Practices**](https://github.com/futurice/ios-good-practices) e [**Windows App Development Best Practices**](https://github.com/futurice/windows-app-development-best-practices).\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n\n## Resumo\n\n#### Use o Gradle e a estrutura do projeto por ele recomendada\n#### Coloque suas senhas e dados sensíveis em gradle.properties\n#### Não escreva o seu próprio cliente de HTTP, utilize as bibliotecas Volley ou OkHttp\n#### Use a biblioteca Jackson para fazer o parse de JSON\n#### Evite o Guava e utilize poucas bibliotecas devido ao *limite máximo de 65 mil métodos*\n#### Use Fragmentos para representar um ecrã UIƒ\n#### Use Atividades apenas para gerir Fragmentos\n#### As layouts de XML são código, organize-as bem\n#### Use estilos para evitar atributos duplicados nas layouts de XML\n#### Use múltiplos ficheiros de estilos para evitar apenas um muito grande\n#### Mantenha o seu colors.xml pequeno e DRY (sem repetições), defina apenas a palete\n#### Mantenha também o dimens.xml DRY, defina constantes genéricas\n#### Não faça uma hierarquia muito profunda de ViewGroups\n#### Evite processar WebViews no cliente, e cuidado com fugas\n#### Use o Robolectric para testes unitários, Robotium para testes conetados (UI)\n#### Use sempre o ProGuard ou DexGuard\n#### Use SharedPreferences para persistência simples, caso contrário use ContentProviders\n\n\n----------\n\n### Android SDK\n\nColoque o [Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools) algures no seu diretório inicial ou algum outro local independente da aplicação . Alguns IDEs incluem o SDK aquando da instalação, e pode colocá-lo sob o mesmo diretório que o IDE. Isso pode ser ruim quando precisa de atualizar (ou reinstalar) o IDE, ou quando mudar IDEs . Além disso, evite colocar o SDK noutro diretório em nível de sistema que pode precisar de permissões sudo, se o IDE é executado sob o utilizador e não na raiz.\n\n### Sistema de compilação\n\nA sua opção padrão deve ser o [Gradle](http://tools.android.com/tech-docs/new-build-system). O Ant é muito mais limitado e também mais verboso. Com o Gradle, é fácil:\n\n- Construir sabores ou variantes diferentes do seu aplicativo\n- Fazer tarefas simples tipo script\n- Gerir e fazer o download de dependências\n- Personalizar keystores\n- E mais\n\nO plugin Gradle do Android também está a ser activamente desenvolvido pela Google como o novo sistema de compilação padrão.\n\n### Estrutura do Projeto\n\nExistem duas opções populares: a estrutura do projeto antiga Ant juntamente com o Eclipse ADT, e a nova estrutura do projeto Gradle juntamente com o Android Studio. Você deve escolher a nova estrutura do projeto. Se o seu projeto usa a estrutura antiga, considere-a desatualizada e comece a transferi-la para a nova estrutura.\n\nEstrutura antiga:\n\n```\nold-structure\n├─ assets\n├─ libs\n├─ res\n├─ src\n│  └─ com/futurice/project\n├─ AndroidManifest.xml\n├─ build.gradle\n├─ project.properties\n└─ proguard-rules.pro\n```\n\nEstrutura nova:\n\n```\nnew-structure\n├─ library-foobar\n├─ app\n│  ├─ libs\n│  ├─ src\n│  │  ├─ androidTest\n│  │  │  └─ java\n│  │  │     └─ com/futurice/project\n│  │  └─ main\n│  │     ├─ java\n│  │     │  └─ com/futurice/project\n│  │     ├─ res\n│  │     └─ AndroidManifest.xml\n│  ├─ build.gradle\n│  └─ proguard-rules.pro\n├─ build.gradle\n└─ settings.gradle\n```\n\nA principal diferença é que a nova estrutura separa explicitamente 'source sets' (`main`, `androidTest`), um conceito do Gradle. Você poderá, por exemplo, adicionar diretórios 'paid' e 'free' a `src` que terá o código fonte para os sabores pagos e gratuitos da sua aplicação.\n\nTer um diretório de topo `app` é útil para distinguir a sua aplicação de outras bibliotecas (por exemplo, `library-foobar`) que terá uma referência na sua aplicação. O `settings.gradle` posteriormente mantém referências para estas bibliotecas, e o `app/build.gradle` pode fazer referência a elas.\n\n### Configuração do Gradle\n\n**Estrutura geral.** Siga [o guia do Google sobre Gradle para Android](http://tools.android.com/tech-docs/new-build-system/user-guide)\n\n**Pequenas tarefas.** Ao invés de scripts (shell, Python, Perl, etc.), pode fazer tarefas com o Gradle. Siga [a documentação do Gradle](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF) para mais detalhes.\n\n**Senhas.** No `build.gradle` da sua aplicação, precisa de definir `signingConfigs` para a _compilação de lançamento_. O que deverá evitar:\n\n_Não faça isto_. Irá aparecerá no sistema de controlo de versão.\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nAo invés, crie o ficheiro `gradle.properties` o qual _não_ deverá ser adicionado ao sistema de controle de versão:\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nAquele ficheiro será importado automaticamente pelo gradle, podendo utilizá-lo no `build.gradle` da seguinte forma:\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**Prefira a resolução de dependências Maven em vez de importar ficheiros jar.** Se você incluir explicitamente os ficheiros jar no seu projeto, eles terão uma versão fixa específica, como `2.1.1`. Baixar jars e gerir atualizações é uma confusão, este é o problema que o Maven resolve de forma adequada, e é também incentivada nas compilações de Android Gradle. Por exemplo:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp:2.2.0'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'\n}\n```    \n\n**Evite a resolução de dependências dinâmicas do Mavem**\n\nEvite usar versões dinâmicas, como por exemplo `2.1.+`, isto porque podem resultar em compilações instáveis ou subtis diferenças de comportamento não rastreadas entre as compilações. O uso de versões estáticas como `2.1.1` ajuda a criar um ambiente de desenvolvimento mais estável, previsível e repetível.\n\n### IDEs e editores de texto\n\n**Use qualquer editor, mas este deverá integrar bem com a estrutura do projeto.** Os editores são uma escolha pessoal, contudo é sua responsabilidade colocar o editor a funcionar de acordo com a estrutura do projeto e o sistema de compilação.\n\nO IDE mais recomendado neste momento é o [Android Studio](https://developer.android.com/sdk/installing/studio.html), porque foi e está a ser desenvolvido pela Google, é o mais próximo do Gradle, usa a nova estrutura de projeto por definição, encontra-se em fase estável, e foi adaptado especificamente para desenvolvimento Android.\n\nPode usar o [Eclipse ADT](https://developer.android.com/sdk/installing/index.html?pkg=adt) se assim o desejar, mas terá de o configurar, visto que ele espera a antiga estrutura do projeto e compilações Ant. Poderá até mesmo usar editores de texto simples como o Vim, Sublime Text, ou Emacs. Nesse caso, irá ter de usar Gradle e `adb` na linha de comando. Se a integração do Eclipse com o Gradle não está a funcionar corretamente, as suas opções são usar a linha de comando apenas para compilação, ou migrar para o Android Studio. A última é a melhor opção visto que o plugin ADT foi depreciado recentemente.\n\nO que quer que use, certifique-se apenas que o Gradle e a nova estrutura do projeto se mantêm como a forma oficial de compilar a sua aplicação, e evite adicionar os ficheiros com as configurações específicas do seu editor ao sistema de controlo de versão. Por exemplo, evite adicionar o ficheiro Ant `build.xml`. Especialmente não se esqueça de manter o `build.gradle` atualizado e em funcionamento se está a modificar as configurações de compilação do Ant. Além disso, seja gentil com outros programadores, não os force a alterar as suas ferramentas preferidas.\n\n### Bibliotecas\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** é uma biblioteca em Java para converter Objetos em JSON e vice-versa. [Gson](https://code.google.com/p/google-gson/) é uma escolha popular para resolver este problema, contudo nós achamos que o Jackson é mais eficiente visto que suporta maneiras alternativas de processar JSON: _streaming_, modelo de árvore em memória, e a vinculação tradicional JSON-POJO. Mantenha em mente, contudo, que o Jackson é uma biblioteca maior do que Gson, assim, dependendo do seu caso, pode preferir Gson para evitar a limitação dos 65 mil métodos. Outras alternativas: [Json-smart](https://code.google.com/p/json-smart/) e [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)\n\n**Trabalhos em rede, armazenamento em cache e imagens.** Há um par de soluções testadas exaustivamente no dia-a-dia para a realização de requisições para servidores, que você deverá utilizar antes de considerar implementar o seu próprio cliente. Use o [Volley](https://android.googlesource.com/platform/frameworks/volley) ou o [Retrofit](http://square.github.io/retrofit/). O Volley também fornece ajudantes para carregar e fazer o _cache_ de imagens. Se escolher o Retrofit, considere o [Picasso](http://square.github.io/picasso/) para carregar e fazer o _caching_ de imagens, e [OkHttp](http://square.github.io/okhttp/) para requisições eficientes de HTTP. Todos os três, Retrofit, Picasso e OkHttp foram criados pela mesma empresa, portanto eles complementam-se muito bem. [OkHttp pode também ser utilizado em conexão com o Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n\n**RxJava** é uma biblioteca para Reactive Programming, por outras palavras, manipulação de eventos assíncronos. É um paradigma poderoso e promissor, o que pode tornar-se confuso devido ao fato de ser tão diferente. Recomendamos que tenha cuidado antes de usar esta biblioteca para arquitetar toda a sua aplicação. Há alguns projetos feitos por nós usando RxJava, se precisar de ajuda fale com uma destas pessoas:  Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. Escrevemos também algumas postagens no blogue sobre ele: [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\nSe você não tiver qualquer experiência com Rx, comece por aplicá-lo apenas nas respostas da API. Alternativamente, comece aplicando-o para a simples manipulação de eventos UI, como eventos de clique ou eventos de digitação num campo de pesquisa. Se você está confiante nas capacidades de Rx e quer aplicá-lo em toda a arquitetura, então, escreva os Javadocs em todas as partes mais difíceis. Mantenha em mente que outro programador que não esteja familiarizado com o RxJava pode ter dificuldades em manter o projeto. Faça o seu melhor para ajudá-los a compreender o seu código e também Rx.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)** é uma biblioteca em Java que permite o uso de expressões lambda em Android ou outras plataformas antes da JDK8. Ajuda a manter o código limpo e legível, especialmente se usa um estilo de programação funcional como pode exemplo o RxJava. Para o usar, instale a JDK8, defina-a como a sua localização SDK na janela da estrutura do projeto no Android Studio, defina as variáveis de ambiente `JAVA8_HOME` e `JAVA7_HOME`, e no ficheiro build.gradle que se encontra na raiz do projeto:\n\n```groovy\ndependencies {\n    classpath 'me.tatarka:gradle-retrolambda:2.4.1'\n}\n```\n\ne no ficheiro build.gradle de cada módulo, coloque\n\n```groovy\napply plugin: 'retrolambda'\n\nandroid {\n    compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n}\n\nretrolambda {\n    jdk System.getenv(\"JAVA8_HOME\")\n    oldJdk System.getenv(\"JAVA7_HOME\")\n    javaVersion JavaVersion.VERSION_1_7\n}\n```\n\nApós fazer isso, o Android Studio irá proporcionar suporte ao código que escreve para lambdas Java8. Se é novo no mundo dos lambdas, use o seguinte para começar:\n\n- Qualquer interface com apenas um método é \"amiga dos lambdas\" e pode ser compressa na sintaxe mais compacta proporcionada pelos lambdas;\n- Se está na dúvida sobre parâmetros e isso, escreva uma classe interna anónima normal e deixe o Android Studio a comprimir num lambda automaticamente.\n\n**Esteja atento à limitação do número de métodos dex, e evite usar demasiadas bibliotecas.** As aplicações de Android, quando organizadas como um arquivo dex, têm um limite de 65536 métodos aos quais se podem fazer referências [[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). Durante a compilação irá encontrar um erro fatal se passar esse limite. Por essa razão, use o número mínimo de bibliotecas, e use a ferramenta [dex-method-counts](https://github.com/mihaip/dex-method-counts) para encontrar que bibliotecas usar para ficar abaixo desse limite. Especialmente evite usar a biblioteca Guava, visto que contém mais de 13 mil métodos.\n\n### Atividades e Fragmentos\n\nNão há um consenso dentro da comunidade nem entre os programadores da Futurice como melhor organizar a arquitetura do Android com Fragmentos e Atividades. O Square até tem\n[uma biblioteca para construir uma arquitetura maioritariamente com Views](https://github.com/square/mortar), descartando a necessidade de Fragmentos, contudo isso ainda não é considerado uma boa prática dentro da comunidade.\n\nDevido à história das APIs Android, pode de forma ligeira considerar Fragmentos como peças de UI no ecrã. Por outras palavras, Fragmentos estão normalmente relacionados com UI. Atividades podem ser ligeiramente consideradas controladores, eles são especialmente importantes devido ao seu ciclo de vida e para gerir estados. Contudo, não se surpreenda se vir variações nestes papéis: atividades podem tomar papéis na UI ([fazendo transições entre ecrãs](https://developer.android.com/about/versions/lollipop.html)), e [fragmentos podem ser usados apenas como controladores](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). Sugerimos que navegue com cuidado, tomando decisões informadas visto que há contrapartidas ao uso de arquiteturas apenas com fragmentos, ou apenas com atividades, ou apenas com views. Seguem alguns conselhos do que ter mais cuidado, mas leve-os com uma pitada de sal:\n\n- Evite usar [fragmentos dentro de fragmentos](https://developer.android.com/about/versions/android-4.2.html#NestedFragments) em excesso, porque [matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/) podem ocorrer. Use fragmentos dentro de fragmentos apenas quando isso faz sentido (por exemplo, fragmentos num ViewPager que desliza horizontalmente dentro de um fragmento tipo ecrã) ou se é uma decisão bem informada.\n\n- Evite colocar demasiado código dentro das atividades. Sempre que possível, mantenha-as como contentores de peso leve, existindo primariamente na sua aplicação pelo ciclo de vida e outras interfaces importantes da API do Android. Dê preferência a atividades com apenas um fragmento ao invés de apenas atividades - coloque o seu código UI no fragmento da atividade. Isto irá fazer com que o código seja reutilizável no caso de por exemplo o querer modificar e colocar dentro de uma tabbed layout, ou num ecrã de tablete com múltiplos fragmentos. Evite ter uma atividade sem um fragmento correspondente, a não se que saiba o que está a fazer.\n\n- Não abuse das APIs do Android, como pode exemplo colocar demasiado peso nos Intent para o funcionamento interno da sua aplicação. Isso pode afetar o sistema operativo do Android e outras aplicações, criando bugs ou lag. Por exemplo, é um fato que se utilizar Intents para a comunicação interna na sua aplicação entre os packages, poderá fazer com que exista um lag de alguns segundos na experiência do utilizador se a app foi aberta depois do sistema operativo tiver sido iniciado.\n\n### Arquitetura dos pacotes de Java\n\nA arquitetura do Java para aplicações Android pode ser mais ou menos aproximada ao modelo [Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). No Android, [Fragmentos e Atividades são na verdade classes de controlo](http://www.informit.com/articles/article.aspx?p=2126865). Por outro lado, elas são parte explícita da interface do utilizador, portanto são também views.\n\nPor este motivo, é difícil classificar fragmentos (ou atividades) como restritamente controladores ou views. É melhor as deixa ficar no seu próprio pacote `fragments`. Atividades podem ficar no pacote mais algo desde que sigam os conselhos da secção anterior. Se está a planear ter mais do que 2 ou 3 atividades, então crie também um pacote `activities`.\n\nCaso contrário, a arquitetura pode ser semelhante ao típico MVS, com um pacote `models` contendo POJOs que serão populados através de JSON parser com respostas à API, e um pacote `views` contendo as Views criadas por si, notificações, views da action bar, widgets, etc. Adapters são uma matéria cinzenta, estando entre os dados e as views. Contudo, eles tipicamente precisam de exportar alguma View através do `getView()`, portanto poderá incluir o sub-pacote `adapters` dentro de `views`.\n\nAlgumas classes de controladores são para toda a aplicação e perto do sistema Android. Estas podem estar no pacote `managers`. Classes de processamento de dados várias, como \"DateUtils\", ficam dentro do pacote `utils`. Classes têm a responsabilidade de interagir com o servidor ficam no pacote `network`.\n\nNo final de contas, organizadas do mais perto do servidor para o mais perto do utilizador:\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n### Recursos\n\n**Dar o nome.** Siga a convenção de colocar o prefixo como tipo, por exemplo `type_foo_bar.xml`. Exemplos:  `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**Organizar os layout XMLs.** Se não tem a certeza de como formatar o layout XML, as seguintes convenções podem ajudar:\n\n- Um atributo por linha, indentação de 4 espaços\n- `android:id` sempre como o primeiro atributo\n- `android:layout_****` atributo no topo\n- `style` atributo no fundo\n- A Tag de fechar `/>` na sua própria linha, para facilitar a ordenação e adicionar novos atributos.\n- Ao invés de colocar o texto diretamente em `android:text`, considere usar os [atributos designtime](http://tools.android.com/tips/layout-designtime-attributes) disponíveis para Android Studio.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\nRegra geral, atributos `android:layout_****` devem ser definidos no layout XML, ao passo que outros atributos `android:****` devem ficar num XML de estilo. Esta regra tem excepções, mas de forma geral funciona bem. A ideia é manter apenas o layout (posicionamento, margem, tamanho) e atributos de conteúdo nos ficheiros de layout, mantendo todos os detalhes de aparência (cores, espaçamento, tipo de letra) em ficheiros de estilo.\n\nAs excepções são:\n\n- `android:id` deverá ficar obviamente no ficheiro de layout\n- `android:orientation` para um `LinearLayout` normalmente faz mais sentido num ficheiro de layout\n- `android:text` deverá ficar no ficheiro de layout porque ele define conteúdo\n- Por vezes irá fazer sentido definir um estilo genérico `android:layout_width` e `android:layout_height` mas por definição estes deverão aparecer no ficheiro de layout\n\n**Use estilos.** Quase todos os projeto precisam de usar estilos de forma adequada, isto porque é muito comum ter de repetir a aparência de uma view. No mínimo deverá ter um estilo comum para a maioria do conteúdo de texto na sua aplicação, por exemplo:\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize>@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nAplicado às TextViews:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\nProvavelmente irá ter de fazer o mesmo para botões, mas não pare já por aqui. Vá mais além e mova um grupo de atributos `android:****` que estejam relacionados e sejam repetidos para um estilo comum.\n\n**Divida um ficheiro de estilo grande em outros ficheiros.** Não precisa de ter apenas um ficheiro `styles.xml`. A Android SDK suporta outros ficheiros, e não há nada de mágico acerca do nome `styles`, o que importa são as tags de XML `<style>` dentro do ficheiro. Assim poderá ter os ficheiros `styles.xml`, `styles_home.xml`, `styles_item_details.xml`, `styles_forms.xml`. Ao contrário dos nomes dos diretório de recursos que têm algum significado para o sistema de compilação, nomes de ficheiros dentro de `res/values` podem ser arbitrários. \n\n**`colors.xml` é uma palete de cores.** Não deverá existir mais nada no seu `colors.xml` do que apenas um mapeamento do nome da cor a um valor RGBA. Não o use para definir valores RGBA para diferentes tipos de botões.\n\n*Não faça isto:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\nPode facilmente começar a repetir valores RGBA desta forma, e isso faz com que seja mais difícil alterar uma cor básica se isso for necessário. Além disso, essas definições estão relacionadas a algum contexto, como pode exemplo \"button\" ou \"comment\", e devem ficar no estilo do botão, não em `colors.xml`.\n\nAo invés, faça isto:\n\n```xml\n<resources>\n\n    <!-- grayscale -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- basic colors -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\nPeça esta palete ao designer da aplicação. Os nomes não precisam de ser nomes de cores como \"green\", \"blue\", etc. Nomes como \"brand_primary\", \"brand_secondary\", \"brand_negative\" são também totalmente aceites. Formatar as cores desta forma irá fazer com que as alterar ou fazer a refatorização de cores seja mais fácil, e também irá mostrar de forma explícita as diferentes cores que estão a ser utilizadas. Normalmente para um UI com bom aspeto, é importante reduzir a variedade das cores que estão a ser utilizadas.\n\n**Trate o dimens.xml como o colors.xml.** Deverá também definir uma \"palete\" de espaçamentos e tamanhos de letra típicos, devido basicamente às mesmas razões que para as cores. Um bom exemplo de um ficheiro dimens:\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\nNas margens e espaçamentos deverá usar as dimensões `spacing_****` para o layout, ao invés de colocar valores fixos, da mesma forma que o strings são tratados. Isto irá dar um look-and-feel consistente, ao mesmo tempo que irá fazer com que seja mais fácil organizar e modificar estilos e layouts.\n\n**strings.xml**\n\nDê o nome aos strings com keys que fazem lembrar namespaces, e não tenha receio de repetir um valor para duas ou mais keys. Linguagens são complexas, portanto namespaces são necessários para trazer contexto e quebrar ambiguidade.\n\n**Ruim*\n```xml\n<string name=\"network_error\">Erro de rede</string>\n<string name=\"call_failed\">Pedido falhou</string>\n<string name=\"map_failed\">Carregamento do mapa falhou</string>\n```\n\n**Bom**\n```xml\n<string name=\"error.message.network\">Erro de rede</string>\n<string name=\"error.message.call\">Pedido falhou</string>\n<string name=\"error.message.map\">Carregamento do mapa falhou</string>\n```\n\nNão escreva os valores do strings em letras maiúsculas. Mantenha-se dentro das convenções normais de texto (exemplo: coloque o primeiro caráter em letras maiúscula). Se precisa de mostrar o string em letras maiúsculas, então use por exemplo o atributo [`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) na própria TextView.\n\n**Ruim**\n```xml\n<string name=\"error.message.call\">PEDIDO FALHOU</string>\n```\n\n**Bom**\n```xml\n<string name=\"error.message.call\">Pedido falhou</string>\n```\n\n**Evite uma hierarquia muito profunda de views.** Por vezes poderá ser tentado a adicionar apenas mais uma LinearLayout, para conseguir organizar as suas views. Este tipo de situação pode ocorrer:\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nMesmo que não veja isso explicitamente num ficheiro de layout, poderá na mesma acontecer se está a inflando (em Java) views noutras views.\n\nUm par de problemas pode ocorrer. Poderá experimentar problemas de performance, porque há uma árvore complexa de UI que o processador precisa de gerir. Outro problema mais sério é a possibilidade de [StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views).\n\nPor isso, tente manter a hierarquia das views tão lisa quanto possível: aprenda como usar [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html), como [optimizar os seus layouts](http://developer.android.com/training/improving-layouts/optimizing-layout.html) e como usar a [tag `<merge>`](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts).\n\n**Esteja atento a problemas relacionados com WebViews.** Quando tem de mostrar uma página web, por exemplo para uma notícia, evite usar o processamento no cliente para limpar o HTML, ao invés, peça um HTML \"*puro*\" aos programadores do servidor. [WebViews também podem vazar memória](http://stackoverflow.com/questions/3130654/memory-leak-in-webview) quando mantêm uma referência à sua Activity, ao invés de conetada ao ApplicationContext. Evite usar uma WebView para textos ou botões simples, dê preferência às TextViews ou Buttons.\n\n### Frameworks para testes\n\nAs frameworks de teste do Android SDK ainda estão na sua infância, especialmente no que toca aos testes UI. O Android Gradle currentemente implementa uma tarefa de teste chamada [`connectedAndroidTest`](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing), a qual corre testes JUnit criados por si, usando uma extensão de JUnit com ajudantes para Android](http://developer.android.com/reference/android/test/package-summary.html). Isto significa que irá ter de correr os testes conectado a um aparelho, ou um simulador. Siga o guia oficial [[1]](http://developer.android.com/tools/testing/testing_android.html) [[2]](http://developer.android.com/tools/testing/activity_test.html) para testar\n\n**Use [Robolectric](http://robolectric.org/) apenas para os testes unitários, não para as views.**\nÉ uma framework de teste que procura testar de forma \"desconectada de um aparelho\" para melhorar a velocidade, desenhado especialmente para os testes unitários aos modelos e _view models_. Contudo, testar sobe o Robolectric é pouco fiável e incompleto no que toca a testes UI. Irá ter problemas a testar elementos UI relacionados com animações, janelas de diálogo, etc., e isto irá ainda ficar mais complicado porque está a \"caminhar no escuro\" (testando sem ver o ecrã que está a ser controlado).\n\n**[Robotium](https://code.google.com/p/robotium/) faz com que escrever testes UI seja fácil.** Não precisa do Robotium para correr testes conectados em casos de UI, mas irá provavelmente ser benéfico para si porque ele tem muitos ajudantes para obter e analisar as views, e controlar o ecrã. Casos de teste irão ser tão simples como:\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // searches for the first occurence of \"More\" and clicks on it\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n### Emuladores\n\nA performance do emulador do Android SDK, particularmente a de arquitetura x86, tem melhorado significantemente nos últimos anos e hoje é a mais adequada para a maioria das tarefas de desenvolvimento do dia-a-dia. Contudo, você não deve desconsiderar que sua aplicação vai funcionar realmente em dispositivos reais. Claro, testar todos os possíveis dispositivos não é nada prático ou produtivo, ou seja, foque os seus esforços nos dispositivos que tenham uma grande fatia de mercado e os que sejam mais relevantes para a aplicação que está sendo desenvolvida no momento.\n\n### Configurações Proguard\n\n[ProGuard](http://proguard.sourceforge.net/) é normalmente usado em projetos Android para diminuir ou ofuscar o código empacotado.\n\nQuer esteja a usar o ProGuard que não depende da configuração do seu projeto. Frequentemente irá configurar o gradle para usar ProGuard quando compilando a apk de lançamento.\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\nDe maneira a determinar que partes do código têm de ser preservadas e quais podem ser descartadas ou ofuscadas, terá de especificar um ou mais pontos de entrada para o seu código. Estes pontes de entrada são normalmente classes com main métodos, applets, midlets, atividades, etc.\nA framework Android usa uma configuração padrão que pode ser encontrada em `SDK_HOME/tools/proguard/proguard-android.txt`. Usando a configuração acima, regras ProGuard específicas para o projeto, definidas em `my-project/app/proguard-rules.pro`, serão anexadas à configuração padrão.\n\nUm problema comum relacionado com o ProGuard é verificar se a aplicação tem um crash ao iniciar com `ClassNotFoundException` ou `NoSuchFieldException` ou similar, mesmo que o comando de compilação (i.e. `assembleRelease`) seja bem sucedido sem qualquer aviso.\n\nIsto significa uma de duas coisas:\n\n1. ProGuard removou a classe, enum, método, nome do campo ou anotação, considerando que esta não era necessária.\n2. ProGuard ofuscou (deu outro nome) à classe, enum ou nome do campo, mas continua a ser usada indiretamente pelo seu nome original, i.e. através da reflexão do Java.\n\nVerifique `app/build/outputs/proguard/release/usage.txt` para ver se o objeto em questão foi removido.\nVerifique `app/build/outputs/proguard/release/mapping.txt` para ver se o objeto em questão foi ofuscado.\n\nDe maneira a prevenir o ProGuard de *remover* classes ou membros da classe que sejam necessários, adicione a opção `keep` à sua configuração do ProGuard:\n\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nDe maneira a prevenir o ProGuard de *ofuscar* classes ou membros da classe, adicione `keepnames` \n\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\nLeia mais em [Proguard](http://proguard.sourceforge.net/#manual/examples.html) para exemplos.\n\n**Cedo no projeto, faça uma compilação de lançamento** para verificar se as regras do ProGuard estão a manter corretamente o que é importante. Além disso, sempre que inclua bibliotecas novas, faça uma compilação de lançamento e teste a apk num aparelho. Não espera até a sua aplicação estar finalmente na versão \"1.0\" para fazer a compilação de lançamento, poderá encontrar algumas surpresas desagradáveis e pouco tempo para as resolver.\n\n**Dica.** Guarde o ficheiro `mapping.txt` por cada lançamento que publique para os seus utilizadores. Ao guardar uma cópia do ficheiro `mapping.txt` por cada compilação de lançamento, assegura-se de que poderá fazer o debug de um problema se o utilizador encontrar um bug e submeter um stack trace ofuscado.\n\n**DexGuard**. Se necessita de ferramentas hard-core para optimizar, e especialmente ofuscar código de lançamento, considere o [DexGuard](http://www.saikoa.com/dexguard), um software comercial feito pela mesma equipa do ProGuard. Também poderá dividir ficheiros Dex para resolver o problema da limitação dos 65 mil métodos.\n\n### Armazenamento de dados\n\n#### SharedPreferences\n\nSe precisa de persistir apenas flags simples e a sua aplicação corre em apenas um processo, SharedPreferences é muito provavelmente suficiente para si. É uma boa opção padrão.\n\nHá duas razões que o podem levar a não querer usar SharedPreferences:\n\n* *Performance*: Os seus dados são complexos ou simplesmente há muitos dados a serem guardados\n* *Vários processos querendo aceder aos dados*: Você tem widgets ou serviços remotos que são executados em seus próprios processos e exigem dados sincronizados\n\n#### ContentProviders\n\nNo caso de que as SharedPreferences não são suficientes para si, deverá usar \no padrão da plataforma ContentProviders, que são rápidos e seguros no uso de processos.\n\nO único problema com ContentProviders é a quantidade de código boilerplate que é necessário para configurá-los, bem como tutoriais de baixa qualidade. É possível, contudo, gerar ContentProvider utilizando bibliotecas como [Schematic](https://github.com/SimonVT/schematic), que reduz significativamente o esforço.\n\n\nVocê ainda precisa escrever algum código de parsing você mesmo para ler os objetos de dados das colunas do SQLite e vice-versa. É possível serializar os objetos de dados, por exemplo, com Gson, e fazer persistir apenas a string resultante. Desta forma, você perde em performance, mas por outro lado não precisa de declarar uma coluna para cada um dos campos da classe de dados.\n\n#### Usando um ORM\n\nNós geralmente não recomendamos o uso de uma biblioteca de Object-Relation Mapping, a não ser que tenha dados invulgarmente complexos e uma necessidade extrema. Eles tendem a ser complexos e necessitam de tempo para aprender. Se decidir avançar com um ORM deverá prestar atenção para saber se é ou não é _seguro em processos_ se a sua aplicação o exige, visto que muitas das soluções ORM existentes neste momento surpreendentemente não o são.\n\n### Obrigado a\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton e outros programadores da Futurice por partilharem o seu conhecimento em desenvolvimento Android.\n\n### License\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n"
  },
  {
    "path": "translations/Russian/README.ru.md",
    "content": "# Лучшие практики в Android разработке\n\nУроки от лучших Android-разработчиков из команды Futurice. Не нужно изобретать велосипед, просто следуйте правилам в руководстве. Если вы интересуетесь разработкой для IOS или Windows Phone, обратите внимание на [**iOS Good Practices**](https://github.com/futurice/ios-good-practices) и [**Windows App Development Best Practices**](https://github.com/futurice/windows-app-development-best-practices).\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n[![Spice Program Sponsored](https://img.shields.io/badge/chilicorn-sponsored-brightgreen.svg?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAPCAMAAADjyg5GAAABqlBMVEUAAAAzmTM3pEn%2FSTGhVSY4ZD43STdOXk5lSGAyhz41iz8xkz2HUCWFFhTFFRUzZDvbIB00Zzoyfj9zlHY0ZzmMfY0ydT0zjj92l3qjeR3dNSkoZp4ykEAzjT8ylUBlgj0yiT0ymECkwKjWqAyjuqcghpUykD%2BUQCKoQyAHb%2BgylkAyl0EynkEzmkA0mUA3mj86oUg7oUo8n0k%2FS%2Bw%2Fo0xBnE5BpU9Br0ZKo1ZLmFZOjEhesGljuzllqW50tH14aS14qm17mX9%2Bx4GAgUCEx02JySqOvpSXvI%2BYvp2orqmpzeGrQh%2Bsr6yssa2ttK6v0bKxMBy01bm4zLu5yry7yb29x77BzMPCxsLEzMXFxsXGx8fI3PLJ08vKysrKy8rL2s3MzczOH8LR0dHW19bX19fZ2dna2trc3Nzd3d3d3t3f39%2FgtZTg4ODi4uLj4%2BPlGxLl5eXm5ubnRzPn5%2Bfo6Ojp6enqfmzq6urr6%2Bvt7e3t7u3uDwvugwbu7u7v6Obv8fDz8%2FP09PT2igP29vb4%2BPj6y376%2Bu%2F7%2Bfv9%2Ff39%2Fv3%2BkAH%2FAwf%2FtwD%2F9wCyh1KfAAAAKXRSTlMABQ4VGykqLjVCTVNgdXuHj5Kaq62vt77ExNPX2%2Bju8vX6%2Bvr7%2FP7%2B%2FiiUMfUAAADTSURBVAjXBcFRTsIwHAfgX%2FtvOyjdYDUsRkFjTIwkPvjiOTyX9%2FAIJt7BF570BopEdHOOstHS%2BX0s439RGwnfuB5gSFOZAgDqjQOBivtGkCc7j%2B2e8XNzefWSu%2BsZUD1QfoTq0y6mZsUSvIkRoGYnHu6Yc63pDCjiSNE2kYLdCUAWVmK4zsxzO%2BQQFxNs5b479NHXopkbWX9U3PAwWAVSY%2FpZf1udQ7rfUpQ1CzurDPpwo16Ff2cMWjuFHX9qCV0Y0Ok4Jvh63IABUNnktl%2B6sgP%2BARIxSrT%2FMhLlAAAAAElFTkSuQmCC)](https://spiceprogram.org/)\n\n## Cодержание\n\n#### [Используйте Gradle и рекомендованную им структуру проекта](#build-system)\n#### [Храните пароли и важные данные в файле gradle.properties](#gradle-configuration)\n#### [Используйте библиотеку Jackson для парсинга JSON данных](#libraries)\n#### [Не пишите свой HTTP клиент, используйте библиотеки Volley или OkHttp](#networklibs)\n#### [Не нужно использовать Guava и большое количество библиотек чтобы не привысить лимит методов (65k)](#methodlimitation)\n#### [Используйте фрагменты для отображения пользовательского интерфейса](#activities-and-fragments)\n#### [Используйте activity только для управления фрагментами](#activities-and-fragments)\n#### [XML-разметка — это код, который нужно писать аккуратно](#resources)\n#### [Чтобы не дублировать атрибуты в XML-разметке, используйте стили](#styles)\n#### [Используйте несколько файлов со стилями, не нужно создавать один огромный файл](#splitstyles)\n#### [Сделайте файл colors.xml компактным. Не дублируйте цвета, задайте основную палитру](#colorsxml)\n#### [То же касается и dimens.xml, задайте только основные константы](#dimensxml)\n#### [Избегайте слишком глубокой иерархии элементов ViewGroup](#deephierarchy)\n#### [Не нужно обрабатывать WebView на клиентской стороне, будьте внимательны к возможным утечкам](#webviews)\n#### [Используйте Robolectric для unit-тестов, а Robotium для UI-тестов](#test-frameworks)\n#### [Используйте Genymotion в качестве эмулятора](#emulators)\n#### [Всегда используйте ProGuard или DexGuard](#proguard-configuration)\n#### [Для простого хранения данных используйте SharedPreferences, для сложной структуры данных - ContentProvider](#data-storage)\n#### [Используйте Stetho для отладки приложения](#use-stetho)\n#### [Используйте Leak Canary для поиска утечек памяти](#use-leakcanary)\n#### [Используйте CI](#use-continuous-integration-1)\n\n\n----------\n\n### Android SDK\n\nРазместите [Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools) в домашней дирректории или другом месте, не связанном с приложением. Некоторые IDE включают в себя SDK при установке и могут размещать его в своей дирректории. Это не совсем правильно, так как в дальнейшем вам может понадобиться обновить, переустановить или сменить IDE. Не размещайте SDK в системные папки, так как для доступа к ним может понадобиться ипользование команды sudo, если вы вошли в систему как обычный пользователь.\n\n\n### Система сборки\n<a name=\"build-system\"></a>\nИспользуйте [Gradle](http://tools.android.com/tech-docs/new-build-system) по умолчанию. У Ant меньше возможностей и его код менее компактный. Используя Gradle, вы сможете:\n\n- Создавать различные сборки и варианты приложения\n- Создавать простые задачи в виде скрипта\n- Управлять и загружать зависимости\n- Настраивать хранилище ключей\n- И многое другое\n\nПлагин Gradle находится в активной разработке командой Google и уже стал основной системой сборки для Android\n\n\n### Структура проекта\n\nСуществует два варианта структуры проекта: старый Ant + Eclipse ADT и новый Gradle + Android Studio. Лучше использовать второй вариант. Если ваш проект все еще использует старую структуру, рекомендуем портировать проект.\n\nСтарая структура:\n\n```\nold-structure\n├─ assets\n├─ libs\n├─ res\n├─ src\n│  └─ com/futurice/project\n├─ AndroidManifest.xml\n├─ build.gradle\n├─ project.properties\n└─ proguard-rules.pro\n```\n\nНовая структура:\n\n```\nnew-structure\n├─ library-foobar\n├─ app\n│  ├─ libs\n│  ├─ src\n│  │  ├─ androidTest\n│  │  │  └─ java\n│  │  │     └─ com/futurice/project\n│  │  └─ main\n│  │     ├─ java\n│  │     │  └─ com/futurice/project\n│  │     ├─ res\n│  │     └─ AndroidManifest.xml\n│  ├─ build.gradle\n│  └─ proguard-rules.pro\n├─ build.gradle\n└─ settings.gradle\n```\n\nГлавным отличием является то, что новая структура явно разделяет 'наборы ресурсов' (`main`, `androidTest`), используя одну из концепций Gradle. Например, вы можете добавить папки 'paid' и 'free' в вашу папку `src`, в которых будет отдельный исходный код для платной и бесплатной версий приложения.\n\nНаличие папки `app` в верхнем уровне иерархии помогает отделить ваше приложение от библиотек (например, `library-foobar`), которые в нем используются. В таком случае файл `settings.gradle` хранит проекты, на которые может ссылаться `app/build.gradle`.\n\n\n### Конфигурация Gradle\n<a name=\"gradle-configuration\"></a>\n**Общая структура.** Следуйте [Рекомендациям Google для Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)\n\n**Маленькие задачи.** Вместо скриптов на shell, Python, Perl, вы можете создавать задачи в Gradle. Подробне в документации [Документация Gradle](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF).\n\n**Пароли.** В файле `build.gradle` вашего приложения необходимо задать `signingConfigs` для релизной сборки. Here is what you should avoid:\n\n_Не делайте так_. Эта информаци появится в системе контроля версий.\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nВместо этого, создайте файл `gradle.properties`, который _не_ будет добавлен в систему контроля версий:\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nGradle автоматически импортирует этот файл, по этому вы можете использовать его в `build.gradle`:\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**Старайтесь использовать зависимости Maven вместо импортирования jar-файлов.** Если вы явно включаете jar файл в ваш проект, его версия будет неизменна, например `2.1.1`. Скачивать и обновлять зависимости это непростая задача, которую Maven с легкостью решает, что также приветствуется в сборках Android Gradle. Например:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp:2.2.0'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'\n}\n```\n\n**Избегайте использования динамических зависимостей Maven**\nНе нужно использовать динамические версии, такие как `2.1.+` так как это может привести к нарушению стабильности сборки, а также непредсказуемым различиям между разными сборками. Использование статических версий как  `2.1.1` помогает создать более стабильную и предсказуемую среду разработки.\n\n**Используйте разные имена пакетов для debug и relese типов**\nИспользуйте `applicationIdSuffix` для *debug* [типа приложения](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types) для того, чтобы была возможность устанавливать *debug* и *release* типы приложения на одном устройстве (это можно также делать и для кастомных типов приложения). Это особенно важно на более поздних стадиях, когда ваше приложение будет опубликовано в магазине.\n\n```groovy\nandroid {\n    buildTypes {\n        debug {\n            applicationIdSuffix '.debug'\n            versionNameSuffix '-DEBUG'\n        }\n\n        release {\n            // ...\n        }\n    }\n}\n```\nИспользуйте разные иконки чтобы различать типы приложения, установленного на уствойство - например используя другой цвет для значка *debug* типа. Gradle значительно упрощает задачу: при использовании стандартной структуры проекта, просто поместите иконку для типа *debug* в `app/src/debug/res`, а для типа *release* - в `app/src/release/res`.\nВы также можете [изменить название приложения](http://stackoverflow.com/questions/24785270/how-to-change-app-name-per-gradle-build-type) в зависимости от типа приложения и имя версии `versionName` (как показано выше).\n\n\n### Среда разработки (IDE) и текстовые редакторы\n\n**Искользуйте любой редактор, который удобно отображает структуру проекта.** Текстовый редактор это дело вкуса, так или иначе вам нужно будет настроить его в соответствии со структурой проекта и системой сборки.\n\nНа данный момент рекомендуемая IDE - [Android Studio](https://developer.android.com/sdk/installing/studio.html), разработанная командой Google, она лучше других сочитается с Gradle, использует новую структуру проекта по умолчанию, уже в стабильной сборке и создана непосредственно для Android разработки.\n\nВы всё ещё можете использовать [Eclipse ADT](https://developer.android.com/sdk/installing/index.html?pkg=adt), но вам придется настроить его, так как там используется старая структура проекта и система сборки Ant. Теперь Google настоятельно рекомендует использовать Android Studio вместо Eclipse:\n\n> Важно: Поддержка Android Developer Tools (ADT) в Eclipse закончилась, об этом сказано в [объявлении](http://android-developers.blogspot.fi/2015/06/an-update-on-eclipse-android-developer.html).\nВам следует перенести проекты в Android Studio как можно быстрее. Чтобы узнать больше о переносе проекта в Android Studio, смотрите [Миграция из Eclipse ADT](http://developer.android.com/sdk/installing/migrate.html).\n\nВы даже можете использовать простые редакторы как Vim, Sublime Text, или Emacs. В этом случае вам понадобится Gradle и команда `adb`. Если у вас не получается интегрировать Gradle в Eclipse, для сборки можно использовать командную строку, или начать использовать Android Studio. Это лучший вариант, учитывая что плагин ADT устарел.\n\nЧто бы вы не использовали, главное убедиться что Gradle и структура проекта следуют официальным инструкциям, и не добавлять в систему контроля версий специфические для редактора файлы. Например, не добавляйте файл `build.xml`. Особенно внимательно следите за обновлениями файла `build.gradle` если вы меняете настройки сборки в Ant. Будьте доброжелательными по отношению к другим разработчикам и не заставляйте их использовать непривычные инструменты.\n\n\n### Библиотеки\n<a name=\"libraries\"></a>\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** это Java-библиотека для конвертации объектов в JSON обратно. [Gson](https://code.google.com/p/google-gson/) так же хорошее решение этой задачи, но мы обнаружили что у Jackson выше производительность, так как он поддерживает альтернативные способы обработки JSON: стриминг, модель дерева памяти, и традиционную связку JSON-POJO. Но имейте в виду что Jackson больше чем GSON, по этому, в зависимости от ситуации, вам нужно будет использовать GSON чтобы не привысить лимит в 65k методов. Альтернативные библиотеки: [Json-smart](https://code.google.com/p/json-smart/) и [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)\n\n<a name=\"networklibs\"></a>\n**Сеть, кеширование и изображения.** Существует несколько проверенных временем библиотек для создания запросов к backend-серверам, которые следует использовать вместо создания собственного клиента. Используйте [Volley](https://android.googlesource.com/platform/frameworks/volley) или [Retrofit](http://square.github.io/retrofit/). Volley также поддерживает кеширование и загрузку изображений. Если вы предпочитаете Retrofit, используйте [Picasso](http://square.github.io/picasso/) для загрузки и кеширования картинок, и [OkHttp](http://square.github.io/okhttp/) для эффективных HTTP запросов. Все три библиотеки (Retrofit, Picasso и OkHttp) созданы одной компанией, поэтому они неплохо дополняют друг друга. [OkHttp так же может быть использован в сочитании с Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n\n**RxJava** - библиотека для Reactive Programming, другими словами, для обработки асинхронных событий. Это очень мощная и многообещающая концепция, которая сначала может смутить своей необычностью. Мы рекомендуем подумать, перед тем как использовать эту библиотеку как фундамент архитектуры вашего приложения. Существуют проекты, созданные с использованием RxJava, и вы можете обратиться за помощью в использовании RxJava к однуму из этих людей: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. Мы написали несколько статей на эту тему:\n[[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\nЕсли у вас нет опыта работы с Rx, то начните с использования API. Или вы можете начать с обработки простых событий пользовательского интерфейса, таких как обработка кликов или ввод текста. Если вы уверены в ваших навыках использования Rx и хотите использовать его во всей архитектуре приложения, напишите Javadocs о самых сложных моментах. Помните, что у программиста, не имеющего опыта  виспользовании RxJava, могут быть большие проблемы при работе с проектом. Помогите понять ваш код и Rx.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)** - Java библиотека fдля использования Lambda-выражений в Android и других платформах с JDK ниже версии 8 . Это поможет сохранить компактность и читабельность кода особенно при использовании функционального стиля, например с RxJava. Для ее использования установите JDK8, выберите его как  SDK в настройках структуры проекта в Android Studio, и задайте переменные `JAVA8_HOME` и `JAVA7_HOME`, затем в корневом файле build.gradle:\n\n```groovy\ndependencies {\n    classpath 'me.tatarka:gradle-retrolambda:2.4.1'\n}\n```\n\nи в файлах build.gradle для каждого модуля:\n\n```groovy\napply plugin: 'retrolambda'\n\nandroid {\n    compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n}\n\nretrolambda {\n    jdk System.getenv(\"JAVA8_HOME\")\n    oldJdk System.getenv(\"JAVA7_HOME\")\n    javaVersion JavaVersion.VERSION_1_7\n}\n```\n\nAndroid Studio предлагает поддержку лямбда-синтаксиса Java8. Если у вас нет опыта работы с лямбдами, начните с этого:\n\n- Любой интерфейс с одним методом вполне совместим с лямбда-выражениями и может быть упрощён с их помошью\n- Если вам непонятно какие параметры использовать, напишите обычный внутренний класс и позвольте Android Studio преобразовать его в лямбда-выражение.\n\n<a name=\"methodlimitation\"></a>\n**Помните о лимите dex-файла на количество методов и избегайте его привышения.** Android приложения, запакованныe в dex файл, не могут привысить лимит в 65536 ссылочных методов [[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). При компиляции вы увидите соответствующую ошибку. Поэтому используйте ограниченное количество библиотек и утилиту [dex-method-counts](https://github.com/mihaip/dex-method-counts) для определения оптимального набора библиотек, не выходящего за лимит. Особенно избегайте библиотеки Guava, так как она содержит 13k методов.\n\n\n### Активности и Фрагменты\n<a name=\"activities-and-fragments\"></a>\nВ сообществе Android-разработчиков (как и в команде Futurice) нет единого мнения по поводу того, как лучше всего построить архитектуру Android-приложения используя фрагменты и активности. Square даже выпустила [библиотеку для построения архитектуры в основном с помощью View](https://github.com/square/mortar), минимизировав тем самым необходимость фрагментов, но этот способ до сих пор не стал общепринятым.\n\nИсходя из истории Android API, фрагменты можно рассматривать как часть пользовательского интерфейса экрана. Другими словами, фрагменты обычно являются частью UI. Activities обычно рассматриваются как контроллеры, которые особенно важны для управления состоянием и жизненным циклом. Однако, может быть иначе: activity могут исполнять функции, связанные с UI ([переходы между экранами](https://developer.android.com/about/versions/lollipop.html)), а  [фрагменты могут быть использованы только как контроллеры](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). Мы советуем принимать решение, имея в виду, что архитектура, которая строится только на фрагментах, только на activity или только на view, может иметь много недостатков. Вот пара советов по поводу того, на что нужно обратить внимание, но относитесь к этим советам критично:\n\n- Избегайте чрезмерного использования [вложенных фрагментов](https://developer.android.com/about/versions/android-4.2.html#NestedFragments), так как может появится побочный эффект [матрёшки](http://delyan.me/android-s-matryoshka-problem/). Используйте вложенные  фрагменты только тогда, когда в этом есть смысл (например, фрагменты в горизонтальной разметке ViewPager внутри фрагмента во весь экран) или если вы действительно знаете что делаете.\n- Избегайте чрезмерного кода в activity. По возможности, используйте их как контейнеры которые отвечают за жизненный цикл и другие важные элементы интерфейса Android API. Вместо того чтобы использовать activity, используйте activity с фрагментом и вынесите код, отвечающий за UI внутрь фрагмента. Это сделает возможным повторное использование фрагмента если вам потребуется поместить его в разметку с во вкладки (tabbed layout), или на экран планшета с несколькими фрагментами. Избегайте создания activity без фрагментов, кроме случаев, когда вы делаете это с определенной целью.\n- Не стоит злоупотреблять Android API, например, полагаясь только на механизм Intent для внутренней работы приложения. Вы можете повлиять на работу операционной системы Android и других приложений, вызвав ошибки или зависания. Например, известно, что если ваше приложение использует механизм Intent для внутренней связи между пакетами приложения, оно может вызвать зависание в несколько секунд, если было открыто сразу после загрузки ОС.\n\n### Структура Java пакетов\n\nМы рекомендуем использовать *feature based* структуру пакетов для организации вашего кода. Это даст вам следующие приемущества:\n\n- Более четкая зависимость функций (фич) и границ интерфейсов.\n- Способствует инкапсуляции.\n- Легче понять компоненты, которые определяют эту функцию.\n- Снижает риск неосознанного изменения несвязанного или общего кода.\n- Упрощенная навигация: большинство связанных классов будут в одном пакете.\n- Легче удалить функцию.\n- Упрощает переход к структуре сборки на основе модулей (лучшее время сборки и поддержка Instant Apps)\n\nАльтернативный подход к определению ваших пакетов с помощью *how* функции создается (путем размещения связанных активностей, фрагментов, адаптеров и т. д. в отдельных пакетах) может привести к фрагментированной базе кода с меньшей гибкостью для реализации. Самое главное, это препятствует пониманию кодовой базы с точки зрения ее основной роли: предоставления функций для приложения.\n\n### Архитектура Java пакетов\n\nАрхитектура Java для приложения Android похожа на [Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). В Android, [Фрагмент и Activity являются контроллерами](http://www.informit.com/articles/article.aspx?p=2126865). С другой стороны, они также являются частью пользовательского интерфейса, следовательно они представляют собой еще и Views.\n\nПо этой причине сложно классифицировать фрагменты (или activities) как только Controller или  View. Лучше поместить их в отдельный пакет `fragments`. Activities могут оставаться в верхнем уровне пакета до тех пор пока вы следуете совету из предыдущей секции. Если вы планируете создать 2 или 3 activities, создайте отдельный пакет `activities`.\n\nВо всем остальном, архитектура выглядит как обычный MVC, с пакетом `models` содержащим объекты POJO, которые будут наполнены информацией при помощи JSON-парсинга ответов, полученных от API, и пакетом `views`,  содержащим кастомные Views, уведомления, action bar, виджеты, и т.д. Адапторы находятся где-то между data и views, связывая их между собой. Однако им нужно экспортировать View с помощью метода `getView()`, по этому можно поместить пакет `adapters` внутрь пакета `views`.\n\nНекоторые Controller-классы используются во всем приложении работая напрямую с системой Android.\nЭти классы могут находиться в пакете `managers`. Различные классы для обработки данных, такие как \"DateUtils\", должны быть в пакете `utils`, а классы, отвечающие за взаимодействие с сетью - в пакете `network`.\n\nПакеты сортируются в порядке от closest-to-backend до closest-to-the-user:\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n\n### Ресурсы\n<a name=\"resources\"></a>\n**Имена.** Следуйте конвенции и указывайте тип в начале названия, как `тип_файла_имя_файла.xml`. Примеры: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**Структура разметки XML.** Если вы не уверены как форматировать XML, вам могут помочь следующие правила:\n\n- Один атрибут на строку с отступом 4 пробела\n- `android:id` всегда указан как первый атрибут\n- `android:layout_****` указываются следом\n- `style` атрибуты указываются внизу\n- Закрывающий тег `/>`на отдельной линии, чтобы облегчить добавление и сортировку атрибутов.\n- Вместо ввода строк `android:text` вручную, используйте [Designtime атрибуты](http://tools.android.com/tips/layout-designtime-attributes), доступные в Android Studio.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\nКак правило, атрибут `android:layout_****` должен быть указан в XML-файлах разметки,в то время ак атрибуты `android:****` должны находиться в XML-файлах стилей. У этого правила есть исключения, но в целом оно работает. Идея в том чтобы держать разметку (позиционирование, отступы, размеры) и другие атрибуты контента в файах разметки, а все внешние детали элементов (цвета, оформление, шрифты) в файлах стилей.\n\nИсключения:\n\n- `android:id` должен находиться в файлах разметки\n- `android:orientation` для `LinearLayout` также более уместен в файлах разметки\n- `android:text` тоже размещать в файлах разметки так как он задает сам контент\n- Иногда имеет смысл определить `android:layout_width` и `android:layout_height` как стили, но по умолчанию они должны находиться в файлах разметки\n\n<a name=\"styles\"></a>\n**Используйте стили.** Практически каждый проект нуждается в использовании стилей, так как очень часть приходится использовать повторяющиеся элементы. По крайней мере у вас долджен быть отдельный файл стилей для основного текстового контента в приложении, например:\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nЭто применимо и к TextViews:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\nСкорее всего вы захотете сделать то же самое и для кнопок, но не нужно на этом останавливаться. Используйте этот принцип для группировки схожих или повторяющихся атрибутов `android:****` в отдельный файл стилей.\n\n<a name=\"splitstyles\"></a>\n**Разделите большой файл стилей на несколько маленьких.** Не нужно держать все стили в одном файле `styles.xml`. Android SDK поддержывает и другие файлы, нет ничего магического в названии файла `styles`, единственное что важно, это тег `<style>` внутри него. Следовательно, вы можете создать файлы `styles.xml`, `styles_home.xml`, `styles_item_details.xml`, `styles_forms.xml` и т.д. В отличие от имен папок с ресурсами, которые несут определенное значение для системы сборки, имена файлов в `res/values` могут быть произвольными.\n\n<a name=\"colorsxml\"></a>\n**Файл `colors.xml` - это палитра цветов.** В файле `colors.xml` не должно быть ничего другого кроме присвоения названиям цветов определенных значений RGBA. Не используйте его чтобы задавать параметры RGBA для разных типов кнопок.\n\n*Неправильный вариант файла colors.xml:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\nПри таком подходе очень легко создать повторные значения RGBA и на много сложнее менять цвета. Кроме того, эти цвета относятся к определённому контенту, как «button» или «comment», поэтому должны быть описаны в стиле кнопки, а не в файле `colors.xml`.\n\nПравильно файл colors.xml:\n\n```xml\n<resources>\n\n    <!-- grayscale -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- basic colors -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\nЦветовую палитру определяет дизайнер приложения. Не обязательно называть цвета «green», «blue», и т.д. Названия вроде «brand_primary», «brand_secondary», «brand_negative» вполне приемлемы. Такие названия цветов облегчают их рефакторинг, а также позволяют понять, сколько цветов используется. Для создания красивого UI, важно уменьшить количество используемых цветов, если это возможно.\n\n<a name=\"dimensxml\"></a>\n**Оформляйте dimens.xml как colors.xml.** Вам также потребуется создать что-то вроде \"палитры\" отступов и размеров, аналогично цветам в файле colors.xml. Пример хорошо оформленного файла dimens.xml:\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\nРекомендуется не писать числовые значения в атрибутах разметки (полях и отступах), а использовать константы вида `spacing_****` (по тому же принципу что и файлы для локализиции строковых значений).\nЭто делает разметку понятнее и облегчает ее рефакторинг.\n\n**strings.xml**\n\nИспользуйте ключи в именах строк, как и в именах пакетов — это поможет вам решить проблему с одинаковыми именами и лучше понимать контекст использования строк.\n\n**Плохой пример**\n```xml\n<string name=\"network_error\">Network error</string>\n<string name=\"call_failed\">Call failed</string>\n<string name=\"map_failed\">Map loading failed</string>\n```\n\n**Хороший пример**\n```xml\n<string name=\"error.message.network\">Network error</string>\n<string name=\"error.message.call\">Call failed</string>\n<string name=\"error.message.map\">Map loading failed</string>\n```\n\nНе пишите значения строк в верхнем регистре. Придерживайтесь стартных конвенций (например, первая буква - заглавная). Если вам нужно отобразить строку в верхнем регистре, сделайте это используя атрибут [`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) внутри элемента TextView.\n\n**Плохой пример**\n```xml\n<string name=\"error.message.call\">CALL FAILED</string>\n```\n\n**Хороший пример**\n```xml\n<string name=\"error.message.call\">Call failed</string>\n```\n\n<a name=\"deephierarchy\"></a>\n**Избегайте глубокой иерархии Views.** Иногда возникает соблазн добавить еще одну LinearLayout в разметку, однако чаще всего это приводит к подобным ситуациям:\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nИногда можно не увидеть чрезмерную вложенность в файле разметки, так как это может происходить из-да добавления элементов в разметку непосредственно в Java файле.\n\nИз-за этого может возникнуть несколько проблем. В первую очередь проблемы с производительностью приложения, так как процессору необходимо управлять более сложной структурой элементов. Другая еще более серьёзная проблема это [StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views).\n\nВ общем, постарайтесь сделать иерархию разметки наиболее более плоской: научитесь использовать [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html), как [оптипизировать вашу разметку](http://developer.android.com/training/improving-layouts/optimizing-layout.html) и использовать [`тег <merge>`](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts).\n\n<a name=\"webviews\"></a>\n**Остерегайтесь проблем, связанных с WebViews.** Когда вам нужно показать web-страницу, например новостную статью, не исполняйте код для очистки HTML на клиентской стороне, лучше всего попросить backend-программистов дать вам «чистый» HTML. [WebViews могут вызвать утечку памяти](http://stackoverflow.com/questions/3130654/memory-leak-in-webview) когда они ссылаются на Activity, вместо того, чтобы ссылаться на ApplicationContext. Избегайте использования WebView для создания текста или кнопок, для этого есть TextView и Button.\n\n\n### Фреймворки для тестов\n<a name=\"test-frameworks\"></a>\nТестовый фреймвокр Android SDK's только развивается, особенно когда ресь идет о UI тестах. Android Gradle содержит задачу [`connectedAndroidTest`](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing) которая запускает созданные вами тесты JUnit, используя [расширение JUnit с утилитами Android](http://developer.android.com/reference/android/test/package-summary.html). Это означает, что вы можете запускать тесты на присоединенном устройстве или эмуляторе. Следуйте официальным инструкциям по тестированию [[1]](http://developer.android.com/tools/testing/testing_android.html) [[2]](http://developer.android.com/tools/testing/activity_test.html).\n\n**Используйте [Robolectric](http://robolectric.org/) только для Unit-тестов, не для UI-тестов.** Этот фреймворк позволяет запускать тесты без устройства, для увеличения скорости разработки и идеально подходит для unit-тестов моделей данных и view. Однако, UI-тесты Robolectric'а не полные и не точные. У вас возникнут проблемы с тестированем элементов UI, таких как анимации, диалоги, и т.д. Процесс тестирования происходит «с закрытыми глазами» (без возможности видеть тестируемый экран).\n\n**[Robotium](https://code.google.com/p/robotium/) значительно облегчает написание UI-тестов.** Вам не понадобится Robotium connected-тестов, но он будет очено полезен в получении и анализе views за счет большого количества утилит и контроля экрана во время тестов. Тесты выглядят достаточно просто:\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // searches for the first occurence of \"More\" and clicks on it\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n\n### Эмуляторы\n<a name=\"emulators\"></a>\nЕсли вы - профессиональный Android разработчик, купите лицензию [эмулятора Genymotion](http://www.genymotion.com/). Genymotion работает быстрее обычных AVD-эмуляторов и с более высоким FPS. Он позволяет записывать демо-видео вашего приложения, эмулирует различное качество соединения, GPS и многое другое. Также он идеален для запуска тестов. У вас появится доступ к многим образам устройств на Android, так что на много дешевле купить Genymotion, чем покупать все эти устройства.\n\nПодводные камни: На эмуляторах Genymotion по умолчанию нет Google Play Store и Google Maps. Вам также могут понадобиться API, специфические для Samsung, по этому необходимо иметь свое устройство Samsung.\n\n\n### Конфигурация Proguard\n<a name=\"proguard-configuration\"></a>\n[ProGuard](http://proguard.sourceforge.net/) обычно используется в проектах Android для сжатия и шифровки кода.\n\nИспользование ProGuard зависит от конфигурации проекта. Обычно ProGuard используют для защиты release-версии проекта.\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\n\nЧтобы выяснить, какой участок кода нуждается в защите, а какой - нет, нужно отметить в коде одну или несколько точек входа. Обычно это классы, содержащие основне методы, апплеты, мидлеты, activities, и т.д. Фреймворк Android по умолчанию использует конфигурацию, которая находится в `SDK_HOME/tools/proguard/proguard-android.txt`. Вы можете задать собственные правила для найтройки ProGuard, просто поместив их в файл `my-project/app/proguard-rules.pro`, которые дополняют конфигурацию по умолчанию.\n\nОсновная проблема, связанная с ProGuard — остановка приложения при запуске с ошибками `ClassNotFoundException` или `NoSuchFieldException`, даже если задача для сборки проекта (т.е. `assembleRelease`) отработала без ошибок. Это означает одно из двух:\n\n1. ProGuard удалил класс, enum, метод, поле or аннотацию, посчитав что она не нужна.\n2. ProGuard зашифровал (переименовал) класс, enum или имя поля, старое имя которого по прежнему используется (т.е. Java-отражение).\n\nПроверьте `app/build/outputs/proguard/release/usage.txt` чтобы убедиться что удаленный объект нигде не упоминается.\nПроверьте `app/build/outputs/proguard/release/mapping.txt` чтобы убедиться что объект не был зашифрован.\n\nЧтобы не допустить *выбрасывание* нужных классов или их членов ProGuard'ом, добавьте опцию `keep` в файл конфигурации ProGuard:\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nЧтобы предотвратить *шифрование* классов или их членов, добавьте опцию `keepnames`:\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\n**Создайте релиз-сборку на ранней стадии** чтобы проверить правила ProGuard на предмет сохранности кода. Также рекомендуется делать релиз-версию каждый раз когда вы добавляете новую библиотеку и тестировать приложение на устройстве. Не ждите версии \"1.0\" для выпуска release-версии, так как тогда могут быть неприятности при запуске приложения.\n\n**Совет.** Сохраняйте файл `mapping.txt` для каждой выпущенной версии приложения. Сохраняя копию `mapping.txt` для каждой сборки, вы можете быть уверены в том что сможете отладить код если пользователь столкнется с ошибкой и отправит лог ошибок из зашифрованного кода.\n\n**DexGuard**. Если вам нужно оптимизировать или зашифровать код намного сильнее, используйте [DexGuard](http://www.saikoa.com/dexguard), коммерческий аналог ProGuard. Он также может разделить dex-файл для обхода лимита в 65k методов.\n\n\n### Хранение данных\n<a name=\"data-storage\"></a>\nЕсли вам нужно сохранить несколько простых \"флагов\" и ваше приложение использует один процесс - SharedPreferences будет достаточно. Это хороший выбор по умолчанию.\n\nЕсть две причины, по которым вы можете не захотеть использовать SharedPreferences:\n\n* *Производительность*: Вам нужно сохранить сложные данные или их очень много\n* *К данным должен быть доступ из нескольких процессов*: У вас есть виджеты или удаленные службы, которые работают в собственных процессах и требуют синхронизированных данных\n* *Реляционные данные*: Отдельные части ваших данных являются реляционными, и вы хотите обеспечить поддержание этих отношений.\n\nВы также можете хранить более сложные объекты - сериализовать их в json и десериализовать их при получении. При этом следует учитывать компромиссы, поскольку они могут быть не особо эффективными и не обслуживаемыми.\n\n#### ContentProviders\n\nИспользуйте стандартные ContentProviders, если вам не достаточно возможностей SharedPreferences. ContentProvider - быстрый и безопасный способ хранения данных.\n\nЕдинственный недостаток ContentProviders - это объем кода, который нужно написать для их работы, как и отсутствие качественных туториалов. Тем не менее, возможно создать ContentProvider с помошью библиотеки, например [Schematic](https://github.com/SimonVT/schematic), что значительно облегчает задачу.\n\nВам все еще понадобится написать код для парсинга, чтобы читать и сохранять данные в столбцы базы SQLite. Также возможно сериализировать данные, например используя Gson, а хранить только строку результата. В этом случае уменьшится производительность, но с другой стороны больше нет необходимости создавать отдельный столбец для каждого поля с данными.\n\n#### Используйте ORM\n\nМы не советуем использовать библиотеки для Object-Relation-Mapping. Используйте их только если у вас не безумно сложная структура данных и вам это действительно необходимо.\nКак правило, ORM библиотеки очень сложные и требуют много времени чтобы научиться их использовать. Если вы решите использовать ORM библиотеку, обратите внимание на то, является ли она _process safe_ (если это необходимо в приложении), так как многие из существующих ORM библиотек почему-то не безопасны.\n\n### Используйте Stetho\n<a name=\"use-stetho\"></a>\n[Stetho](http://facebook.github.io/stetho/) это мост отладки для приложений Android от компании Facebook, который интегрируется с Инструментами Разработчика из браузера Chrome. С помошью Stetho вы легко можете изучить работу приложения, а именно использование сетевого траффика. Stetho также позволяет легко отслеживать работу и редактировать базы данных SQLite и SharedPreferences в ващем приложении. Однако важно помнить, что Stetho нужно включать для debug типа приложения, но не для release версии.\n\n#### Используйте LeakCanary\n<a name=\"use-leakcanary\"></a>\n\n[LeakCanary](https://github.com/square/leakcanary) - это библиотека, которая производит обнаружение во время выполнения и выявление утечек памяти более рутинной частью процесса разработки приложений. См. в [wiki](https://github.com/square/leakcanary/wiki) дополнительные сведения о конфигурации и использовании. Только не забудьте настроить зависимости, чтобы данная библиотека не попадала в релизную сборку!\n\n### Используйте непрерывную интеграцию (Continuous Integration)\n<a name=\"use-continuous-integration-1\"></a>\n\nСистемы непрерывной интеграции позволяют автоматически создавать и тестировать ваш проект каждый раз, когда вы вносите изменения и систему контроля версий. Непрерывная интеграция также включает в себя статические инструменты анализа кода, генерирует файлы APK и распространяет их. [Lint](https://developer.android.com/studio/write/lint.html) и [Checkstyle](http://checkstyle.sourceforge.net/) - это инструменты, которые обеспечивают качество кода, в то время как [Findbugs](http://findbugs.sourceforge.net/) ищет ошибки в коде.\n\nСуществует большое разнообразие программного обеспечения для непрерывной интеграции, которые обеспечивают различные функции. Тарифы могут быть бесплатными, если ваш проект бесплатный и с открытым исходным кодом. [Jenkins](https://jenkins.io/) - хороший вариант, если в вашем распоряжении есть локальный сервер, с другой стороны, [Travis CI](https://travis-ci.org/) также рекомендуется, если вы планируете использовать непрерывную интеграцию в облаке.\n\n### Благодарности\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton и другим разработчики из команды Futurice за то, что они поделились своими знаниями в области Android разработки.\n\n<p align=\"center\">\n  <img alt=\"logo\" src=\"https://raw.githubusercontent.com/futurice/spiceprogram/gh-pages/assets/img/logo/chilicorn_no_text-256.png\" width=\"220\"/>\n</p>\n\nЭтот проект спонсируется [**Spice Program**](http://spiceprogram.org/chilicorn-history/), нашей программой с открытым исходным кодом и социальным воздействием, созданной с любовью [**Futurice**](http://www.futurice.com).\n\n### Лицензия\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n"
  },
  {
    "path": "translations/Spanish/README.es.md",
    "content": "# Buenas prácticas en el desarrollo de Android\n\nÉstas son algunas de las lecciones aprendidas por los desarrolladores de Android en [Futurice](http://www.futurice.com). Evita reinventar la rueda siguiendo estas directrices. Si también estás interesado en desarrollo de iOS o Windows Phone, también puedes echarle un ojo a nuestras guías de [**Buenas prácticas para el desarrollo en iOS**](https://github.com/futurice/ios-good-practices) y [**Buenas prácticas para el desarrollo de Windows Phone apps**](https://github.com/futurice/windows-app-development-best-practices).\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n\n## Resumen\n\n#### [Usar Gradle y su estructura recomendada de proyecto](#build-system)\n#### [Guardar contraseñas y datos sensibles en gradle.properties](#gradle-configuration)\n#### [IDEs y editores de texto](#ides)\n#### [Usar la librería Jackson para el parseo de datos JSON](#libraries)\n#### [No crear tu propio cliente HTTP, usa las librerías Volley o OkHttp](#networklibs)\n#### [Evitar Guava y usar sólo algunas librerías debido al *límite de 65k métodos*](#methodlimitation)\n#### [Estructura de paquetes Java](#java-structure-package)\n#### [Navegar con cuidado al elegir entre Activities y Fragments](#activities-and-fragments)\n#### [Los layouts XML son también código, trata de organizarlos correctamente](#resources)\n#### [Usar estilos para evitar atributos duplicados en XML layouts](#styles)\n#### [Usar varios archivos de estilos para evitar crear un único archivo de estilos enorme](#splitstyles)\n#### [Mantener el archivo colors.xml claro y conciso, definiendo la paleta de colores](#colorsxml)\n#### [Mantener el archivo dimens.xml claro y conciso, definiendo constantes genéricas](#dimensxml)\n#### [No hacer una jerarquía muy profunda de ViewGroups](#deephierarchy)\n#### [Evitar procesos en el lado del cliente para WebViews, y tener cuidado con las fugas de memoria](#webviews)\n#### [Usar Robolectric para tests de unidad, Robotium para UI tests](#test-frameworks)\n#### [Usar Genymotion como tu emulador](#emulators)\n#### [Siempre usar ProGuard o DexGuard](#proguard-configuration)\n#### [Usar SharedPreferences para una persistencia simple y ContentProviders para el resto](#data-storage)\n#### [Usar Stetho para depurar tu app](#use-stetho)\n#### [Usar Leak Canary para encontrar fugas de memoria](#use-leakcanary)\n\n----------\n\n### Android SDK\n\nColoca tu [Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools) en algún lugar de tu directorio `home` o en algún sitio independiente de cualquier otra aplicación. Algunas distribuciones de IDEs incluyen el SDK en la instalación, y es posible que lo coloque en el mismo directorio donde se encuentra el IDE. Esto puede ser contraproducente cuando necesites actualizar (o reinstalar) el IDE, ya que podrías perder la instalación del SDK, y forzándote a un nuevo largo y tedioso proceso de descarga.\n\nTambién evita poner el SDK en otro directorio de nivel de sistema que necesite permisos de sudo, si su IDE se ejecuta bajo tu usuario y no bajo root.\n\n<a name=\"build-system\"></a>\n### Sistema de construcción (Build system)\n\nTu opción por defecto debe ser [Gradle](http://tools.android.com/tech-docs/new-build-system). Con Gradle es más facil hacer:\n\n- Crear diferentes `sabores` o variantes de tu app\n- Hacer tareas sencillas con scripts\n- Administrar y descargar dependencias\n- Personalizar keystores\n- Y mucho más...\n\nAnt, el anterior sistema de compilación, está obsoleto desde 2015 y ahora el plugin de Gradle para Android está siendo desarrollado y apoyado por Google.\n\nEs importante que el proceso de construcción de tu aplicación esté definido por tus archivos Gradle, en lugar de depender de configuraciones específicas del IDE. Esto permite una construcción consistente entre herramientas y un mejor soporte para sistemas de integración continua.\n\n### Estructura de proyecto\n\nAunque Gradle ofrece mucha flexibilidad a la hora de estructurar tu proyecto, a menos que tenga una razón convincente para hacerlo, deberías adoptar su [estructura por defecto](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Project-Structure). Ésto simplificará tus scripts de construcción. \n\n<a name=\"gradle-configuration\"></a>\n### Configuración de Gradle\n\n**Estructura general.** Seguir la [guía de Gradle de Google para Android](http://tools.android.com/tech-docs/new-build-system/user-guide)\n\n**Pequeñas tareas.** En lugar de (shell, Python, Perl, etc) scripts, puedes crear tareas en Gradle. Tan sólo sigue la [documentación de Gradle](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF) para más detalles.\n\n**Contraseñas.** En el archivo `build.gradle` de tu aplicación necesaritarás definir los `signingConfigs` para tu `release`. Ésto es lo que deberías de evitar:\n\n_No hagas esto_. Esto apararecerá en el sistema de control de versiones.\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nEn su lugar, crea un archivo `gradle.properties` que _no_ sea añadido al sistema de control de versiones:\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nEse archivo será automáticamente importado por Gradle, por lo tanto, podrás usarlo en el `build.gradle` de la siguiente forma:\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"Deberías definir tu KEYSTORE_PASSWORD y KEY_PASSWORD en gradle.properties.\")\n        }\n    }\n}\n```\n\n**Mejor usar una resolución de dependencia Maven que importar ficheros jar** Si explicitamente incluyes fichero jar en tu proyecto, éstos estarán en una versión especifica congelada. Descargar jars y gestionar sus actualizaciones es muy tedioso, éste es un problema que Maven soluciona de una manera adecuada, y es también la forma que Gradle recomienda usar. Por ejemplo:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp:2.2.0'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'\n}\n```    \n\n**Evitar usar resoluciones de dependencia dinámicas en Maven**\nEvitar el uso de resoluciones de dependencia dinámicas, como por ejemplo `2.1.+`, ya que puede dar lugar a compilaciones inestables o a diferencias de comportamiento entre compilaciones. El uso de versiones estáticas como `2.1.1` ayuda a crear un entorno de desarrollo más estable, predecible y reproducible.\n\n**Usar diferentes nombres para los paquetes de las compilaciones que no sean para release**\nUsar `applicationIdSuffix` para *debug* [build type](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types) para ser capaz de instalar el apk de ambas versiones, *debug* y *release*, en un mismo dispositivo (también puedes hacer esto para compilaciones personalizadas, si fuera necesario). Esto será especialmente valioso más adelante en el ciclo de vida de la aplicación, después de haber sido publicado en la tienda.\n\n```groovy\nandroid {\n    buildTypes {\n        debug {\n            applicationIdSuffix '.debug'\n            versionNameSuffix '-DEBUG'\n        }\n\n        release {\n            // ...\n        }\n    }\n}\n```\n\nUtiliza iconos diferentes para distinguir las versiones instaladas en el dispositivo, por ejemplo, con diferentes colores o con un texto `debug` superpuesto. Gradle hace esto muy sencillo: con la estructura de proyecto por defecto, simplemente pon el icono de *debug* en `app/src/debug/res` y el de *release* en `app/src/release/res`. También podrías [cambiar el nombre de la app](http://stackoverflow.com/questions/24785270/how-to-change-app-name-per-gradle-build-type) por tipo de compilación, así como el `versionName` (como en el ejemplo anterior).\n\n<a name=\"ides\"></a>\n### IDEs y editores de texto\n\n**Usa el editor que quieras, pero debe de adaptarse a la estructura de proyecto.** Los editores son una elección personal, y es tu responsabilidad que su editor funcione de acuerdo con la estructura del proyecto y el sistema de construcción.\n\nEl IDE recomendado es [Android Studio](https://developer.android.com/sdk/installing/studio.html) porque es desarrollado y actualizado frecuentemente por Google, tiene un buen soporte para Gradle, contiene una amplia gama de herramientas muy útiles para la supervisión y análisis y generalmente está adaptada para el desarrollo de Android.\n\nAlternativamente puedes utilizar un editor de texto sin formato como Vim, Sublime Text o Emacs. Pero en ese caso, necesitará usar Gradle y `adb` en la línea de comandos.\n\nUsar [Eclipse ADT](http://developer.android.com/tools/help/adt.html) para el desarrollo de Android ya no es una buena práctica.\n[Google dejó de dar soporte a ADT en 2015](http://android-developers.blogspot.fi/2015/06/an-update-on-eclipse-android-developer.html) y sugirió a los usuarios a [migrar a Android Studio](http://developer.android.com/sdk/installing/migrate.html) lo antes posible.\n\nCualquiera que sea tu elección, evita añadir ficheros de configuración específicos del editor en cuestión, como los ficheros de Android Studio `.iml`, al sistema de control de versiones, ya que normalmente contienen configuraciones específicas de tu máquina local que no funcionarán para los equipos de tus compañeros de trabajo.\n\nEn última instancia, se amable con otros desarrolladores; No los obligue a cambiar su herramienta de preferencia si así es como son más productivos.\n\n<a name=\"libraries\"></a>\n### Librerías\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** es una librería de Java para convertir Objects en JSON y viceversa. [Gson](https://code.google.com/p/google-gson/) es también una elección muy popular para este cometido, sin embargo creemos que Jackson es más completo, ya que suporta diferentes maneras de procesamiento de JSON: streaming, el modelo de árbol en memoria y el tradicional enlace de datos JSON-POJO. Ten en cuenta también, que Jackson es una librería más grande que GSON, así que dependiendo de tu caso, podrías optar por GSON para evitar el límite de 65k métodos. Otras alternativas: [Json-smart](https://code.google.com/p/json-smart/) y [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)\n\n<a name=\"networklibs\"></a>\n**Networking, caching, e imágenes.** Hay un par de soluciones probadas para realizar las peticiones a los servidores back-end, los cuales debes utilizar teniendo en cuenta la implementación de tu app. Usa [Volley](https://android.googlesource.com/platform/frameworks/volley) o [Retrofit](http://square.github.io/retrofit/). Volley también proporciona ayuda para cargar y almacenar imágenes en caché. Si eliges Retrofit, considera usar [Picasso](http://square.github.io/picasso/) para cargar y guardar en caché imágenes, y [OkHttp](http://square.github.io/okhttp/) para unas peticiones HTTP más eficientes. Todos ellos, Retrofit, Picasso y OkHttp han sido creados por la misma compañía, por lo que se complementan muy bien entre ellas. [OkHttp puede también ser usado en conjunción con Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n[Glide](https://github.com/bumptech/glide) es otra opción para cargar y guardar imágenes en caché. Tiene mejor rendimiento que Picasso, GIF y soporte para imágenes circulares, pero también tiene un número mayor de métodos.\n\n**[RxJava](https://github.com/ReactiveX/RxJava)** es una libreía para Programación Reactiva (Reactive Programming), en otras palabras, gestionar eventos asíncronos. Es un paradigma muy potente y prometedor, el cuál puede ser también muy confuso al ser tan distinto de cualquier otro. Recomendamos tomar precauciones antes de usar esta librería para diseñar toda la aplicación. Hay algunos proyectos hechos usando RxJava, si necesitaras ayuda ponte en contacto con alguna de estas personas: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. Hemos escrito algunas entradas de blog sobre este tema: [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\nSi no tienes experiencia previa con Rx, empieza a usarlo únicamente para las respuestas devueltas de una API. Poco a poco, podrías empezar a aplicarlo para gestión de eventos en un componente de la UI, como un evento de click o escribir en un campo de búsqueda. Si confías en tus habilidades en Rx y quieres aplicarlo a toda la arquitectura del proyecto, entonces será mejor que escribas Javadocs en todas las partes complicadas. Ten en cuenta que otros programadores pueden no estar familiarizados con RxJava y podría ser muy dificil mantener el proyecto. Haz lo posible para ayudarles a entender tu código y también Rx.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)** es una librería de Java para usar expresiones Lambda en Android y otras plataformas pre-JDK8. Retrolambda ayuda a mantener el código compactado y legible, especialmente si utilizas un estilo funcional como, por ejemplo, con RxJava.\n\nAndroid Studio ofrece soporte de ayuda de código lambda para Java 8. Si eres nuevo en lambdas, simplemente usa lo siguiente para comenzar:\n\n- Cualquier interfaz con sólo un método es \"lambda friendly\" y puede ser englobado en una sintaxis más compacta y reducida.\n- En caso de duda sobre los parámetros y demás, crea una clase anónima interna normal y luego deja que Android Studio lo pliegue en un lambda.\n\n<a name=\"methodlimitation\"></a>\n**Ten cuidado con la limitación de 65k métodos y evita usar muchas librerías.** Las aplicaciones Android, cuando están empaquetadas en un fichero dex, tienen una limitación de 65536 métodos referenciados [[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). Verás un error fatal de compilación si sobrepasas este límite. Por esta razón, es recomendable usar el menor número de librerías posibles y usar el contador de métodos dex: [dex-method-counts](https://github.com/mihaip/dex-method-counts) una herramienta para determinar el conjunto de librerías que pueden ser usadas para mantenerte por debajo de ese límite. Especialmente evita usar la librería Guava, ya que contiene cerca de 13k métodos.\n\n<a name=\"activities-and-fragments\"></a>\n### Activities y Fragments\n\nNo hay un consenso en la comunidad ni entre los desarrolladores en Futurice sobre cual es la mejor organización para una arquitectura Android con Fragments y Activities. Square incluso tiene [una librería para construir arquitecturas principalmente con Views](https://github.com/square/mortar), superando la necesidad de usar Fragments, pero ésto no está considerado aún como una práctica recomendable en la comunidad Android.\n\nDebido a la historia de la API de Android, puedes considerar que los Fragments son como partes de la interfaz de usuario de una pantalla. En otras palabras, los Fragments normalmente están relacionados con la interfaz de usuario. Las Activities pueden considerarse vagamente como las controladoras, son especialmente importantes para su ciclo de vida y para la gestión del estado. Sin embargo, es probable que veas variación en estas funciones: las Activities pueden tomar funciones de UI ([envío de transiciones entre pantallas](https://developer.android.com/about/versions/lollipop.html)), y [Fragments pueden ser usados sólo como controladores](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). Sugerimos que lo pruebes con cuidado, tomando decisiones con información suficiente, ya que hay varios inconvenientes a tener en cuenta al elegir una arquitectura sólo con Fragments, o sólo con Activities o sólo con Views. Aquí hay algunos consejos sobre con lo que se debe tener cuidado:\n\n- Evita usar [Fragments anidados](https://developer.android.com/about/versions/android-4.2.html#NestedFragments) siempre que se pueda, ya que pueden causar [matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/). Usa Fragments anidados únicamente cuando tenga sentido usarlos (como por ejemplo, Fragments en un ViewPager horizontal dentro de un Fragment similar a una pantalla) o si de verdad tienes razones suficientes para tomar esa decisión.\n\n- Evita poner demasiado código en las Activities. Siempre que sea posible, manténlas como unos contenedores ligeros de código, que existen en tu app principalmente para el ciclo de vida de la aplicación y otras tareas importantes de la API de Android. \nEs preferible Activities con un sólo Fragment en lugar de sólo Activities - poner el código UI en el Fragment de la Activity. De esta forma puedes reutilizarlo siempre que se necesite cambiar algo como, por ejemplo, reajustar el tamaño en una pantalla de tablet con varios Fragments dentro. Evita tener una Activity sin su correspondiente Fragment, a no ser que tengas verdaderas razones para ello.\n\n- No abuses de las API level de Android, ya que puedes depender en gran medida de Intents para el funcionamiento interno de su aplicación. Podría afectar al sistema operativo Android o a otras aplicaciones, creando errores o retrasos. Por ejemplo, se sabe que si su aplicación utiliza Intents para la comunicación interna entre sus paquetes, podría incurrir en retrasos de varios segundos en la experiencia del usuario si la aplicación se abriera justo después del inicio del sistema operativo.\n\n<a name=\"java-structure-package\"></a>\n### Estructura de paquetes Java\n\nLa arquitectura Java para aplicaciones Android puede ser brevemente explicada en [Modelo-Vista-Controlador (Model-View-Controller)](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). En Android, [Fragments y Activities son realmente clases controladoras](http://www.informit.com/articles/article.aspx?p=2126865). Por otro lado, también son explícitamente parte de la UI, por lo tanto también son Vistas.\n\nPor esta razón, es difícil clasificar a los Fragments (o Activities) estrictamente como controladores o vistas. Por eso, es mejor dejarlas estar en su propio paquete `fragments`. Las Activities pueden estar en el nivel superior  can stay on the top-level package as long as you follow the advice of the previous section. If you are planning to have more than 2 or 3 activities, then make also an `activities` package.\n\nDe lo contrario, la arquitectura puede parecerse a un MVC típico, con un paquete `models` que contiene POJOs para ser usados mediante el parseador JSON y las respuestas de una API, y un paquete `views` con todas las Views, notificaciones, Action Bars Views, widgets, etc. Los adaptadores (Adapters) son una estructura intermediaria entre los datos y las vistas. Sin embargo, normalmente necesitan exportar algunas View a través de `getView()`, por lo que se pueden incluir el paquete `adapters` dentro del paquete `views`.\n\nAlgunas clases de controladores se aplican a toda la aplicación y están cercanos al sistema Android. Éstos puede encontrarse en el paquete `managers`. Para las clases de procesamiento de datos, como \"DateUtils\", podría crearse el paquete `utils`. Y las clases responsables de interactuar con el backend en el paquete `network`.\n\nEn general, ordenado desde el más cercano al backend al más cercano al usuario:\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n<a name=\"resources\"></a>\n### Recursos (Resources)\n\n**Cómo nombrarlos.** Sigue el siguiente patrón para nombrar los los ficheros dependiendo de su tipo, `type_foo_bar.xml`. Ejemplos: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**Organizando los layouts XML.** Si no estás seguro de qué formato seguir en un layout XML, puede que te ayude seguir estas reglas.\n\n- Un atributo por línea, y 4 espacios de sangrado.\n- Empezar siempre con el atributo `android:id`.\n- Los atributos del tipo `android:layout_****` siempre arriba.\n- El atributo `style` al final.\n- La etiqueta de cierre `/>` en su propia línea, para facilitar el ordenado o la adición de nuevos atributos.\n- En lugar de usar textos estáticos (`hard coded`) en `android:text`, considera usar [atributos Designtime](http://tools.android.com/tips/layout-designtime-attributes) disponibles en Android Studio.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\nComo regla de oro, los atributos `android:layout_****` deberían estar definidos en el layout XML, mientras que otros atributos como `android:****` deberían mantenerse en un fichero XML de estilos. Esta regla tiene excepciones, pero en general funciona bien. La idea es mantener los atributos de del layout (posicionamiento, márgenes, tamaño, etc.) y el contenido en el fichero layout, mientras que todos los detalles de la apariencia (colores, padding, fuentes, etc.) en el fichero de estilos.\n\nLas excepciones son:\n\n- `android:id` obviamente debería estar en el archivo del layout.\n- `android:orientation` para un `LinearLayout` normalmente tiene más sentido estar en el fichero del layout.\n- `android:text` debería estar en el fichero del layout, ya que define el contenido.\n- Algunas veces tendrá sentido definir un valor genérico para `android:layout_width` y `android:layout_height` en un fichero de estilos, pero por defecto éstos deberían estar en los ficheros del layout.\n\n<a name=\"styles\"></a>\n**Uso de estilos (styles).** La gran mayoría de proyectos necesita usar apropiadamente estilos, ya que es muy común tener que reusar detalles de apariencia en algunas Views. Al menos deberías tener un estilo común para la mayoría de textos en la aplicación, por ejemplo:\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nY aplicándolo a un TextView:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\nSeguramente necesitarás hacer lo mismo para botones, pero no te pares aquí. Ve más lejos y mueve un grupo de atributos del tipo `android:****` repetidos y relacionados a un estilo común.v\n\n<a name=\"splitstyles\"></a>\n**Divide los ficheros grandes de estilos en varios ficheros.** No necesitas tener un único fichero `styles.xml`. Android SDK soporta otros archivos también, no hay nada mágico sobre el nombre `styles`, lo que importa son las etiquetas XML` <style> ` de dentro del archivo. Por lo tanto, puedes tener `styles.xml`,` styles_home.xml`, `styles_item_details.xml`,` styles_forms.xml`. A diferencia de los nombres de directorio de recursos que sí tienen algún significado para el sistema de compilación, los nombres de archivo en `res/values` pueden ser arbitrarios.\n\n<a name=\"colorsxml\"></a>\n**`colors.xml` es una paleta de colores.** No debería haber nada más en tu `colors.xml` que una transformación del nombre de un color a su valor RGBA. No lo uses para definir valores RGBA para distintos tipos de botones.\n\n*No hagas esto:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\nDe esta forma, es muy fácil que repitas valores RGBA y que resulte complicado cambiar algún color básico si lo necesitas. De hecho, estas definiciones están relacionadas con un contexto, como por ejemplo \"button\" o \"comment\", y debería estar en un fichero de estilo para botones y no en `colors.xml`.\n\nEn su lugar, mejor hacer lo siguiente:\n\n```xml\n<resources>\n\n    <!-- Escala de grises -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- Colores básicos -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\nPídele ayuda al diseñador de la aplicación para crear la paleta de colores. Los nombres no tienen por qué ser el nombre del color \"verde\", \"azul\", etc. También nombres como \"color_primario\" o \"color_segundario\" están bien. Dar el correcto formato a los colores facilitará su cambio o refactorización, y también hará que se sepa cuántos colores diferentes se están utilizando en la aplicación. Normalmente para una IU aceptable, es importante reducir la variedad de colores que se utilizan.\n\n<a name=\"dimensxml\"></a>\n**Tratar el fichero dimens.xml como al colors.xml.** Se debería definir una \"paleta\" para los tamaños de letra y espaciado, con el mismo cometido que para los colores. Un buen ejemplo de fichero de dimensiones sería:\n\n```xml\n<resources>\n\n    <!-- Tamaño de letra -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- Espacio entre dos Views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- Tamaño de una View -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\nDeberías usar `espacio_****` para definir los márgenes y paddings en los layouts, de la misma forma que los textos son normalmente tratados. Esto hará que el look-and-feel de la aplicación sea consistente, a la vez que hace más fácil organizar y cambiar los estilos y layouts.\n\n**strings.xml**\n\nAsigne nombres a las cadenas de texto con claves que se asemejen al contexto al que se refieren y romper la ambigüedad, así que no tengas miedo de repetir un valor para dos o más claves, si realmente lo necesitas.\n\n**Mal**\n```xml\n<string name=\"network_error\">Network error</string>\n<string name=\"call_failed\">Call failed</string>\n<string name=\"map_failed\">Map loading failed</string>\n```\n\n**Bien**\n```xml\n<string name=\"error_message_network\">Network error</string>\n<string name=\"error_message_call\">Call failed</string>\n<string name=\"error_message_map\">Map loading failed</string>\n```\n\nNo escribas cadenas de texto en mayúsculas. Sigue las convenciones, como por ejemplo, poner en mayúscula sólo el primer carácter del texto. Si necesitas mostrar todo el texto en mayúsculas, hazlo usando, el atributo [\n`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) en un TextView.\n\n**Mal**\n```xml\n<string name=\"error_message_call\">CALL FAILED</string>\n```\n\n**Bien**\n```xml\n<string name=\"error_message_call\">Call failed</string>\n```\n\n<a name=\"deephierarchy\"></a>\n**Evite una jerarquía de vistas de gran profundidad.** A veces, se puede estar tentado a añadir un LinearLayout, para realizar la composición de vistas. Puede ocurrir que se dé esta situación:\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nIncluso si esto no ocurre de explícitamente en un único layout, podría terminar ocurriendo si están inflando vistas (en Java) dentro de otras vistas.\n\nPueden ocurrir un par de problemas a raíz de esto. Es posible que se experimenten problemas de rendimiento, ya que hay un árbol muy complejo en la UI que el procesador necesita controlar. Otro problema más grave es la posibilidad de un [Error de StackOverflow](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views) al tener demasiadas vistas.\n\nPor lo tanto, intenta mantener la jerarquía de las vistas lo más plana posible: aprende a utilizar [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html), y cómo [optimizar tus diseños](Http://developer.android.com/training/improving-layouts/optimizing-layout.html) y utilizar la etiqueta [`<merge>`](http://stackoverflow.com/questions/8834898/whatwhat-is-the-purpose-of-androids-merge-tag-in-xml-layouts).\n\n<a name=\"webviews\"></a>\n**Ten cuidado con los problemas relacionados con WebViews.** Cuando tengas que mostrar una página web, por ejemplo para un artículo de noticias, evita hacer el procesamiento del lado del cliente para limpiar el código HTML, solicita un HTML \"*puro*\" a los programadores del backend. [Los WebViews también pueden crear memory leaks](http://stackoverflow.com/questions/3130654/memory-leak-in-webview) cuando mantienen una referencia a su actividad, en lugar de estar vinculados al ApplicationContext. Evita usar un WebView para textos simples o botones, usa en su lugar TextViews o Buttons.\n\n<a name=\"test-frameworks\"></a>\n### Herramientas de Testing\n\nLas herramientas de testing en el SDK de Android siguen estando \"en pañales\", especialmente lo relativo al testing de UI. Actualmente, Android Gradle implementa una tarea llamada [`connectedAndroidTest`](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing) la cual, lanza los test de unidad que creas, usando una [extensión de JUnit para Android](http://developer.android.com/reference/android/test/package-summary.html). Esto significa que necesitarás conectar un dispositivo o un emulador para ejecutar los test. Sigue la guía oficial [[1]](http://developer.android.com/tools/testing/testing_android.html) [[2]](http://developer.android.com/tools/testing/activity_test.html) para el testing.\n\n**Usar [Robolectric](http://robolectric.org/) únicamente para los test de unidad, no para vistas.** Se trata de una herramienta de testing que busca realizar los test \"sin necesidad de conectar un dispositivo\" buscando una mayor velocidad de desarrollo, especialmente adecuadas para test de unidad en Models y View Models. Sin embargo, los test con Robolectric son inexactos e incompletos con respecto a los test de UI. Tendrás problemas para probar elementos de la UI relacionados con animaciones, diálogos, etc., y esto se complicará más aún por el hecho de que estás \"a ciegas\" (ya que las pruebas se realizan sin ver la pantalla sobre las que se ejecutan los test).\n\n**[Robotium](https://code.google.com/p/robotium/) Hace que la escritura de test para UI sea más sencillo.** No necesitas Robotium para ejecutar los test para UI, pero probablemente será beneficioso ya que posee ayudantes para obtener y analizar vistas y controlar la pantalla. Los casos de prueba serán tan simples como:\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // Busca la primera ocurrencia de \"More\" y hace click en él\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n<a name=\"emulators\"></a>\n### Emuladores\n\nSi estás desarrollando aplicaciones de Android como profesión, compra una licencia para el [emulador de Genymotion](http://www.genymotion.com/). Los emuladores de Genymotion se ejecutan a una velocidad de frames/seg. más rápida que los emuladores AVD típicos. Tienen herramientas para enseñar tu aplicación, emulando la calidad de conexión de red, posiciones GPS, etc. También son ideales para testing. Tiene acceso a muchos (no a todos) dispositivos diferentes, por lo que el coste de una licencia de Genymotion es en realidad mucho más barato que comprar múltiples dispositivos reales.\n\nLas advertencias son: Los emuladores de Genymotion no poseen todos los servicios de Google, como Google Play Store y Google Maps. Es posible que también necesites probar APIs específicas de Samsung, por lo que es necesario tener un dispositivo Samsung real.\n\n<a name=\"proguard-configuration\"></a>\n### Configuración de Proguard\n\n[ProGuard](http://proguard.sourceforge.net/) Se utiliza normalmente en proyectos de Android para reducir y ofuscar el código compilado.\n\nYa uses ProGuard o no, dependerá de la configuración de tu proyecto. El uso habitual es configurar Gradle para usar ProGuard al crear el apk para la release.\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\n\nPara determinar qué código tiene que ser conservado y qué código se puede descartar u ocultar, se debe especificar uno o más puntos de entrada a tu código. Estos puntos de entrada suelen ser clases con métodos principales, applets, midlets, Activities, etc.\n\nAndroid usa una configuración por defecto que se encuentra en `SDK_HOME/tools/proguard/proguard-android.txt`.\nUsando ésta configuración, con reglas específicas para el proyecto en cuestión en ProGuard, definidas en `my-project/app/proguard-rules.pro`, se anexarán a la configuración predeterminada.\n\nUno de los problemas comunes relacionados con ProGuard es ver fallar la aplicación al inicio con `ClassNotFoundException`, `NoSuchFieldException` o similar, incluso aunque el comando de compilación (como por ejemplo: `assembleRelease`) terminó satisfactoriamente sin advertencias.\n\nEsto puede deberse a:\n\n1. ProGuard ha eliminado esa clase, enum, método, variable o anotación, considerando que no era necesario.\n2. ProGuard ha ofuscado (renombrado) la clase, enum o nombre de campo, pero está siendo utilizado indirectamente por su nombre original, es decir, a través de la reflexión de Java.\n\nComprueba `app/build/outputs/proguard/release/usage.txt` para ver si el objeto en cuestión ha sido eliminado.\nY comprueba `app/build/outputs/proguard/release/mapping.txt` para ver si el objecto ha sido ofuscado.\n\nPara prevenir que ProGuard *se deshaga* de las clases o elementos necesarios, añádelos a `keep` en la configuración de ProGuard:\n\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nPara prevenir que ProGuard *ofusque* clases u otros elementos, añádelos a `keepnames`:\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\nTambién podrás encontrar más ejemplos en la documentación oficial de [Proguard](http://proguard.sourceforge.net/#manual/examples.html).\n\n**En las primeras etapas de tu proyecto, haz una versión para release** para comprobar si las reglas de ProGuard funcionan correctamente. También, cuando incluyas nuevas librerías al proyecto, haz otra versión para release y prueba el apk en un dispositivo real. No esperes hasta la versión \"1.0\" de tu app para hacer las pruebas, ya que podrías encontrarte con sorpresas inesperadas y un tiempo muy ajustado para poder solucionar cualquier error.\n\n**Consejo.** Guarda el fichero `mapping.txt` de cada release que publiques a tus usuarios. Haciendo ésto, podrás depurar un problema cuando un usuario encuentre un error y lo envíe como una traza ofuscada.\n\n**DexGuard**. Si lo que necesitas es una herramienta más potente para optimizar, y especialmente para ofuscar el código, considera la opción de [DexGuard](http://www.saikoa.com/dexguard), es un software comercial hecho por el mismo equipo que hizo ProGuard. También puede dividir fácilmente archivos Dex para resolver la limitación de 65k métodos.\n\n<a name=\"data-storage\"></a>\n### Almacenamiento de datos\n\n#### SharedPreferences\n\nSi lo único que necesitas guardar son datos simples y tu app se ejecuta en un único proceso SharedPreferences entonces puede que sea suficiente como opción por defecto.\n\nHay dos razones por las que no podrías no querer usar SharedPreferences:\n\n* *Rendimiento*: La información a guardar es muy compleja o es mucha.\n* *Múltiples procesos accediendo la información*: Puede que tengas widgets o servicios remotos que se ejecutan en sus propios procesos y requieren de datos sincronizados.\n\n\n#### ContentProviders\n\nEn el caso de SharedPreferences no sea suficiente para tu app, deberías utilizar la plataforma estándar ContentProviders, que son más rápidos y su procesamiento es más seguros.\n\nEl único problema con ContentProviders es la cantidad de código que se necesita para configurarlos, además de tutoriales de baja calidad. Sin embargo, es posible generar el ContentProvider utilizando librerías como [Schematic](https://github.com/SimonVT/schematic), que reduce significativamente el esfuerzo.\n\nAún así se necesita escribir algo de código para leer los objetos de las columnas SQLite y viceversa. Es posible serializar los objetos, por ejemplo con Gson, y sólo guardar la cadena de texto resultante. De esta manera se pierde en rendimiento pero por otro lado no necesitas declarar una columna para todos los campos de la clase.\n\n\n#### Usar un ORM\n\nPor lo general, no recomendamos el uso de librerías de mapeo Objeto-Relacional (Object-Relational Mapping), a menos que tengas datos extremadamente complejos y tengas una necesidad grave. Tienden a ser complejas y requieren tiempo para aprender. Si decidieras usar un ORM debes prestar atención a si es o no un _proceso seguro_ y si su aplicación realmente lo requiere, ya que muchas de las soluciones existentes de ORM sorprendentemente no lo son.\n\n\n<a name=\"use-stetho\"></a>\n### Usar Stetho \n\n[Stetho](http://facebook.github.io/stetho/) es una herramienta de depuración para aplicaciones Android de Facebook que se integra con las herramientas de desarrollo (Developer Tools) del navegador Chrome. Con Stetho puedes inspeccionar fácilmente tu aplicación, especialmente el tráfico de red. También te permite inspeccionar y editar fácilmente bases de datos SQLite y las SharedPreferences en su aplicación. Sin embargo, debes asegurarse de que Stetho sólo está habilitada en la versión de debug y no en la de release. \n\n<a name=\"use-leakcanary\"></a>\n### Usar LeakCanary\n\n[LeakCanary](https://github.com/square/leakcanary) es una librería que hace que la detección en tiempo de ejecución y la identificación de memory leaks sean una parte rutinaria más del proceso de desarrollo de apps. Échale un ojo a la librería [wiki](https://github.com/square/leakcanary/wiki) para tener detalles sobre la configuración y su uso. Únicamente recuerda configurar sólo la dependencia \"no-op\" en tu versión de release!\n\n### Gracias a\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton y otros desarrolladores de Futurice por compartir su conocimiento en el desarrollo de Android.\n\n### Licencia\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n"
  },
  {
    "path": "translations/Turkish/README.tr.md",
    "content": "# Android Geliştirmede En İyiyi Yakalamak\n\n[Futurice](http://www.futurice.com)'deki Android Geliştiriciler tarafından öğrenilmiş Android derslerini içerir. Bu kılavuzları takip edin ve tekerleği tekrar icat etmekle vakit harcamayın. Eğer IOS ve Windows Phone platformlarında da geliştirme yapmakla ilgileniyorsanız, [**iOS Good Practices**](https://github.com/futurice/ios-good-practices) ve [**Windows App Development Best Practices**](https://github.com/futurice/windows-app-development-best-practices) dökümanlarını da incelemeyi unutmayın.\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n\n## Özet\n\n#### [Gradle ve önerilen proje yapısı](#build-system)\n#### [Şifreleri ve hassas verileri gradle.properties içerisine koyun](#gradle-configuration)\n#### [JSON data parse etmek için Jackson kütüphanesini kullanın.](#libraries)\n#### [Kendi HTTP client'ınızı yazmak yerine, Volley veya OkHttp kütüphanelerini kullanın.](#networklibs)\n#### [*65k method limit* olayından dolayı Guava ve çok fazla kütüphane kullanmaktan kaçının.](#methodlimitation)\n#### [UI ekranları için Fragment kullanmayı tercih edin.](#activities-and-fragments)\n#### [Activity dosyalarını sadece Fragment'ları yönetirken kullanın.](#activities-and-fragments)\n#### [Layout XML dosyaları da kodlardan oluşur, onları düzgün organize edin.](#resources)\n#### [Layout XML dosyalarında nitelik çakışmasını engellemek için style dosyaları kullan.](#styles)\n#### [Bir tane büyük style dosyası yerine bu dosyayı parçalara bölün.](#splitstyles)\n#### [colors.xml dosyasını kısa ve sade tut, sadece renk paletini belirle](#colorsxml)\n#### [dimens.xml dosyanıda sade tut, sadece genel sabitleri belirle.](#dimensxml)\n#### [ViewGroup'lar için derin bir hiyerarşiden kaçın.](#deephierarchy)\n#### [WebView üzerinde client-side işlemlerden kaçın, ve leakleri hesaba kat](#webviews)\n#### [Unit Test yaparken Robolectric, UI testler içinse Robotium  kullan.](#test-frameworks)\n#### [Emülatör olarak Genymotion kullan](#emulators)\n#### [Her zaman ProGuard veya DexGuard kullan](#proguard-configuration)\n#### [Basit devamlılıktaki uygulamalar için SharedPreferences, diğerleri içinse ContentProvider kullan.](#data-storage)\n#### [Uygulamanı debug ederken Stetho kullan.](#use-stetho)\n\n\n----------\n\n### Android SDK\n\n[Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools) dosyanızı uygulamalardan bağımsız ve erişebileceğiniz bir yere koyun. Bazı IDE'ler yüklenirken, kendisiyle birlikte SDK dosyalarınıda yükler ancak bunu yaparken kendi ana dosya dizinine yükleyebilir. Bu kullanışlı değildir, çünkü IDE değiştirmek istediğinizde veya güncelleme yaparken bu verilerde kayba uğrayabilirsiniz. Ayrıca eğer IDE'niz root üzerinde çalışmıyorsa, SDK dosyalarınızı sistem seviyesinde veya admin izni isteyen bir yere koymayın.  .\n\n### Yapı Sistemi\n\n[Gradle](http://tools.android.com/tech-docs/new-build-system) bu durumda ilk seçeneğiniz olmalı. Ant daha sınırlı ve daha çok komut kullanmanızı istemektedir. Gradle ile ise:\n\n- Uygulamanın farklı yerlerini oluşturur\n- Okunabilir görevlendirme yapmanızı sağlar\n- Dependency'leri yönetir ve indirir,\n- Keystore'ları düzenler\n- ve daha fazlasını yapar\n\nAndroid'in Gradle eklentisi, Google tarafından durmadan geliştirilmekte ve dependency kontrolünde en ön plana çıkan seçenek olmaktadır.\n\n### Proje Yapısı\n\nİki seçeneğimiz var: Eski ADT ve Eclipse proje yapısı, ve yeni Gradle & Android studio proje yapısı.Siz yeni olanı seçmelisiniz. Eğer eski yapıyı kullanıyorsunuz, artık onun tarih olduğunu varsayıp yeni yapuya geçirin.\n\nEski yapı:\n\n```\nold-structure\n├─ assets\n├─ libs\n├─ res\n├─ src\n│  └─ com/futurice/project\n├─ AndroidManifest.xml\n├─ build.gradle\n├─ project.properties\n└─ proguard-rules.pro\n```\n\nYeni yapı:\n\n```\nnew-structure\n├─ library-foobar\n├─ app\n│  ├─ libs\n│  ├─ src\n│  │  ├─ androidTest\n│  │  │  └─ java\n│  │  │     └─ com/futurice/project\n│  │  └─ main\n│  │     ├─ java\n│  │     │  └─ com/futurice/project\n│  │     ├─ res\n│  │     └─ AndroidManifest.xml\n│  ├─ build.gradle\n│  └─ proguard-rules.pro\n├─ build.gradle\n└─ settings.gradle\n```\n\nBu iki yapı arasındaki ana fark, yeni fark kesin olarak 'kaynak dosyaları'  (main, androidTest), Gradle ile birbirinden ayırmaktadır. Örneğin, 'paid' ve 'free' adı altında iki kaynak dosyasını 'src' içerisine ekleyip uygulamanıza bu kaynakların özelliklerinden faydalanmasına olanak sağlayabilirsiniz.\n\nYüksek kalitede bir 'app' klasörü sahibi olmak  uygulamanızda kullanılan başka kütüphane projelerinden projelerinizin ayrılmasına olanak sağlar. `settings.gradle` ise `app/build.gradle` referanslarını tutacağı kütüphaneleri takip eder.\n\n### Gradle Düzenlemeleri\n\n**Genel Yapı** [Google'ın Android için Gradle Rehberi](http://tools.android.com/tech-docs/new-build-system/user-guide) takip edin.\n\n**Küçük işlemler** shell, Python, Perl, gibi dillerde script ile işlem yapmak yerine, Bu işlemleri Gradle üzerinden yapabilirsiniz.Bunun için [Gradle Dökümantasyonu](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF) nu okuyun.\n\n**Şifreler.** `build.gradle` içerisinde, uygulamanın yayın versiyonu için `signingConfigs` kısmını belirlemeniz lazım. Kaçınmanız gerekenler şunlar:\n\n_Bundan Kaçının_. VCS üzerinde görülecektir.\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nOnun yerine, `gradle.properties` dosyası oluşturup VCS'ye eklemeyin:\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nBu dosya Gradle otomatik olarak tarafından tanınacaktır, `build.gradle` içinde direk kullanabilirsiniz.\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**Jar dosyaları import etmek yerine Maven dependency çözümünü kullanın.** Jar dosyalarını projelerinize direk olarak eklerseniz, bunlar `2.1.1` gibi belirli versiyonlarda olacaktır. Bu da jarların güncellenmesi yada versiyon değiştirmesi ile ilgili sıkıntı çıkaracaktır, bu sorun Maven'ın çözdüğü bir sorundur, Android Gradle Build tarafından da önerilmektedir. Örneğin:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp:2.2.0'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'\n}\n```    \n\n**Dinamik Maven Dependency çözümlerinden kaçının**\n`2.1.+` şeklinde yazılmış dinamik versiyon numaralarından kaçının,farklı versiyon numaralarında dikkate alınmamış değişikliklerden dolayı, düzgün çalışmayan veya ince hatalar bulunan uygulamalar geliştirmiş olursunuz. `2.1.1` gibi statik versiyonlar kullanmak daha stabil, düzgün çalışan ve hataları kolayca belirlenebilen uygulamalar ortaya çıkarmanızı sağlar.\n\n**Release olmamış projeler için farklı paket isimleri kullanın**\n `applicationIdSuffix` ile *debug* [build type](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types) seçeneklerini *debug* ve *release* modudnaki apk apkları aynı cihaz üzerine yükleyip test edebilmek için yazarız. Bu uygulamamız yayınlandıktan sonraki süreçte dahada büyük önem kazanacaktır.\n\n```groovy\nandroid {\n    buildTypes {\n        debug {\n            applicationIdSuffix '.debug'\n            versionNameSuffix '-DEBUG'\n        }\n\n        release {\n            // ...\n        }\n    }\n}\n```\n\nFarklı versiyon tipleri için farklı icon'lar kullanmanız sizin yararınıza olacaktır. Gradle bu işlemleri kolaylaştırmıştır: verilen proje yapısında, *debug* iconunu `app/src/debug/res` içerisine ve *release* iconunu `app/src/release/res` koyun. Aynı zamanda [Uygulama adı değiştirip](http://stackoverflow.com/questions/24785270/how-to-change-app-name-per-gradle-build-type) `versionName` üzerinden bunu gerçekleştirebilirsiniz.\n\n### IDEler ve Text Editörler\n\n**Proje yapısını düzgün takip edebileceğiniz herhangi bir text editörünü kullanabilirsiniz** Editörler kişisel tercihler üzerine değişebilir ancak proje yapısını düzgün takip edebileceğiniz bir çevre yaratmalısınız.\n\nŞu anda en çok tavsiye edilen IDE [Android Studio'dur](https://developer.android.com/sdk/installing/studio.html). Bunun, Google tarafından geliştiriliyor olması, Gradle kullanıyor olması, yeni proje yapısı hazır halde gelmesi, Android Development için özel üretilmiş olması ve artık stabil olması gibi pek çok sebebi vardır.\n\nAndroid geliştiriciliğinde [Eclipse ADT](http://developer.android.com/tools/help/adt.html) kullanımı artık tavsiye edilmemektedir. [Google ADT desteiğini 2015 sonunda bitirdi](http://android-developers.blogspot.fi/2015/06/an-update-on-eclipse-android-developer.html) ve kullanıcılarını [Android Studio'ya geçiş](http://developer.android.com/sdk/installing/migrate.html) yapmalarını önerdi. Hala Eclipse kullanmaya devam edebilirsiniz ancak, ancak eski proje yapısını ve ANT kullanımını desteklediği için, Gradle çalışması için düzenlemeler yapmanız veya komut satırı üzerinden çalıştırmanız gerekmektedir.\n\nVim, Sublime Text veya Emacs gibi Text Editörleri de kullanabilirsiniz. Bu durumda Gradle ve adb'yi komut satırından çalıştırmanız beklenmektedir.\n\nHangi editörü kullanırsanız kullanın Gradle ve proje yapısının önerilen şekilde olduğundan emin olun, ve editörünüze özgü dosyaları VCS üzerine eklemediğinize emin olun. Örneğin, Ant üzerinde `build.xml` dosyasını eklemediğinize emin olun. Özellikle `build.gradle` dosyasını güncel tutmayı ve çalışır halde olduğundan emin olmayı unutmayın. Her zaman diğer developerları düşünün ve onların sizin için projelerini toparlamak zorunda olmadıklarını hatırlayın.\n\n### Kütüphaneler\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** Objeleri JSON'a çeviren ve JSON'ları da objeye çeviren bir Java kütüphanesidir. [Gson](https://code.google.com/p/google-gson/) kütüphaneside bu durumda en çok kullanılan kütüphanedir, ancak biz Jackson'ı JSON işlemede alternatif seçenekler sunduğu için tercih ediyoruz: streaming, in-memory tree model, ve klasik JSON-POJO data binding. Ama unutmamanız gereken şey Jackson GSON'dan daha büyük bir kütüphanedir ve 65k method limitine uymak için bazen duruma göre değişiklik yapmanız gerekebilir. Diğer alternatifler: [Json-smart](https://code.google.com/p/json-smart/) ve [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)\n\n<a name=\"networklibs\"></a>\n**Networking, caching, ve resimler.** Backend serverlara istek atmada kendini ispatlamış sizinde kendi projenizin client-side'ınde kullanabileceğiniz pek çok kütüphane vardır. [Volley](https://android.googlesource.com/platform/frameworks/volley) yada [Retrofit](http://square.github.io/retrofit/)'i kullanabilirsiniz'.Volley aynı zamanda resim yükleme ve cachede tutmaya yardımcı olmaktadır. Retrofiti seçerseniz, resim yüklemek için [Picasso](http://square.github.io/picasso/)yu, ve etkili HTTP requestler için [OkHttp](http://square.github.io/okhttp/) kullanabilirsiniz. Üç kütüphanede (Retrofit, Picasso and OkHttp) aynı şirketin ürünüdür ve birbirleriyle verimli çalışmaktadırlar. [OkHttp aynı zamanda Volley ilede kullanılabilmektedir.](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n\n**RxJava** reaktif programlama için kullanılan bir kütüphanedir, başka bir deyişle ise, senkronize olmayan işlemleri gerçekleştirir. Bu çok güçlü ve pek çok şey vaad eden bir paradigmadır, Çok farklı olduğu için kafa karıştırıcı da olabilir.Tüm uygulamanızı bu kütüphaneye göre yapmadan önce herşeyi dikkatlice göz önüne almanızı öneriyoruz. RxJava ile yapılmış bazı projeler var, eğer yardıma ihtiyacıbız olursa bu konuyla ilgili konuşabileceğiniz insanlar: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. Bu konuyla ilgili bizimde yazdığımız blog gönderileri: [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\nRx programlama ile ilgili herhangi bir tecrübeniz yoksa öncelikle ,API'den gelen cevaplara uygulayarak başlayın. Alternatif olaraksa, Basit UI işlemlerinde uygulayabilirsiniz , click yada bir text kısmına yapılan yazıları dinlerken gibi. Eğer Rx yeteneklerinize güveniyorsanız ve tüm mimariye bunu uygulamak istiyorsanız,O zaman her kısma Javadocs ekleyin. Unutmamanız gereken önemli noktaysa ileride projede çalışacak Rx programlama ile ilgili tecrübesiz olabilir, bu yüzden kodunuzu mümkün olduğunca anlaşılır tutun.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)**, Android ve JDK-8 öncesi projelerde Lambda syntax'ını kullanmamızı sağlayan kütüphanedir. Kodunuzu temiz ve düzenli tutar, özellikle RxJava ile çalışırken işinizi çok kolaylaştırır. Kullanmak için, JDK8 yükleyin, SDK yerini nasıl belirlemenizi istediysek aynı şekilde jdk yerini belirleyin, `JAVA8_HOME` ve `JAVA7_HOME` sistem değişkenlerini ayarlayın, build.gradle üzerinde artık çağırabilirsiniz:\n\n```groovy\ndependencies {\n    classpath 'me.tatarka:gradle-retrolambda:2.4.1'\n}\n```\n\nGradle'ın her bir modülüne belirtilen değeri yazın:\n\n```groovy\napply plugin: 'retrolambda'\n\nandroid {\n    compileOptions {\n    sourceCompatibility JavaVersion.VERSION_1_8\n    targetCompatibility JavaVersion.VERSION_1_8\n}\n\nretrolambda {\n    jdk System.getenv(\"JAVA8_HOME\")\n    oldJdk System.getenv(\"JAVA7_HOME\")\n    javaVersion JavaVersion.VERSION_1_7\n}\n```\n\nAndroid Studio Java8 lambdalar için destek sağlar. Lambda'lar hakkında bilginiz yoksa, Sıradakileri takip edin:\n\n- Bir method barındıran interface'ler \"lambda dostu\" olarak anılır ve daha kısa syntax içerisine alınabilir.\n- Parametreler ve benzeri hakkında ikileme düşerseniz, anonim bir inner class yazın ve Android Studio onu sizin için lambda formatına çevirsin.\n\n<a name=\"methodlimitation\"></a>\n**Dex method sınırlamasına dikkat edin ve çok fazla kütüphane kullanmaktan kaçının.** Android uygulamalar, dex dosyası olarak sıkıştırıldıklarında, 65536 adet referans edilebilecek metod sınırlaması vardır.  [[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). Eğer sınır aşarsınız hata aldığınızı göreceksiniz. Bu sebeple, düşük sayıda kütüphaneler kullanın, [dex-method-counts](https://github.com/mihaip/dex-method-counts) aracını kullanarak hangi kütüphanelerle bu limitin altında kalacağınızı hesaplayabilirsiniz. Özellikle Guava kullanımından sakının.İçeriğinde 13k metod barındırmaktadır.\n\n### Activity'ler ve Fragment'lar\n\nAndroid developerlar ve Futurice developerları arasında dahi Android Uygulamada Activity ve Fragment kullanarak en iyi yazılım mimarisinin nasıl yapılacağı hakkında bir fikir birliği yok. Square bile [Çoğunlukla View'lar aracılığıyla Mimari oluşturma](https://github.com/square/mortar),Fragmentlara olan ihtiyacı ortadan kaldırmıştır, ama community arasında halen kabul edilebilir bir işlem olarak görülmemektedir.\n\nAndroid API'nin tarihi itibariyle, Fragmentları UI kısmının başında olarak görebilirsiniz. Diğer bir deyişle, Fragmentlar çoğunlukla UI'a bağlıdırlar. Activityler ise yönetmek ve lifecycle'dan dolayı controller görevi görmektedir. Ancak, Bu roller arasında çeşitlilikte de gözlenebilir: Activityler UI görevi alabilir([Ekranlar arası değişiklik yapmak](https://developer.android.com/about/versions/lollipop.html)), ve [Fragmentları controller olarak kullanmak](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). Her bir yaklaşımın(sadece-fragment mimarisi, veya sadece-activity,veya sadece-view) kendince sakıncaları olduğu için dikkatli karar vermenizi öneriyoruz.Dikkat etmeniz gereken birkaç şey aşağıda sıralanıyor, işinize yarayan kısımları kullanmaya dikkat edin.\n\n- [İçiçe Fragment](https://developer.android.com/about/versions/android-4.2.html#NestedFragments)ları sıkça kullanmamaya çalışın, çünkü [matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/) oluşabilir. Sadece mantıklı yerlerde içiçe fragment kullanın (örneğin, Fragment içerisindeki Viewpager'ın içerisinde bulunan fragmentlar) veya gerçekten düşünülmüş bir senaryoysada kullanabilirsiniz.\n- Activityler içerisine çokça kod koymaktan çekinin. Mümkün olduğunca hafif kodlar tutun, uygulamanızın lifecycle ve Android-interfacing API'leri ile çoğunlukla ön plana çıkarılmalıdır. Düz activityler yerine tek fragment içeren activityler tercih edilmeli ve UI kodları fragment içerisine yerleştirilmelidir. Bu bir modifikasyonda veya taba eklemek,çoklu fragment ekranına geçmek gibi genel değişiklikte bize kolaylık sağlar. Mümkün olduğunca her activitynize karşılık bir fragment bulundurmaya çalışın, aksi durumda dikkatlice herşeyi ayarladığınıza emin olun.\n- Android işletim seviyesinde işlem yapmamaya dikkat edin.Bu seviyeyle ilgili yaşayabileceğiniz en büyük sıkıntıları Intent kullanımı sırasında yaşayabilirsiniz. Bu kullandığınız intentler, Android işletim sistemini veya diğer uygulamaları etkileyebilir ve buglara sebep olabilir. Örneğin, eğer uygulamanızda paketler arası haberleşmede intent kullanıyorsanız, cihazınız açıldıktan sonra bu haberleşmede bir kaç saniyelik gecikme yaşayabilirsiniz.\n\n### Java Paket Mimarisi\n\nJava Android mimarisi kabaca [Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) üzerinden açıklanabilir. Android'de, [Fragment ve Activity controller kısımlarıdır](http://www.informit.com/articles/article.aspx?p=2126865). Öte yandan, kullanıcı arayüzünün arayüzleridir,dolayısıyla UI kısımlarıdır.\n\nBu sebeple, fragment veya activityleri view yada controller sınıfına direk koymak yanlıştır. Bu yüzden onları `fragments` paketinde tutmak daha mantıklıdır. Önceki kısımdaki yönergeleri takip ettiğiniz takdirde activitynizi en tepede tutmakta sakınca yoktur. Eğer 2,3 veya daha fazla activity kullanmak istiyorsanız activitylerinizi `activities` paketi içine koyabilirsiniz.\n\nYoksa, mimari klasik bir MVC gibi görünebilir, API cevaplarından gelen JSON'lardan elde edilen POJO'ların tutulduğu `models`paketi, custom-viewlarınızı tuttugunuz `views` paketi, bildirimler, action bar viewları, widgetlar vs. Adapterlar ara birimlerdir, data ve viewlar arasında bulunur. Ancak, çoğunlukla `getView()` ile viewları çağırdıkları için `adapters` alt paketini `views` içerisine koyabilirsiniz.\n\nBazı controller sınıfları tüm uygulamayı kapsar ve Android İşletim Sistemi seviyesine yakındır. Bunlar `managers` packeti içerisinde bulunabilir. Çeşitli data process sınıfları, \"DateUtils\" gibi, `utils` paketi içerisinde yer almaktadır. Backend ile iletişim içerisindeki sınıfları ise `network` paketi içerisine koyabilirsiniz.\n\nBackende en yakından Kullanıcıya en yakın olarak sıraladığımızda hepsi böyle bir görünüm alır:\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n### Resource Dosyaları\n\n**İsimlendirme** İsimlendirme yaparken `type_foo_bar.xml` kalıbındaki gibi, tipini öncesine yazın. Örneğin: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**Layout XML'leri Düzenlemek** XML dosyalarını doğru bir şekilde nasıl oluşturacağınızı bilmiyorsanız, Bunları takip edin:\n\n- Her bir satıra bir özellik gelecek ve 4 boşluk karakteri kadar boşluk bırakılacak şekilde yazın.\n- `android:id` her zaman ilk özelliğiniz olmalı\n- `android:layout_****` özellikleri her zaman yukarıda olmalı\n- `style` özelliği en aşağıda tutulmalı\n- Tag kapatma simgesini `/>` ayrı bir satıra yazmanız yeni bir özellik eklerken veya düzenleme yaparken yararınıza olacaktır.\n- `android:text` kullanmak yerine,[Designtime attributes](http://tools.android.com/tips/layout-designtime-attributes) seçeneğini kullanmayı deneyin.Android studio desteği bulunmaktadır.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\nAna kural olarak `android:layout_****` ile paylaşan kavramlar XML içerisinde tanımlanmalıyken, `android:****` ile başlayan diğer özellikler style etiketi altında ayrı bir XML'de belirtirlmelidir. Bu kuralın istisna durumları vardır,ancak genelde böyle yapılması yararlıdır. Ana fikir her zaman (pozisyon,büyüklük,kenarlara olan uzaklıklar vs.) ve içerik özelliklerini xml içinde tutarken, Style özelliklerini (renk,dosya adı,text boyutu vs.) style XML'leri içerisinde tutmaktır.\n\nİstisnalar ise:\n\n- `android:id` kesinlikle layout XML dosyasında olmalıdır\n- `LinearLayout` özelliği olan `android:orientation` ın layout XML içinde bulunması daha mantıklıdır\n- `android:text` içerik belirlediği için layout dosyasında olmalıdır\n- `android:layout_width` ve `android:layout_height` kullanarak bazen farklı bir style yapabilirsiniz ancak önceden dosyayı oluşturduğunuzda, layout XML içerisinde bu özellikler gelecektir.\n\n<a name=\"styles\"></a>\n**Style kullanın.** Nerdeyse bütün projelerimizde style kullanmamız mantıklı olan seçenektir,çünkü bir view'ın pek çok kez aynı özelliklerle karşımıza gelme olasılığı yüksektir. Örneğin çok kullanılan bir Text için ortak bir style belirleyip kod yükünüzü aşağıdaki gibi hafifletebilirsiniz:\n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nApplied to TextViews:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\nBunu buttonlar içinde yapmanız gerekebilecektir. Ama bununla yetinmeyin,`android:****` özelliklerin hepsini style'a taşıyın.\n\n<a name=\"splitstyles\"></a>\n**Büyük bir style dosyasını küçük dosyalara bölün.** Kendinizi `styles.xml` dosyası ile sınırlamak zorunda değilsiniz. Android SDK için `styles` kelimesinden ziyade, XML dosyasısın `<style>` etiketini içernesi daha önemlidir. Bu sebeple `styles.xml`, `styles_home.xml`, `styles_item_details.xml`, `styles_forms.xml` gibi pek çok dosya oluşturabilirsiniz. res dosyası içerisindeki işletim sistemine anlam ifade eden kelimeler varken, `res/values` içerisindeki dosyalar değişkenlik gösterebilir.\n\n<a name=\"colorsxml\"></a>\n**`colors.xml` sizin renk paletiniz.** `colors.xml` dosyanızda bir rengin adını gösteren RGBA değerinden başka birşey olmamalıdır. Buttonların farklı özellikleri için farklı RGBA kullanmak gibi girişimler yapmayın.\n\n*Bunu yapmayın:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\nBurada aynı RGBA değerini farklı yerlerde kullanmanız mümkündür ve basit bir renk değişikliğinde pek çok dosyada değişiklik yapmanız gerekecektir. Aynı zamanda, bu açıklamalar style kısmına ait olmalıdır `colors.xml` içerisinde tutulmamalıdır.\n\nOnun yerine, bunu yapın:\n\n```xml\n<resources>\n\n    <!-- grayscale -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- basic colors -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\n\nBu renk paletini uygulamanızın tasarımcısından isteyin. Renklerin isimleri illede \"beyaz\",\"mavi\" gibi renk isimleri olmak zorunda değildir. \"anarenk\", \"ikincilrenk\", \"negatifdegeri\" gibi isimlerde kabul edilebilir. Renkleri böyle belirlemek değişiklik yapmamızı kolaylaştırırken, kullandığımız renk sayısınada hakim olabiliriz. Estetik bir UI için renk varyasyonları düşürmek önemlidir.\n<a name=\"dimensxml\"></a>\n**dimens.xml dosyasını da colors.xml gibi düzenleyin.** Renklerdeki aynı amaçlar doğrultusunda Text büyüklüğü ve kenar boşlukları içinde bir \"palet\" oluşturmak doğru olandır. Dimen dosyasına güzel bir örnek şekildeki gibidir:\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\n`spacing_****`etiketi layoutlarda boşluk bırakma için kullanılmaktadır, margin veya paddinglerde, direk kod içerisinde veri yazmak yerine, normal string oluşturmuşuz gibi düşünülebilir. Bu bize daha düzenli, düzenlenmesi kolay ve anlaması kolay bir kod ortamı sunmaktadır.\n\n**strings.xml**\nStringleri etiketlerken içerikle yakın olacak şekilde anahtar kelimeler seçmeyi tercih edin, aynı stringi birden çok etiket için kullanmaktan çekinmeyin. Diller karmaşık kavramlardır, bu etiketlemenin düzgün yapılması mantık kurulmasını kolaylaştırıp belirsizliği ortadan kaldıracaktır.\n\n**Kötü**\n```xml\n<string name=\"network_error\">Network error</string>\n<string name=\"call_failed\">Call failed</string>\n<string name=\"map_failed\">Map loading failed</string>\n```\n\n**İyi**\n```xml\n<string name=\"error.message.network\">Network error</string>\n<string name=\"error.message.call\">Call failed</string>\n<string name=\"error.message.map\">Map loading failed</string>\n```\n\nString değerlerinin hepsini büyük harflerle yazmayın, normal kullanımdaki gibi devam edin(ör., İlk harf büyük harfle başlanabilir.). Tüm texti büyük harflerle göstermeniz gerekiyorsa bunu TextView özelliği olan [`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) ile yapabilirsiniz.\n\n**Kötü**\n```xml\n<string name=\"error.message.call\">CALL FAILED</string>\n```\n\n**İyi**\n```xml\n<string name=\"error.message.call\">Call failed</string>\n```\n\n<a name=\"deephierarchy\"></a>\n**Viewlar arasında içiçe çoklu hiyerarşiden kaçının.** Bazen UI'da düzenleme yapıp istediğinizi elde etmek için, bir tane daha LinearLayout eklemek size cazip gelebilir. Bu tarz şeyler şunlara sebep olabilir:\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nBunu özel olarak layout dosyasında kullanmasanız bile, Java kodunuz üzerinden yazarken view oluşturduğunuzda buna benzer durumu oluşturabilirsiniz.\n\nBununla ilgili birkaç problem oluşabilir. performans problemleriyle karşılabilirsiniz, çünkü ele alınması gereken pek çok UI elemanı bulunmaktadır. Öne çıkacak başka hataysa bu [StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views) dur.\n\nBu yüzden, view'lerinizi mümkün olduğunca basit tutun: [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html) kullanımını öğrenin, [Layoutlarınızı ayarlamak](http://developer.android.com/training/improving-layouts/optimizing-layout.html) nasıl olur onu öğrenin ve [`<merge>` tag](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts) kullanımını araştırın.\n\n<a name=\"webviews\"></a>\n**WebView'ler ile alakalı sorunları dikkate alın.** Bir makale ile ilgili sayfa göstermek ve benzeri durumlarda bir web sayfası göstermek istediğinizde, cilient-side tarafında mümkün olduğunca işlem yapmaktan çekinin, backend programcılarınızdan \"*saf*\" HTML dosyası almayı talep edin. ApplicationContext'e bağlı olmak yerine Activity üzerinden bir referans alındıysa [WebView'da Memory Leak](http://stackoverflow.com/questions/3130654/memory-leak-in-webview) oluşabilir. Basit butonlar ve form yapıları için websayfası kullanmayın, native çalışmayı tercih edin.\n\n\n### Test frameworkleri\n\nAndroid SDK test frameworkleri, özellikle UI testleri, henüz daha başlangıç aşamasındadır. Android Gradle [`connectedAndroidTest`](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing) adını verdikleri bir test materyali üzerinde çalışmaktadırlar.Bu materiyal [Android için JUnit eklentileri ve yardımcıları](http://developer.android.com/reference/android/test/package-summary.html) üzerinde çalışmaktadır. Bunun için bir cihaz veya emülatör üzerinden testlerinizi sürdürmelisiniz. Test için resmi kaynaklar şunlardır: [[1]](http://developer.android.com/tools/testing/testing_android.html) [[2]](http://developer.android.com/tools/testing/activity_test.html).\n\n**Unit test için [Robolectric](http://robolectric.org/) kullanın** Robolectric \"cihazdan bağımsız olarak\" Unit ve UI testlerde kullanabileceğiniz bir test frameworküdür. Ancak, Robolectric üzerinde UI test yapmak doğru sonuçlar vermeyecektir. UI elemanları arasında animasyonlarda ve benzeri durumlarda gözlem yapamadığınız için verimli bir test alamayacaksınız.\n\n**[Robotium](https://code.google.com/p/robotium/) UI testleri kolaylaştırır.** Robotium ile birbirinden bağımsız UI testler yazabilirsiniz. Ancak birbirine bağlı testler yazmanız uygulamanızın akışını kontrol etmeniz açısından size daha yararlıdır. Test kodları örnekteki kadar kolaydır.:\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // searches for the first occurrence of \"More\" and clicks on it\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n### Emulatorler\n\nAndroid geliştiricilik mesleğiniz ise [Genymotion emulator](http://www.genymotion.com/) için lisans alın. Genymotion emulatorler AVD emülatörlerden daha hızlı frame/sec hizmeti sağlarlar. İçerisinde uygulamanızı test etmek için, network bağlantı kalitesini test etmek için, GPS pozisyonları ve buna benzer pekçok durum için araç bulundurmaktadır. Aynı zamanda uygulamayı toplu test etme durumlarında yararlıdır. Pek çok cihaz üzerinde farklı android versiyonları üzerinde test yapabilirsiniz, dolayısıyla Genymotion lisansı pek çok cihaz almaktan çok daha mantıklıdır.\n\nUyarılar: Genymotion Play Store ve Maps gibi Play Store Servislerini içermez. Ayrıca Samsunga özgü API'leri test etmek için Samsung cihaz kullanmanız önerilir.\n\n### Proguard Ayarları\n\n[ProGuard](http://proguard.sourceforge.net/) Android projelerini küçültmek ve kodları karartmak için kullanılır.\n\nProGuard kullanıp kullanmamanız proje ayarlarına bağlıdır. Genellikle uygulama yayınlarken Gradle dosyanızı ProGuard kullanmaya ayarlamanız mantıklı olandır.\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\n\nHangi kodun gözardı edileceğini, hangisinin korunacağını ve hangisinin karartılacağını ayarlamak için, kodunuz içerisinde birden çok giriş noktası ayarlamanız gerekmektedir. Bu giriş noktaları genelde main methodu olan sınıflar, appletler, midletler, activityler,ve benzeridir.\nAndroid frameworkü proguard ayarlarını `SDK_HOME/tools/proguard/proguard-android.txt` adresindeki txt'den alır. Yukarıdaki ayarlarla,projeye özgü,belirli ProGuard kuralları, `my-project/app/proguard-rules.pro`, adresinde belirtildiği üzere varsayılan ayarlar olarak uygulanacaktır.\n\n`assembleRelease` gibi Proguard komutları başarılı çalıştığı halde,ProGuard'la ilgili en belirgin hatalar `ClassNotFoundException` veya `NoSuchFieldException` ve benzerleri ortaya çıkabilir.\nBu iki anlama gelebilir:\n\n1. ProGuard bulunmayan dosyayı gerekli bulmayarak silmiş olabilir.\n2. ProGuard Java adını karartmış olabilir ve bu Java sınıfına başka bir yerde direk ismiyle ulaşılıyor olabilir.\n\n`app/build/outputs/proguard/release/usage.txt` üzerinden objenin kaldırılıp kaldırılmadığını kontrol edin.\n`app/build/outputs/proguard/release/mapping.txt` üzerinden objenin karartılıp karartılmadığını kontrol edin.\n\nProGuard'ın gerekli dosyalardan ve methodlardan *kurtulmasını* engellemek için, ProGuard ayarlarına `keep` ile özel durumu ekleyin:\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nProGuard'ın gerekli dosyaları ve methodları *karartmasını* engellemek için, ProGuard ayarlarına `keepnames` ile özel durumu ekleyin:\n\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\nDahası için [Proguard](http://proguard.sourceforge.net/#manual/examples.html).\n\n**Projelerinizin erken aşamalarında yayınlamak için APK oluşturun** Böylece ProGuard'ın size gerekli dosyaları tutup tutmadığını kontrol edebilirsiniz.Yeni bir kütüphane eklediğiniz zamanda aynı şekilde, bir tane yayına göndermek üzere APK hazırlayıp, cihazlarda deneyin. Uygulamanızın yayına tamamen hazır olduğunu düşündüğünüzde APK oluşturmak yerine bu şekilde durmadan APK oluşturmak daha yararlıdır. Böylece hatayı erkenden keşfedip önüne geçebilirsiniz.\n\n**Öneri.** `mapping.txt` dosyanızı kullanıcıya yolladığınız her bir güncellemede tutun. Bu şekilde kullanıcıdan gelecek hatada veya size gelen hata raporunda uygulamanızdaki hatayı daha çabuk bulabilirsiniz.\n\n**DexGuard**. Kodunuzu karartmak için gerçekten güçlü bir araca ihtiyacınız varsa,[DexGuard](http://www.saikoa.com/dexguard)'ı araştırın.DexGuard ticari amaçla ProGuard'ı yapan ekip tarafından yapılmış, ProGuard'a ek olarak 65k limit metodunu dex üzerinden çözmenizede yaran bir araçtır.\n\n### Veri Depolama\n\n\n#### SharedPreferences\n\nUygulamanız tek bir context üzerinde çalışıyor ve karmaşık veriler içermiyorsa varsayılan olarak SharedPreferences kullanmak en mantıklısıdır.\n\nSharedPreferences kullanmamak için düşünebileceğiniz seçenekler ise şunlardır:\n\n* *Performans*: Verilerinizin karmaşık veya çok fazlaysa\n* *Farklı işlemlerin istekleri* :Farklı pek çok işlem veriye ulaşmaya çalışıyorsa\n\n\n#### ContentProviders\n\nSharedPreferences yetmediği durumlarda, platform standardı olan ContentProviders'ı kullanabiliriz.ContentProviders daha hızlıdır ve işlemleri yapmada daha güvenilirdir.\n\nContentProviders kullanıma hazırlamak için yazmamız gereken kod miktarının uzun olması, hele kötü tutoriallar ile daha uzamasıdır. Ancak ContentProviderları [Schematic](https://github.com/SimonVT/schematic) gibi kütüphanelerle kullanıp büyük bir efordan kar edebiliriz.\n\nHalen SQLite üzerinden verileri okumak üzerine kod yazmanız gerekmektedir. Gson ve benzeri kütüphanelerle sadece ihtiyacınız olan verileri alabilirsiniz.Bu şekilde performans olarak düşüş olacaktır ancak veriler için teker teker sütün ayarlamak zorunda kalmayacaksınız.\n\n\n#### ORM Kullanımı\n\nGenellikle kesin bir ihtiyacınız yoksa veya kalabalık bir veri topluluğunuz yoksa ORM kullanımını tavsiye etmiyoruz. Biraz karmaşık ve öğrenmesi zaman almaktadır. Eğer uygulamanızda ORM kullanma kararı verdiyseniz _process safe_ olup olmamasını kontrol edin, çoğu ORM çözümü  _process safe_ değildir.\n\n\n### Stetho Kullanın\n\n[Stetho](http://facebook.github.io/stetho/) Facebook tarafından geliştirilmiş Chrome Developer Araçlarınıda kullanan, Android uygulumalarda kullanım için yapılmış bir debug bridge'dir. Stetho ile uygulamanızı kolayca inceleyebilirsiniz, özellikle network trafiğini takip etmede faydalıdır. Uygulamanızdaki SharedPreferences ve SQLite verilerini takip etmede size yardımcıdır. Ancak bunları yaparken Stethonun sadece debug modunda açık olduğuna emin olun.\n\n### Teşekkür\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton ve diğer Futurice geliştiricilere bilgilerini paylaştıkları için teşekkürler.\n\n### Lisans\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n"
  },
  {
    "path": "translations/Vietnamese/README.vi.md",
    "content": "# Những phương pháp tốt nhất trong việc phát triển Android (Best practices in Android development)\n\nĐây là những bài học và kinh nghiệm được rút ra từ những lập trình viên Android tại [Futurice](http://www.futurice.com). Những chỉ dẫn trong bài viết này giúp bạn tối ưu hoá được thời gian cũng như chất lượng dự án Android.Bên cạnh đó, nếu bạn quan tâm tới iOS và Windows Phone, bạn có thể tham khảo thêm tại hai bài hướng dẫn tương tự [**iOS Good Practices**](https://github.com/futurice/ios-good-practices) và [**Windows App Development Best Practices**](https://github.com/futurice/windows-app-development-best-practices).\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-android--best--practices-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1091)\n\n## Tổng quát (Summary)\n\n#### [Sự dụng Gradle và cấu trúc Android project](#build-system)\n#### [Đặt password và dữ liệu quan trọng trong gradle.properties](#gradle-configuration)\n#### [Sử dụng Jackson library để bóc tách dữ liệu dạng JSON](#libraries)\n#### [Đừng tự viết HTTP Client, hãy sử dụng thư viện Volley hoặc OkHttp](#networklibs)\n#### [Không nên sử dụng Guava và hãy sử dụng thư viện ít nhất có thể để tránh vượt quá *65k method limit*](#methodlimitation)\n#### [Cẩn thận trong việc lựa chọn giữa Activities và Fragments](#activities-and-fragments)\n#### [Layout XMLs cũng là code, nên hãy học cách tổ chức và sắp xếp chúng](#resources)\n#### [Sử dụng styles để tránh lặp lại việc khai báo attributes trong layout XMLs](#styles)\n#### [Sử dụng nhiều file styles thay vì nhét tất cả vào một file](#splitstyles)\n#### [Chỉ dùng colors.xml cho việc định nghĩa bàng màu và thật ngắn gọn](#colorsxml)\n#### [Tương tự cũng chỉ dùng dimens.xml cho định nghĩa các hằng số tổng quát](#dimensxml)\n#### [Không nên sử dụng hệ phân cấp sâu trong ViewGroups](#deephierarchy)\n#### [Tránh việc xử lý phía client tại WebViews, và chú ý việc rò rỉ bộ nhớ](#webviews)\n#### [Sử dụng Robolectric cho Unit Tests và Robotium cho UI tests](#test-frameworks)\n#### [Nên sử dụng Genymotion như máy ảo chính](#emulators)\n#### [Luôn sử dụng ProGuard hoặc DexGuard](#proguard-configuration)\n#### [Sử dụng SharedPreferences cho việc lưu trữ đơn giản, còn lại dùng ContentProviders](#data-storage)\n#### [Sử dụng Stetho để debug ứng dụng](#use-stetho)\n\n----------\n\n### Android SDK\n\nNên đặt [Android SDK](https://developer.android.com/sdk/installing/index.html?pkg=tools) ở đâu đó trong thư mục home (home directory) hoặc vị trí mà không liên quan đến ứng dụng/dự án của bạn. Một số bản phân phối IDEs đã bao gồm cả SDK, và có thể đặt nó trong cùng thư mục với IDEs. Việc này sẽ làm bạn điên đầu khi cần update hay cài lại IDE, và như vậy sẽ mất bản cài đặt SDK, một lần nữa phải mất công download lại.\n\nBên cạnh đó, nếu IDE của bạn chạy dưới quyền user, thì không nên để SDK trong thư mục hệ thống, nơi cần quyền truy cập root (sudo).\n\n### Build system\n\nSự lựa chọn mặc định là [Gradle](http://tools.android.com/tech-docs/new-build-system). Với Gradle, mọi thứ thực sự đơn giản để:\n\n- Build các bản flavours hay variants khác nhau cho ứng dụng của bạn\n- Tạo các tasks dạng script-like đơn giản\n- Quản lý và download thư viện hay dependencies\n- Thay đổi keystores\n- Và nhiều thứ hay ho nữa\n\nTrước đó Android có sử dụng một hệ thống build khác là Ant nhưng đã chấm dứt từ cuối năm 2015, giờ chỉ có Android's Gradle plugin là được phát triển và hỗ trợ từ Google.\n\nViệc ứng dụng của bạn được định nghĩa bởi các file Gradle quan trọng hơn việc phụ thuộc vào các cấu hình trong IDEs. Việc này cho phép việc chuyển tiếp builds giữa các công cụ tốt hơn và hỗ trợ tốt hơn cho hệ thống tích hợp liên tục (continuous integration).\n\n### Cấu trúc dự án (Project structure)\n\nMặc dù Gradle có độ linh hoạt cao và cho phép can thiệp sâu vào cấu trúc một project Android, trừ khi bạn bắt buộc phải thay đổi, còn không thì bạn nên chấp nhậntru cấu trúc mặc định[default structure](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Project-Structure). Việc này sẽ giúp bạn tối giản code trong build scripts.\n\n### Cấu hình Gradle (Gradle configuration) \n\n**Cấu trúc tổng quát (General structure).** Áp dụng hướng dẫn của Google[Google's guide on Gradle for Android](http://tools.android.com/tech-docs/new-build-system/user-guide)\n\n**Các tác vụ nhỏ (Small tasks).** Thay vì sử dụng (shell, Python, Perl, etc) scripts, bạn có thể tạo các tác vụ bằng Gradle, chỉ cần dựa theo hướng dẫn của Gradle ở đây [Gradle's documentation](http://www.gradle.org/docs/current/userguide/userguide_single.html#N10CBF).\n\n**Passwords.** Nếu bạn cần định nghĩa `signingConfigs` trong file `build.gradle` cho bản release build. Thì bên dưới là việc bạn nên tránh:\n\n_Không nên_. Bởi vì khi bạn định nghĩa như vậy thì password sẽ hiển thị trên hệ thống quản lý mã nguồn (Version Control System).\n\n```groovy\nsigningConfigs {\n    release {\n        storeFile file(\"myapp.keystore\")\n        storePassword \"password123\"\n        keyAlias \"thekey\"\n        keyPassword \"password789\"\n    }\n}\n```\n\nBạn nên tạo file `gradle.properties` và nó _không nên_ được thêm vào hệ thống quản lý mã nguồn (ví dụ Git) (nên liệt kê `gradle.properties` trong file .gitignore):\n\n```\nKEYSTORE_PASSWORD=password123\nKEY_PASSWORD=password789\n```\n\nFile đó sẽ tự động được import vào Gradle, vậy nên bạn có thể khái báo trong file `build.gradle` như sau:\n\n```groovy\nsigningConfigs {\n    release {\n        try {\n            storeFile file(\"myapp.keystore\")\n            storePassword KEYSTORE_PASSWORD\n            keyAlias \"thekey\"\n            keyPassword KEY_PASSWORD\n        }\n        catch (ex) {\n            throw new InvalidUserDataException(\"You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.\")\n        }\n    }\n}\n```\n\n**Nên sử dụng Maven dependency thay vì import thư viện file jar.** Nếu bạn sử dụng file jar trong project, thì việc download và update các phiên bản mới của nó sẽ mất thời gian và phức tạp. Vấn đề này đã được Maven giải quyết và được khuyến khích sử dụng trong Android Gradle builds. Ví dụ:\n\n```groovy\ndependencies {\n    implementation 'com.squareup.okhttp:okhttp:2.2.0'\n    implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'\n}\n```    \n\n**Tránh việc khai báo thư viện có version động trong Maven**\nTránh việc khai báo thư viện có version động ví dụ như `2.1.+`, vì việc này có thể dẫn đến các bản build khác nhau và không ổn định và khó kiểm soát các thư viện. Nên khai báo version tĩnh ví dụ như `2.1.1` để giúp project có môi trường phát triển ổn đinh, dễ kiểm soát.\n\n**Sử dụng tên package khác cho các bản build không phải là bản release**\nVí dụ sử dụng (`applicationIdSuffix`) cho bản *debug* [build type](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types) để có thể cài đặt cả hai bản *debug* và *release* trên cùng một thiết bị (cũng nên thay đổi tên package cho mỗi bản build của mỗi khách hàng). Việc này rất có lợi cho phần sau trong vòng đời của một ứng dụng, sau khi nó đã được publish trên store.\n\n```groovy\nandroid {\n    buildTypes {\n        debug {\n            applicationIdSuffix '.debug'\n            versionNameSuffix '-DEBUG'\n        }\n\n        release {\n            // ...\n        }\n    }\n}\n```\n\nSử dụng icons khác nhau để phân biệt bản debug và release. Dùng Gradle, làm việc này rất đơn giản: với cấu trúc app mặc định, chỉ cần đặt *debug* icon trong `app/src/debug/res` và *release* icon trong `app/src/release/res`. Bạn cũng có thể [thay đổi app name](http://stackoverflow.com/questions/24785270/how-to-change-app-name-per-gradle-build-type) cho các loại bản build, cũng như  `versionName` (như ví dụ bên trên).\n\n### IDE và trình soạn thảo (IDEs and text editors)\n\n**Sử dụng bất cứ trình soạn thảo nào, nhưng nó phải phù hợp với cấu trúc dự án của bạn** Trình soạn thảo(Editors) là sự lựa chọn của cá nhân bạn, và nhiệm vụ của bạn là cấu hình và thay đổi trình soạn thảo của bạn để phù hợp với cấu trúc dự án và hệ thống build(build system).\n\nIDE được khuyên dùng là [Android Studio](https://developer.android.com/sdk/installing/studio.html) bởi nó được phát triển và update thường xuyên bởi Google, hỗ trợ tốt Gradle, có rất nhiều các công cụ giám sát và phân tích hữu dụng, và nó được phát triển nhắm đến các dự án Android.\n\nNếu bạn muốn, bạn có thể sử dụng các trình soạn thảo như Vim, Sublime Text, or Emacs. Nhưng trong trường hợp này, bạn sẽ phải sử dụng Gradle and `adb` qua command line. \n\nSử dụng [Eclipse ADT](http://developer.android.com/tools/help/adt.html) cho việc phát triển Android không còn được khuyến khích.\n[Google ngừng hỗ trợ ADT vào cuối năm 2015](http://android-developers.blogspot.fi/2015/06/an-update-on-eclipse-android-developer.html) và thông báo cho người dùng [Chuyển qua Android Studio](http://developer.android.com/sdk/installing/migrate.html) sớm nhất có thể.\n\nBất cứ lựa chon của bạn là gì, bạn cũng nên tránh việc thêm files cấu hình trình soạn thảo hay IDE vào hệ thống quản trị mã nguồn (CVS), ví dụ file `.iml` của Android Studio, vì các file này thường chứa thông tin cấu hình cho riêng máy của bạn, và nó sẽ không phù hợp với máy của người khác, ví dụ thành viên trong nhóm làm cùng project với bạn.\n\nCuối cùng, nên đối xử hoà nhã với những lập trình viên khác; đừng bắt họ phải thay đổi công cụ ưa thích nếu họ làm việc hiệu quả với những công cụ đó.\n\n### Thư viện (Libraries)\n\n**[Jackson](http://wiki.fasterxml.com/JacksonHome)** là thư viện Java giúp chuyển đổi dữ liệu dạng Objects thành JSON và ngược lại. [Gson](https://code.google.com/p/google-gson/) thường được mọi người sử dụng, tuy nhiên chúng tôi thấy rằng Jackson có hiệu năng tốt hơn bởi vì nó hỗ trợ nhiều cách khác nhau trong việc xử lý JSON: streaming, in-memory tree model, and traditional JSON-POJO data binding. Mặc dù vậy hãy nên nhớ rằng Jackson là thư viện lớn hơn Gson, vì vậy phụ thuộc vào trường hợp của bạn, bạn có thể sử dụng Gson để tránh 65k methods limitation. Hai thư viện khác bạn có thể sử dụng là: [Json-smart](https://code.google.com/p/json-smart/) và [Boon JSON](https://github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes)\n\n<a name=\"networklibs\"></a>\n**Networking, caching, and images.** Có rất nhiều giải pháp đang tranh cãi được đưa ra cho việc thực hiện request tới backend mà bạn sử dụng để implement phía client. Vậy nên sử dụng [Volley](https://android.googlesource.com/platform/frameworks/volley) hay [Retrofit](http://square.github.io/retrofit/). Volley cung cấp cả helpers để load and cache images. Còn nếu bạn dùng Retrofit, nên sử dụng [Picasso](http://square.github.io/picasso/) cho việc loading and caching images, và [OkHttp](http://square.github.io/okhttp/) cho việc thực hiện HTTP requests hiệu quả. Bộ ba thư viện Retrofit, Picasso và OkHttp được tạo ra bởi cùng một công ty, nên chúng hỗ trợ cho nhau rất tốt. [OkHttp cũng có thể được sử dụng để kết nối với Volley](http://stackoverflow.com/questions/24375043/how-to-implement-android-volley-with-okhttp-2-0/24951835#24951835).\n[Glide](https://github.com/bumptech/glide) là một lựa chọn nữa cho việc loading and caching images. Nó có performance tốt hơn Picasso, hỗ trợ GIF and circular image, nhưng có số lượng method lớn hơn Picasso.\n\n**RxJava** là một thư viện cho Reactive Programming, hay nói cách khác, xử lý các sự kiện không đồng bộ (asynchronous events). Đây là một mô hình mạnh mẽ và đầy hứa hẹn nhưng cũng có thể làm bạn hơi bối rối vì sự khác biệt của nó. Chúng tôi khuyến khích các bạn nên thận trọng trong việc sử dụng thư viện này để cấu trúc toàn bộ application. Chúng tôi đã sử dụng RxJava trong một số project, nếu bạn cần sự giúp đỡ, hãy liên hệ với một trong những thành viên sau: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. We have written some blog posts on it: [[1]](http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android), [[2]](http://blog.futurice.com/top-7-tips-for-rxjava-on-android), [[3]](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), [[4]](http://blog.futurice.com/android-development-has-its-own-swift).\n\nNếu bạn không có kinh nghiệm với Rx, khi bắt đầu bạn chỉ nên áp dụng nó cho responses từ API. Bên cạnh đó, bắt đầu bằng việc áp dụng nó cho các tác vụ xử lý sự kiện UI đơn giản, ví dụ sự kiện click hay typing trong search field. Nếu bạn đủ tự tin vào kỹ năng Rx programming và muốn áp dụng nó cho toàn bộ cấu trúc, thì hãy nên viết Javadocs cho tất cả các phần khó. Vì nếu không sẽ khó cho một lập trình viên khác không quen với RxJava khi maintain project của bạn. Hãy cố gắng giúp họ hiểu code của bạn cũng như Rx một cách tốt nhất.\n\n**[Retrolambda](https://github.com/evant/gradle-retrolambda)** là một thư viện Java cho việc sử dụng cú pháp Lamda expression trong Android và các nền tảng trước JDK-8. Nó giúp làm cho code bạn ngắn gọn và dễ hiểu, đặc biệt nếu bạn sử dụng functional style, ví dụ với RxJava.\n\nAndroid Studio hỗ trợ code cho Java8 lambdas. Nếu bạn mới bắt đầu với lambdas, bạn nên theo hướng dẫn sau đây: \n- interface chỉ có một phương thức là \"lambda friendly\" và nó có thể gộp thành một cú pháp gọn hơn.\n- Nếu bạn nghi ngờ về parameters, hãy lập tức viết một inner class và để Android Studio tự động gộp nó vào một lamda.\n\n<a name=\"methodlimitation\"></a>\n**Nên chú ý về dex method limitation, và tránh sử dụng quá nhiều thư viện.** Android apps,khi được đóng gói như một file dex, chỉ cho phép giới hạn trong 65536 phương thức tham chiếu (referenced methods) [[1]](https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71) [[2]](http://blog.persistent.info/2014/05/per-package-method-counts-for-androids.html) [[3]](http://jakewharton.com/play-services-is-a-monolith/). Bạn sẽ bắt gặp lỗi fatal error trong quá trình biên dịch nếu bạn vượt qua ngưỡng này. Với lý do đó, hãy nên sử dụng thử viện ít nhất có thể và sử dụng công cụ [dex-method-counts](https://github.com/mihaip/dex-method-counts) để xác định xem tập thư viện nào có thể được sử dụng để tránh việc vượt quá giới hạn này. Đặc biệt, tránh sử dụng thư viện Guava vì nó chứa hơn 13k methods.\n\n### Activities and Fragments\n\nKhông có sự đồng thuận duy nhất nào trong cộng đồng cũng như trong developers tại Futurice trong câu trả lời cho câu hỏi: \"Đâu là cách tổ chức cấu trúc tốt nhất cho một dự án Android với Fragments hay Activity?\". Thậm chí Square có một thư viện cho việc xây dựng cấu trúc gần như hoàn toàn với Views [a library for building architectures mostly with Views](https://github.com/square/mortar), bỏ qua cho sự cần thiết của Fragments, nhưng việc này vẫn không được khuyến khích như một phương pháp hay trong cộng đồng.\n\nQua lịch sử xây dựng Android API, bạn có thể coi Fragments như là một phần UI trên một màn hình. Activities có thể được xem như controllers và chúng đặc biệt quan trọng cho việc quản lý vòng đời và trạng thái của chúng. Tuy nhiên, bạn có thể thấy chúng trong điều ngược lại: activities có thể đóng vai trò như thành phần UI([delivering transitions between screens](https://developer.android.com/about/versions/lollipop.html)), và fragments có thể được độc lập sử dụng như controllers[fragments might be used solely as controllers](http://developer.android.com/guide/components/fragments.html#AddingWithoutUI). \nChúng tôi khuyên bạn nên cẩn thận khi đưa ra quyết định bởi vì sẽ có nhiều hạn chế nếu chọn cấu trúc project chỉ có fragments, chỉ có activities hay chỉ có views.Sau đây là một số lời khuyên nhưng bạn nên tự đưa ra quyết định của riêng mình:\n\n- Tránh sử dụng [nested fragments](https://developer.android.com/about/versions/android-4.2.html#NestedFragments) quá nhiều, bởi vì lỗi [matryoshka bugs](http://delyan.me/android-s-matryoshka-problem/) có thể xảy ra. Chỉ sử dụng nested fragments khi nó có ích với bạn (ví dụ, fragments trong ViewPager trong một fragment hoạt động như một màn hình), hoặc nếu nó là một quyết định chắc chắn và được hiểu rõ.\n- Tránh đặt quá nhiều code trong activities. Bất cứ khi nào có thể, hãy giữ cho chúng như một containers gọn nhẹ, tồn tại trong application mục đích chính cho quản lý lifecycle và các APIs giao diện quan trọng. Nên sử dụng các activity đơn fragment (single-fragment activities) thay vì activities đơn thuần - đăt code liên quan tới UI trong fragment. Việc này giúp nó có thể được sử dụng lại trong trường hợp bạn cần thay đổi để đặt trong một tabbed layout, hoặc trong một màn hình tablet đa fragment(multi-fragment tablet screen). Một activity nên kèm theo một fragment tương ứng.\n- Đừng lạm dụng các Android-level APIs ví dụ như phụ thuộc vào Intent cho các app's internal workings. Việc đó có thể sẽ ảnh hưởng tới Android OS và ứng dụng khác, tạo ra các lỗi(bug) và độ trễ(lag). \n- Ví dụ, app của bạn sử dụng Intents cho việc giao tiếp giữa các packages, bạn có thể vô tình tạo ra độ trễ vài giây, gây ảnh hưởng tới trải nghiệm người dùng nếu ứng dụng đó mở ngay khi boot OS.\n\n### Cấu trúc gói Java (Java packages architecture)\n\nJava architectures cho Android applications có thể gần tương tự như [Model-View-Controller](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller). Trong Android, [Fragment và Activity thực sự là các controller classes](http://www.informit.com/articles/article.aspx?p=2126865). Mặt khác, rõ ràng chúng là một phần của giao diện (user interface), do đó chúng cũng là views.\n\nDo đó, khó có thể phân loại fragments(hoặc activities) là controllers hay views. Tốt hơn là nên để fragments trong `fragments` package. Activities có thể để ở package cao nhất (top-level package). Nếu bạn có nhiều hơn 2 hoặc 3 activities thì bạnc cũng nên tạo riêng `activities` package.\n\nTrái lại, cấu trúc có thể được xây dựng như mô hình MVC cơ bản, với một `models` package chứa POJOs, lớp có thể chứa dữ liệu sau khi bóc tách JSON từ API responses, và một `views` package chứa những custom Views của bạn như notifications, action bar views, widgets, etc. Adapters giống như chất xám, nằm ở giữa data và views. Tuy nhiên, chúng cơ bản cần export một số Views qua `getView()`, vì vậy bạn có thể đặt `adapters` subpackage trong `views`.\n\nMột số lớp controllers ở mức application và gần tới Android system thì nên để trong `managers` package. Còn các lớp xử lý data, ví dụ như \"DateUtils\" nên được đặt trong `utils` package. Các lớp đảm nhiệm vai trò tương tác với backend nên đặt trong `network` package.\n\nTất cả package nên được sắp xếp từ các lớp phía backend tới các lớp phía user.\n\n```\ncom.futurice.project\n├─ network\n├─ models\n├─ managers\n├─ utils\n├─ fragments\n└─ views\n   ├─ adapters\n   ├─ actionbar\n   ├─ widgets\n   └─ notifications\n```\n\n### Resources\n\n**Đặt tên(Naming).** Dùng tên của loại resources để đặt làm tiếp đầu ngữ cho tên file, như `type_foo_bar.xml`. Ví dụ: `fragment_contact_details.xml`, `view_primary_button.xml`, `activity_main.xml`.\n\n**Sắp xếp file layout XMLs.** Nếu bạn không chắc chắn trong việc định dạng như nào cho đúng một file layout XML, bạn có thể tham khảo các quy ước dưới đây.\n\n-  Đặt một thuộc tính (attribute) trên một dòng, lùi vào 4 spaces\n- `android:id` luôn là attribute đầu tiên\n- `android:layout_****` nên đặt trên\n- `style` nên đặt dưới cùng\n- Tag closer `/>` nên để trên cùng một dòng, để tạo điều kiện thêm và sắp xếp attributes.\n- Thay vì đặt cố định text(hard-coding) trong`android:text`, nên sử dụng [Designtime attributes](http://tools.android.com/tips/layout-designtime-attributes) có sẵn trong Android Studio.\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <TextView\n        android:id=\"@+id/name\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentRight=\"true\"\n        android:text=\"@string/name\"\n        style=\"@style/FancyText\"\n        />\n\n    <include layout=\"@layout/reusable_part\" />\n\n</LinearLayout>\n```\n\nNhư là một quy tắc chuẩn,các attributes `android:layout_****` nên được định nghĩa trong file layout XML, còn các attributes `android:****` nên đặt trong file style XML. Quy tắc này cũng có một số ngoại lệ nhưng nhìn chung đúng với hầu hết các attributes. Theo như quy tắc này thì chúng ta chỉ nên đặt các layout và content attributes(positioning, margin, sizing) trong file layouts, còn các thuộc tính định nghĩa về chi tiết bề ngoài (như colors, padding, font) nên đặt trong file styles.\n\nLưu ý một số ngoại lệ:\n\n- `android:id` hiển nhiên là nên đặt trong file layouts.\n- `android:orientation` trong `LinearLayout` cũng nên đặt trong file layouts.\n- `android:text` nên đặt trong file layouts vì nó định nghĩa nội dung(content).\n- Trong một vài trường hợp nên định nghĩa style chung cho `android:layout_width` and `android:layout_height` nhưng mặc định thì những thuộc tính này nên đặt trong file layouts.\n\n<a name=\"styles\"></a>\n**Sử dụng styles.** Hầu hết các project cần sử dụng styles một các phù hợp, vì nếu không nó sẽ dẫn đến việc lặp lại việc khai báo thuộc tính cho một view. Ít nhất, bạn nên có một file style chung cho toàn bộ text content trong application. Ví dụ: \n\n```xml\n<style name=\"ContentText\">\n    <item name=\"android:textSize\">@dimen/font_normal</item>\n    <item name=\"android:textColor\">@color/basic_black</item>\n</style>\n```\n\nÁp dụng vào TextViews:\n\n```xml\n<TextView\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:text=\"@string/price\"\n    style=\"@style/ContentText\"\n    />\n```\n\nBạn có thể sẽ cần làm điều tương tự với buttons, nhưng đừng chỉ dừng lại ở hai thành phần trên. Nên khai báo các thành phần `android:****` attributes liên quan và có tính lặp lại vào một file style chung.\n\n<a name=\"splitstyles\"></a>\n**Chia một file style lớn thành các file styles nhỏ hơn.** Bạn không cần đặt mọi thứ trong một file `styles.xml`. Android SDK hỗ trợ nhiều files khác cùng nhau, tên file sẽ không ảnh hưởng vì Android quan tâm đến nội dung trong tags `<style>` bên trong file. Do đó bạn có thể khai báo files `styles.xml`, `styles_home.xml`, `styles_item_details.xml`, `styles_forms.xml`. Không giống như tên của thư mục resource cần phải đặt đúng để cho build system hiểu, tên file trong `res/values` có thể đặt tuỳ ý.\n\n<a name=\"colorsxml\"></a>\n**`colors.xml` được coi là một bảng màu.** File `colors.xml` chỉ nên giữ nhiệm vụ là định nghĩa tên màu với giá trị RGBA chứ không nên có nội dung nào khác. Không nên định nghĩa giá trị RGBA cho các loại buttons khác nhau.\n\n*Không nên khai báo như dưới đây:*\n\n```xml\n<resources>\n    <color name=\"button_foreground\">#FFFFFF</color>\n    <color name=\"button_background\">#2A91BD</color>\n    <color name=\"comment_background_inactive\">#5F5F5F</color>\n    <color name=\"comment_background_active\">#939393</color>\n    <color name=\"comment_foreground\">#FFFFFF</color>\n    <color name=\"comment_foreground_important\">#FF9D2F</color>\n    ...\n    <color name=\"comment_shadow\">#323232</color>\n```\n\nBạn sẽ dễ khai báo lặp lại giá trị RGBA trong kiểu định nghĩa này và sẽ phức tạp khi thay đổi một màu cơ bản khi cần. Bên cạnh đó, việc định nghĩa này liên quan đến một số trường hợp nhất đinh, giống như \"button\" hay \"comment\", và nên đặt trong a button style, không phải trong `colors.xml`.\n\nThay vì đó, nên khai báo như sau:\n\n```xml\n<resources>\n\n    <!-- grayscale -->\n    <color name=\"white\"     >#FFFFFF</color>\n    <color name=\"gray_light\">#DBDBDB</color>\n    <color name=\"gray\"      >#939393</color>\n    <color name=\"gray_dark\" >#5F5F5F</color>\n    <color name=\"black\"     >#323232</color>\n\n    <!-- basic colors -->\n    <color name=\"green\">#27D34D</color>\n    <color name=\"blue\">#2A91BD</color>\n    <color name=\"orange\">#FF9D2F</color>\n    <color name=\"red\">#FF432F</color>\n\n</resources>\n```\nNên hỏi bảng màu này từ designer. Tên có thể không nhất thiết phải là tên màu như \"green\", \"blue\", etc. Dùng các tên như \"brand_primary\", \"brand_secondary\", \"brand_negative\" hoàn toàn được chấp nhận. Việc định dạng colors như vậy sẽ giúp việc thay đổi colors dễ dàng và biết rõ ràng rằng có bao nhiêu màu khác nhau đang được sử dụng. Về tính thẩm mỹ, việc giảm số lượng màu cần dùng là rất quan trọng.\n\n<a name=\"dimensxml\"></a>\n**Đối với file dimens.xml cũng tương tự** Bạn cũng nên định nghĩa một \"bảng màu\" cho typical spacing and font sizes, như việc định nghĩa màu trong file colors.xml. Một ví dụ cho một file dimens:\n\n```xml\n<resources>\n\n    <!-- font sizes -->\n    <dimen name=\"font_larger\">22sp</dimen>\n    <dimen name=\"font_large\">18sp</dimen>\n    <dimen name=\"font_normal\">15sp</dimen>\n    <dimen name=\"font_small\">12sp</dimen>\n\n    <!-- typical spacing between two views -->\n    <dimen name=\"spacing_huge\">40dp</dimen>\n    <dimen name=\"spacing_large\">24dp</dimen>\n    <dimen name=\"spacing_normal\">14dp</dimen>\n    <dimen name=\"spacing_small\">10dp</dimen>\n    <dimen name=\"spacing_tiny\">4dp</dimen>\n\n    <!-- typical sizes of views -->\n    <dimen name=\"button_height_tall\">60dp</dimen>\n    <dimen name=\"button_height_normal\">40dp</dimen>\n    <dimen name=\"button_height_short\">32dp</dimen>\n\n</resources>\n```\n\nBạn nên sử dụng `spacing_****` dimensions cho việc bố trí(layouting), trong margins và paddings, thay vì các giá trị hard-coded, giống như strings. Việc này sẽ tạo sự thống nhất và dễ dàng cho việc sắp xếp và thay đổi styles và layouts.\n\n**strings.xml**\n\nĐặt tên strings với keys mà giống với namespaces, và việc lặp lại một giá trị cho 2 hoặc nhiều keys cũng không thành vấn đề. Ngôn ngữ thường phức tạp, vì vậy namespaces rất cần thiết cho việc định nghĩa ngữ cảnh (context) và mang lại sự rõ ràng.\n\n**Bad**\n```xml\n<string name=\"network_error\">Network error</string>\n<string name=\"call_failed\">Call failed</string>\n<string name=\"map_failed\">Map loading failed</string>\n```\n\n**Good**\n```xml\n<string name=\"error_message_network\">Network error</string>\n<string name=\"error_message_call\">Call failed</string>\n<string name=\"error_message_map\">Map loading failed</string>\n```\n\nKhông nên viết hoa toàn bộ chữ cái trong string. Nên sử dụng quy ước bình thường cho text (Ví dụ: chỉ viết hoa chữ cái đầu tiên). Nếu bạn cần hiển thị string dưới dạng các chữ cái viết hoa, thì bạn có thể sử dụng attribute [`textAllCaps`](http://developer.android.com/reference/android/widget/TextView.html#attr_android:textAllCaps) cho một TextView.\n\n**Bad**\n```xml\n<string name=\"error_message_call\">CALL FAILED</string>\n```\n\n**Good**\n```xml\n<string name=\"error_message_call\">Call failed</string>\n```\n\n<a name=\"deephierarchy\"></a>\n**Tránh sử dụng một hệ phân cấp sâu cho views.** Đôi khi bạn chỉ dùng LinearLayout cho việc sắp xếp các Views. Ví dụ như:\n\n```xml\n<LinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    >\n\n    <RelativeLayout\n        ...\n        >\n\n        <LinearLayout\n            ...\n            >\n\n            <LinearLayout\n                ...\n                >\n\n                <LinearLayout\n                    ...\n                    >\n                </LinearLayout>\n\n            </LinearLayout>\n\n        </LinearLayout>\n\n    </RelativeLayout>\n\n</LinearLayout>\n```\n\nMột số vấn đề có thể xảy ra. Ví dụ bạn sẽ gặp phải vấn đề về hiệu năng, bởi vì cây UI (UI tree) phức tạp sẽ làm processor xử lý khó hơn. Một vấn đề nghiêm trọng hơn là khả năng gặp phải lỗi này [StackOverflowError](http://stackoverflow.com/questions/2762924/java-lang-stackoverflow-error-suspected-too-many-views).\n\nVì vậy, cố gắng giữ cho hệ phân cấp Views ít cấp bậc nhất có thể. Bạn nên học cách sử dụng [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative.html), và [tối ưu layouts](http://developer.android.com/training/improving-layouts/optimizing-layout.html) và sử dụng [`<merge>` tag](http://stackoverflow.com/questions/8834898/what-is-the-purpose-of-androids-merge-tag-in-xml-layouts).\n\n<a name=\"webviews\"></a>\n** Nên chú ý vấn đề liên quan đến WebViews.** Khi bạn phải hiện thỉ một web page, ví dụ cho một bài báo, nên tránh xử lý phía client để clean the HTML hơn là yêu cầu \"*pure*\" HTML từ lập trình viên backend. [WebViews cũng có thể gây ra rò rỉ bộ nhớ](http://stackoverflow.com/questions/3130654/memory-leak-in-webview) khi bạn giữ một tham chiếu tới Activity, thay vì bound to the ApplicationContext. Tránh sử dụng một WebView cho các texts hay buttons đơn giản mà nên sử dụng TextViews và Buttons.\n\n\n### Test frameworks\n\nAndroid SDK's testing framework vẫn trong giai đoạn phát triển, đặc biệt là UI tests. Android Gradle currently hiện tại áp dụng một test task [`connectedAndroidTest`](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Testing). Test task này chạy JUnit tests mà bạn tạo ra, sử dụng extension của JUnit kết hợp với helpers cho riêng Android[extension of JUnit with helpers for Android](http://developer.android.com/reference/android/test/package-summary.html). Điều này có nghĩa là bạn cần thiết bị thật hoặc emulator để run tests. Bạn có thể theo dõi hướng dẫn chính thức của Google [[1]](http://developer.android.com/tools/testing/testing_android.html) [[2]](http://developer.android.com/tools/testing/activity_test.html) for testing.\n\n**Chỉ sử dụng [Robolectric](http://robolectric.org/) cho unit tests, không phải cho views.** Đây là một test framework với mục đích giúp test mà không cần thiết bị \"disconnected from device\" giúp tăng tốc độ phát triển, đặc biệt phù hợp với unit tests trên models và view models. Tuy nhiên, sử dụng Robolectric sẽ sinh ra lỗi nếu áp dụng cho UI tests. Bạn sẽ gặp vấn đề khi khi test thành phần UI liên quan đến animations, dialogs, etc, và việc này sẽ rất phức tạp bởi thực sự bạn đang \"đi trong bóng tối\" (test mà không nhìn thấy màn hình điều khiển).\n\n**[Robotium](https://code.google.com/p/robotium/) trong khi đó lại giúp việc viết UI tests dễ dàng.** Ví dụ, viết test cases sẽ đơn giản như sau:\n\n```java\nsolo.sendKey(Solo.MENU);\nsolo.clickOnText(\"More\"); // searches for the first occurrence of \"More\" and clicks on it\nsolo.clickOnText(\"Preferences\");\nsolo.clickOnText(\"Edit File Extensions\");\nAssert.assertTrue(solo.searchText(\"rtf\"));\n```\n\n### Emulators\n\nNếu nghề nghiệp chính của bạn là phát triển Android, thì bạn nên mua bản Pro (có license) cho [Genymotion emulator](http://www.genymotion.com/). Genymotion emulators chạy với tốc độ frames/sec nhanh hơn AVD emulators mặc định. Họ còn có tools cho việc demo app, giả lập chất lượng kết nối mạng, vị trí GPS,... Bên cạnh đó, Genymotion cũng rất lý tưởng cho connected tests. Bạn có thể dùng nhiều (không phải tất cả) các thiết bị khác nhau, vì vậy giá cho Genymotion license thực sự rẻ hơn việc mua nhiều thiết bị thật.\n\nĐiều nên chú ý là: Genymotion emulators không cài sẵn Google services như Google Play Store và Maps. Bạn cũng có thể cần test một số APIs của Samsung, vì vậy có một thiết bị Samsung thật là cần thiết.\n\n### Cấu hình Proguard\n\n[ProGuard](http://proguard.sourceforge.net/) về cơ bản được dùng để giảm kích thước và che đậy code trong package.\n\nBạn có thể dùng hoặc không dùng ProGuard, mặc định Gradle sẽ khai báo việc cấu hình Proguard khi build bản apk release.\n\n```groovy\nbuildTypes {\n    debug {\n        minifyEnabled false\n    }\n    release {\n        signingConfig signingConfigs.release\n        minifyEnabled true\n        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n    }\n}\n```\n\nĐể xác định phần code nào nên giữa lại, phần code nào cần che giấu (obfuscated), bạn phải chỉ rõ một hoặc vài điểm đánh dấu (entry points). Những entry points về cơ bản là các classes với main methods, applets, midlets, activities, etc.\nAndroid framework sử dụng một cấu hình mặc định cho Proguard và bạn có thể tìm thấy trong `SDK_HOME/tools/proguard/proguard-android.txt`. Sử dụng cấu hình trên, phần chỉnh sửa thêm cho riêng từng project sẽ được định nghĩa trong file `my-project/app/proguard-rules.pro`. Những khai báo này sẽ bổ sung thêm cho phần cấu hình mặc định.\n\nNếu bạn cấu hình sai ProGuard thì thường bạn sẽ thấy ứng dụng crash ngay khi startup và báo lỗi `ClassNotFoundException` hay `NoSuchFieldException` hoặc tương tự, thậm chí build command (i.e. `assembleRelease`) không hề báo lỗi hay cảnh báo.\nĐiều này thường xảy ra bởi vì một trong hai lý do: \n\n1. ProGuard đã xoá class, enum, method, field hoặc annotation, mà nó tự xem là không cần thiết.\n2. ProGuard đã thay đổi tên class, enum hoặc field, nhưng nó lại được sử dụng gián tiếp bằng tên chính.Ví dụ: qua Java reflection.\n\nKiểm tra `app/build/outputs/proguard/release/usage.txt` để xem các object đã bị xoá.\nKiểm tra `app/build/outputs/proguard/release/mapping.txt` để xem các object đã bị đổi tên.\n\nĐể tránh việc ProGuard *xoá* classes hoặc class members, dùng `keep` trong ProGuard config:\n```\n-keep class com.futurice.project.MyClass { *; }\n```\n\nĐể tránh việc Proguard *đổi tên* classes hoặc class members,  dùng `keepnames`:\n```\n-keepnames class com.futurice.project.MyClass { *; }\n```\n\nTìm hiểu thêm các ví dụ [Proguard](http://proguard.sourceforge.net/#manual/examples.html).\n\n**Ngay từ ban đầu, hãy build bản release** để kiểm tra ProGuard có được cấu hình đúng hay không. Bên cạnh đó, bất cứ khi nào thêm một thư viện mới, hãy build bản release và test apk trên thiết bị. Đừng đợi đến khi app của bạn hoàn thành version \"1.0\" mới build bản release. Việc này giúp gặp và sửa vấn đề nhanh hơn.\n\n**Gợi ý.** Lưu file `mapping.txt` cho mỗi bản release mà bạn publish cho users. Bằng cách giữ bản copy của file `mapping.txt` cho mỗi bản build release, bạn sẽ đảm bảo rằng bạn có thể debug một vấn đề nếu user gặp phải và submit một bản obfuscated stack trace.\n\n**DexGuard**. Nếu bạn cần một công cụ tốt hơn cho việc tối ưu hay che giấu code khi release, hãy xem xét việc dùng [DexGuard](http://www.saikoa.com/dexguard), bản thương mại của ProGuard. Nó cũng giúp cho việc chia nhỏ Dẽ files để giải quyết vấn đề 65k methods limitation.\n\n### Lưu trữ dữ liệu (Data storage)\n\n\n#### SharedPreferences\nNếu bạn cần lưu trữ các dữ liệu đơn giản như flags và ứng dụng bạn chạy trên tiến trình đơn (single process) thì SharedPreferences có lẽ đủ cho bạn. Đây nên là một lựa chọn mặc định.\n\nCó 2 trường hợp bạn không nên sử dụng SharedPreferences:\n\n* *Hiệu năng(Performance)*: Dữ liệu của bạn phức tạp hoặc nhiều.\n* *Xử lý truy cập dữ liệu đa tiến trình (Multiple processes accessing the data)*: Ví dụ, bạn có widgets và remote services chạy trên tiến trình riêng và cần dữ liệu đồng bộ (synchronized data).\n\n\n#### ContentProviders\n\nTrong trường hợp SharedPreferences không đủ cho bạn, bạn nên sử dụng platform standard ContentProviders, vì nó nhanh và an toàn.\n\nMột vấn đề của ContentProviders là nó tốn nhiều thời gian cho việc viết code khi setup và cũng rất ít hướng dẫn chất lượng về vấn đề này. Tuy nhiên, nếu có thể thì nên tạo ContentProvider bằng cách sử dụng thư viện như [Schematic](https://github.com/SimonVT/schematic), nó sẽ giúp giảm đáng kể công sức và thời gian.\n\nNhưng đôi khi bạn vẫn cần tự viết parsing code để đọc data objects từ Sqlite và ngược lại. Bạn có thể serialize data objects, ví dụ dùng Gson, và chỉ lưu trữ dữ liệu dưới dạng string. Trong trường hợp này, performance sẽ kém đi nhưng bạn giảm được việc phải khai báo column cho tất cả các trường trong lớp dữ liệu (data class).\n\n\n#### Sử dụng một thư viện ORM\n\nNhìn chung, chúng tôi không khuyến khích sử dụng Object-Relation Mapping library trừ khi bạn có dữ liệu đặc biệt phức tạp và vô cùng cần thiết. Thư viện ORM thường phức tạp và cần thời gian tìm hiểu. Nếu bạn quyết định dùng nó, bạn nên xác định xem nó có được xử lý an toàn _process safe_ hay không, vì có một sự đáng ngạc nhiên là rất nhiều các giải pháp ORM hiện tại không được xử lý tốt.\n\n\n### Sử dụng Stetho \n\n[Stetho](http://facebook.github.io/stetho/) là một debug bridge cho Android applications được phát triển bởi Facebook. Nó tích hợp được với Chrome desktop browser's Developer Tools. Stetho cho phép bạn dễ dàng giám sát ứng dụng, đáng chú ý là network traffic. Nó cũng cho phép bạn giám sát, theo dõi và dễ dàng thay đổi SQLite databases và shared preferences. Tuy nhiên, bạn nên đảm bảo rằng Stetho chỉ được bật khi build bản debug chứ không phải bản release.\n\n### Gửi lời cảm ơn tới (Thanks to)\n\nAntti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton and other Futurice developers for sharing their knowledge on Android development.\n\n### Giấy phép (License)\n\n[Futurice Oy](http://www.futurice.com)\nCreative Commons Attribution 4.0 International (CC BY 4.0)\n"
  }
]