Android development best practice manual is the only one in the whole network, well-known large enterprises are using it, it is recommended to collect

table of Contents

  • Foreword
  • Summary
  • Androids SDK
  • Build system
  • Project summary
  • Gradle configuration
  • IDE integrated development environment and text editor
  • Class library
  • Activities and Fragments
  • Java package structure
  • Test framework
  • Emulator
  • Obfuscated configuration

Foreword

This article is a summary of best practices by Android developers at Futurice. Following these guidelines can avoid repetitive wheel manufacturing. If you are interested in iOS or Windows Phone development, then also take a look at iOS best practices and Windows client development best practices.

Summary

  • Use Gradle and its recommended engineering structure
  • Put passwords and sensitive data in gradle.properties
  • Don't write your own HTTP client, use Volley or OkHttp library
  • Parsing JSON data using Jackson library
  • Avoid using Guava and use some libraries to avoid 65k method limit (maximum 65536 methods can be executed in an Android program)
  • Use Fragments to present a UI view
  • Use Activities just to manage Fragments
  • Layout is XMLs code, organize them
  • When using layout XMLs, use styles files to avoid duplicate attributes
  • Use multiple style files to avoid a single large style file
  • Keep your colors.xml short DRY (don't repeat yourself), just define the color palette
  • Always use dimens.xml DRY (don't repeat yourself), define universal constants
  • Don't make a deep ViewGroup
  • Avoid processing on the client when using WebViews, beware of memory leaks
  • Use Robolectric unit test, Robotium do UI test
  • Use Genymotion as your emulator
  • Always use ProGuard and DexGuard confusion to project

Androids SDK

Place your Android SDK in a location unrelated to your home directory or other applications. When installing some IDEs that include SDK, the SDK may be placed in the same directory of the IDE. When you need to upgrade (or reinstall) the IDE or replace the IDE, it will be very troublesome. In addition, if your IDE is a normal user, not running under root, you should also avoid putting the SDK in a system-level directory that requires sudo permissions.

Build system

Your default compilation environment should be Gradle. Ant has many limitations and is also redundant. Using Gradle, it is convenient to complete the following tasks:

  • Build variants of different versions of the APP
  • Make simple script-like tasks
  • Management and download dependencies
  • Custom key
  • More

At the same time, the Android Gradle plugin is being actively developed by Google as a new standard build system.

Project summary

There are two popular structures: the old Ant & Eclipse ADT project structure, and the new Gradle & Android Studio project structure. You should choose the new project structure. If your project is still using the old structure, consider giving up. The project is transplanted to the new structure.

Old structure

New structure

[External chain image transfer failed, the source site may have an anti-theft chain mechanism, it is recommended to save the image and upload it directly (img-Eb2YhruK-1585838741642) (https://upload-images.jianshu.io/upload_images/22459598-5d2d08de3e07fceb?imageMogr2 / auto-orient / strip% 7CimageView2 / 2 / w / 1240)]

The main differences are:

  • The new structure clearly separates 'source sets' (main, androidTest), a concept of Gradle. You can do it, for example, add the source group 'paid' and 'free' in src, which will become the source code of both paid and free modes of your application.
  • When your project references a third-party project library (for example, library-foobar), it is very useful to have a top-level package name app to distinguish your application from third-party library projects. Then settings.gradle constantly references these library projects, of which app / build.gradle can be referenced.

Gradle configuration

Common structure  reference

Google’s guide on Gradle for Android

Small tasks  in addition to (shell, Python, Perl, etc ) these scripting language, you can also make use Gradle task. For more information, please refer to Gradle's documentation.

 Your app ’s password when the version is released

build.gradle you need to define signingConfigs At this point you should avoid the following:

Don't do this. This will appear in version control.

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

Instead, create a gradle.properties file without adding a version control system.

KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

That file is automatically introduced by gradle, you can use it in the buld.gradle file, for example:

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

Use the Maven dependency scheme instead of using the imported jar package scheme. If you explicitly use jar files in your project, then they may become permanent versions, such as 2.1.1. Downloading the jar package to update them is very cumbersome. This problem Maven is very Good solution, this is also the recommended method in the Android Gradle build. You can specify a range of versions, such as 2.1. +, And then Maven will automatically upgrade to the latest version specified, for example:

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

IDE integrated development environment and text editor

  • No matter what editor you use, be sure to build a good engineering structure editor. Everyone has their own choice. It is your own responsibility to let your editor operate according to the engineering structure and build system.
  • Android Studio is the first to be promoted because it is developed by Google and is closest to Gradle. It uses the latest engineering structure by default. It has reached the beta stage (currently there is already release 1.0), and it is customized for Android development.
  • You can also use Eclipse ADT, but you need to configure it because it uses the old engineering structure and Ant as the build system. You can even use plain text editors such as Vim, Sublime Text, or Emacs. In that case, you need to use the Gardle and adb command lines.
  • If using Eclipse to integrate Gradle is not for you, you just use the command line to build the project, or migrate to Android Studio.
  • No matter what development tool you use, just make sure that Gradle and the new project structure maintain the official way to build the application and avoid adding your editor configuration file to version control.
  • For example, avoid adding Ant build.xml files. Especially if you change the configuration of Ant, do n’t forget to keep build.gradle up to date and working. At the same time, treat other developers well and don't force change their development tools and preferences.

Class library

Jackson is a class library that converts java objects to JSON and JSON to java classes. Gson is a popular solution to this problem. However, we found Jackson to be more efficient because it supports alternative methods for handling JSON: streams, memory tree models, and traditional JSON-POJO data binding. However, please keep in mind that the Jsonkson library is larger than GSON, so depending on your situation, you may choose GSON to avoid APP 65k method limitations. Other options: Json-smart and Boon JSON

There are several interactive solutions for network requests, caching, and image execution request backend servers. You should consider implementing your own network client. Use Volley or Retrofit. Volley also provides image cache classes. If you choose to use Retrofit, then consider using Picasso to load images and cache, and use OkHttp as an efficient network request. Retrofit, Picasso and OkHttp are all developed by the same company (Note: developed by Square), so they can run together well. OkHttp can also use Volley with Volley.

RxJava is a functional reactive library, in other words, it can handle asynchronous events. This is a powerful and promising model and may also cause confusion because it is so different. We recommend careful consideration before using this library to structure the entire application. Some projects are completed using RxJava, if you need help, you can get in touch with these people: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. We also wrote some blogs: [1 ], [2], [3], [4].

If you have used Rx before, start using it from the API response. In addition, start with simple UI event handling, such as clicking events or entering events in the search bar. If you have confidence in your Rx technology and want to apply it to your overall architecture, then please write Javadocs in the complicated part. Please keep in mind that other developers who are not familiar with RxJava may find it difficult to understand the entire project. Do your best to help them understand your code and Rx.

Retrolambda is a Java library that uses Lambda expression syntax on Android and pre-JDK8 platforms. It helps keep your code compact and readable, especially when you use functional style programming such as RxJava. When using it, first install JDK8, set it as the SDK path in the Android Studio project structure dialog box, set the JAVA8_HOME and JAVA7_HOME environment variables at the same time, and then configure build.gradle in the project root directory:

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

At the same time add in each module's build.gradle

apply plugin: 'retrolambda'
android {   
 compileOptions {   
 sourceCompatibility
 JavaVersion.VERSION_1_8   
 targetCompatibility 
JavaVersion.VERSION_1_8
}
retrolambda {  
  jdk System.getenv("JAVA8_HOME")  
  oldJdk System.getenv("JAVA7_HOME")   
 javaVersion
 JavaVersion.VERSION_1_7
}

Android Studio provides Java8 lambdas strap is code hint support. If you are not familiar with lambdas, just start learning by referring to the following:

  • Any method that contains only one interface is "lambda friendly" and the code can be folded into a more compact syntax
  • If you have questions about parameters or similar, write a normal anonymous inner class and let Android Status generate a lambda for you.
  • Beware of the limitation of the number of dex methods, while avoiding the use of too many Android libraries. When packaged into a dex file, there is a hard limit of 65535 application methods [1] [2] [3]. When you break the 65k limit you will see a fatal error. Therefore, use a normal range of library files and use the dex-method-counts tool to determine which libraries can be used under the 65k limit. In particular, avoid using the Guava library because it contains more than 13k methods.

Activities and Fragments

Fragments should be your default choice for implementing the UI interface. You can reuse Fragments user interface to compose your application. We strongly recommend using Fragments instead of activities to present UI interfaces for the following reasons:

  • Provide multi-pane layout solutions

The introduction of Fragments mainly extends the mobile application to the tablet, so on the tablet you may have two panes A and B, but on the mobile application A and B may fill the entire screen respectively. If your application uses fragments from the beginning, it will be very simple to adapt your application to other screens of different sizes in the future.

  • Data communication between screens

Send complex data (such as Java objects) from one Activity to another Activity, Android API does not provide a suitable method. But with Fragment, you can use an activity instance as a communication channel for this activity's subfragments. Even if this is better than the communication between Activity and Activity, you also want to consider using Event Bus architecture, such as Otto or greenrobot EventBus as a more concise implementation. If you want to avoid adding another library, RxJava can also implement an Event Bus.

  • Fragments are generally not only UI

You can have a fragment without an interface as an activity to provide background work. Further you can use this feature to create a fragment that contains the logic to change other fragments instead of putting this logic in the activity.

  • Even ActionBar can be managed using internal fragments

You can choose to use a fragment without a UI interface to specifically manage the ActionBar, or you can choose to add its own action in each Fragment as the ActionBar of the parent Activity. Reference.

Unfortunately, we do not recommend the extensive use of nested fragments, as they sometimes cause matryoshka bugs. We only use fragments extensively when it makes sense (for example, a ViewPager that slides horizontally in a fragment like a screen) or if he is indeed a wise choice.

At an architectural level, your app should have a top-level activity to contain most business-related fragments. You may also have some auxiliary activities, these auxiliary activities communicate with the main activity is simply limited to these two methods  Intent.setData () or Intent.setAction () or similar methods.

Java package structure

  • The Android application is roughly a Model-View-Controller structure in Java. In Android, Fragment and Activity are usually controller classes (http://www.informit.com/articles/article.aspx?p=2126865). In other words, they are part of the user interface, which is also the Views view section.
  • Because of this, it is difficult to strictly divide fragments (or activities) strictly into controllers or view views. It is best to put them in their own fragments package. As long as you follow the recommendations mentioned earlier, Activities can be placed in the top-level directory. If you plan to have more than 2 or 3 activities, then create an activity package.
  • However, this architecture can be seen as another form of MVC that contains JSON data to be parsed by the API response to populate the POJO models package. And a views package to contain your custom views, notifications, navigation views, widgets, etc. Adapter Adapter is between the data and the view. However, they usually need to export some views through the getView () method, so you can put the adaptors package in the views package.
  • Some controller role classes are application-level and close to the system. These classes are placed under the managers package. Some complicated data processing classes, such as "DateUtils", are placed under the utils package. Interacting with the backend is responsible for the network processing class, which is placed under the network package.
  • In summary, arrange them closest to the user rather than to the back end.
com.futurice.project
├─ network
├─ models
├─ managers
├─ utils
├─ fragments
└─ views   
├─ adapters   
├─ actionbar  
 ├─ widgets   
└─ notifications

Resources

  • Naming follows the convention of prefixes indicating types, like type_foo_bar.xml. For example: fragment_contact_details.xml, view_primary_button.xml, activity_main.xml.
  • Organizing layout files If you are not sure how to typeset a layout file, following the rules may help.
  • One line per attribute, indented by 4 spaces
  • android: id is always used as the first attribute
  • android: layout _ **** attribute is on the top
  • style attribute at the bottom
  • Close tag /> Start a new line, help to adjust and add new attributes
  • Consider using

Designtime attributes Design time attributes, Android Studio has provided support, rather than hard-coded android: text (Translator's Note: You can also refer to this blog link in stormzhang).

<?xml version="1.0" encoding="utf-8"?>

As a rule of thumb, the android: layout_ attribute should be defined in layout XML, while other attributes android: should be placed in styler XML. There are exceptions to this rule, but it generally works well. The whole idea of ​​this idea is to keep the layout attributes (positioning, margin, sizing) and content attributes in the layout file, and put all the appearance details attributes (colors, padding, font) in the style file.

The exceptions are the following:

  • android: id should obviously be in the layout file
  • android: orientation in layout files is usually more meaningful for a LinearLayout layout
  • android: text Because it is defined content, it should be placed in the layout file
  • Sometimes it makes more sense to put the android: layout_width and android: layout_height attributes in a style as a general style, but by default these should be placed in the layout file.

Using styles  Almost every project requires proper use of style files, because it is very common for a view to have a repeated appearance. For most text content in the application, at least you should have a common style file, for example:

Apply to TextView:

You may need to do the same for button controls, don't stop there. Put a set of related and repeated android: **** attributes into a common style.

** Split a large style file into multiple files ** You can have multiple styles.xml files. The Android SDK supports other files. The name of the styles file has no effect. What works is that the files in the xml 标签。因此你可以有多个style文件styles.xml,style_home.xml,style_item_details.xml,styles_forms.xml。 不用于资源文件路径需要为系统构建起的有意义,在res/valuesdirectory in the file can be named arbitrarily.

colors.xml is a color palette.  In your colors.xml file, it should just map the name of the color to an RGBA value, and nothing else. Do not use it to define RGBA values ​​for different buttons.

Do not do this

#FFFFFF #2A91BD #5F5F5F #939393 #FFFFFF #FF9D2F … #323232

Using this format, you can easily start to repeatedly define RGBA values, which makes it very complicated to change the basic color changes if necessary. At the same time, these definitions are associated with some environments, such as button or comment, should be placed in a button style, rather than in the color.xml file.

Instead, do this:

#FFFFFF #DBDBDB #939393 #5F5F5F #323232 #27D34D #2A91BD #FF9D2F #FF432F

Ask the application designer for this palette. The name does not need to be the same as "green", "blue", etc. Names like "brand_primary", "brand_secondary", "brand_negative" are also completely acceptable. Standard colors like this can be easily modified or refactored, making it clear how many different colors are used in the application. Usually for a UI with aesthetic value, it is very important to reduce the types of colors used.

Treating the dimens.xml file as you do with colors.xml is the same as defining a color palette . You should also define a "palette" of gaps and font sizes. A good example is as follows:

22sp 18sp 15sp 12sp 40dp 24dp 14dp 10dp 4dp 60dp 40dp 32dp

When writing margins and paddings during layout, you should use the spacing _ **** format for layout instead of writing values ​​directly like String strings. Writing this way will be very sensational and will make it very easy to organize and change the style or layout.

** Avoid deep view structure ** Sometimes in order to place a view, you may try to add another LinearLayout. You may use this method to solve:

<RelativeLayout … > <LinearLayout … > <LinearLayout … > <LinearLayout … >

Even if you don't use it very clearly in a layout file, if you go from a view inflate (this inflate cannot be translated, everyone understands it) to other views in a Java file, it may happen.

May cause a series of problems. You may encounter performance problems because of the need to deal with a complex UI tree structure. It may also cause the following more serious problem StackOverflowError.

So try to keep your view tree: learn how to use RelativeLayout, how to optimize your layout and how to use `` tags.

Be careful about WebViews . If you have to display a web view, for example, for a news article, avoid doing client-side HTML work, it is best to ask the back-end engineer to help him return a "pure" HTML. WebViews can also cause memory leaks when keeping their activities cited, rather than being bound to the ApplicationContext. When using simple text or buttons, avoid using WebView, then use TextView or Buttons is better.

Test framework

The testing framework of the Android SDK is still in its infancy, especially regarding UI testing. Android Gradle currently implements a test called connectedAndroidTest, which uses a JUnit extension of JUnit with helpers for Android. You can run the JUnit test you generated,

** Robolectric is used only for unit testing, and views are not needed. ** It is the most demanded "off-device" test to speed up development. In very occasions, unit testing of models and view models is done. However, when using Robolectric testing, it is inaccurate and does not completely test the UI. When you test UI elements, dialog boxes, etc. related to animation, there will be problems, mainly because you are "working in the dark" (testing without a controllable interface)

_Robotium makes writing UI tests very easy. _ For UI tests you do n’t need Robotium to run a test to connect to the device. But it may be beneficial to you because it has many to help the class get and analyze the view, control the screen. The test case looks as simple as this:

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

Emulator

If you develop Android apps full time, then buy a Genymotion emulatorlicense. The Genymotion emulator runs at a faster second frame rate than a typical AVD emulator. He has tools to demonstrate your APP, high-quality simulated network connection, GPS location, and so on. It also has an ideal connection test. If you are involved in adapting to many different devices, buying a Genymotion copyright is much cheaper than buying many real devices.

Note: The Genymotion simulator does not load all Google services, such as Google Play Store and Maps. You may also need to test the API specified by Samsung. If so, you still need to purchase a real Samsung device.

Obfuscated configuration

ProGuard is a tool that is widely used in Android projects to compress and obfuscate packaged source code.

Whether you use ProGuard depends on the configuration of your project. When you build a release version of the apk, you should usually configure the gradle file.

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

In order to decide which code should be retained and which code should be obfuscated, you have to specify one or more entity classes in your code. These entities should be specified classes containing main methods, applets, midlets, activities, etc. The Android framework uses a default configuration file, which can be found in the SDK_HOME / tools / proguard / proguard-android.txt directory. The project-specific obfuscation rules specified by the custom project, as defined in my-project / app / proguard-rules.pro, will be added to the default configuration.

A common question about ProGuard is to see if the application crashes and reports ClassNotFoundException or NoSuchFieldException or similar exceptions, even if the compilation is successful without warning. This means the following two possibilities:

ProGuard has removed classes, enumerations, methods, member variables or annotations, considering whether it is necessary.

ProGuard confuses the names of classes, enumerations, and member variables, but these names are used as the original names, such as through reflection in Java.

Check the app / build / outputs / proguard / release / usage.txt file to see if the object in question has been removed. Check the app / build / outputs / proguard / release / mapping.txt file to see if the object in question is confused.

In order to prevent ProGuard from stripping away needed classes or class members, add a keep options to your proguard config: In order to prevent ProGuard from stripping the required classes and class members, add a keep option in your proguard configuration file:

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

To prevent ProGuard from confusing some classes and members, add keepnames:

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

Check out some examples in this template's ProGuard config. For more examples, please refer to Proguard.

At the beginning of the construction project, a version was released to check whether the ProGuard rules were correct and kept important parts. At the same time whenever you add a new class library, make a release version, at the same time the apk runs on the device to test. Don't wait for your app to release the "1.0" version before doing version release. At that time, you may encounter a lot of unexpected exceptions, and it will take some time to fix them.

Tips Each time you release a new version, you must write mapping.txt. Every time a version is released, if the user encounters a bug, he also submits an obfuscated stack trace. By keeping the mapping.txt file, determine the problems you can debug.

 If you need core tools to optimize DexGuard , and specifically confuse the release code, consider using DexGuard, a commercial software, ProGuard is also developed by their team. It will easily split the Dex file to solve the 65K method limitation problem.

The article is not easy, if you like this article, or it is helpful to you, I hope everyone will like it and forward it. The article will be updated continuously. Absolutely dry goods! ! !

Published 34 original articles · Like1 · Visits 756

Guess you like

Origin blog.csdn.net/Android725/article/details/105281517