Brief discussion on the document structure of Android project and Suggestions on standardized deployment

  • 2020-05-07 19:39:48
  • OfStack

A few words

Use Gradle and its recommended project framework Put sensitive data such as passwords into gradle.properties Instead of writing your own Http client, use the Volley or OkHttp libraries Use the Jackson library to parse JSON data Avoid Guava and Dalvik 65K methods limit don't use too many libraries Use Fragment to draw the UI interface Activity is mainly used to manage Fragment The layout file XML is also code, so organize it well In the layout file, styles is used to avoid duplicate properties Use multiple style files instead of one large style file Keep your color.xml short and DRY defined Also keep dimens.xml DRY, define generic constants Do not create a layout that is too deep Avoid client handling of WebView and be aware of memory leaks Use Robolectric for unit testing and Robotium for connection (UI) testing The emulator USES Genymotion 1 always use ProGuard or DexGuard

2. Detailed
Android SDK
put your Android SDK in your home directory or somewhere else that is not related to the application. 1 some IDEs will associate SDK when installed and put SDK in the same directory as IDE. When you need to upgrade (reinstall) IDE or replace IDE, you will find the worst. Also, if your IDE is running under one user account instead of root, don't put SDK in the system-level directory, or you'll need sudo permission to use it.

Build System
The default choice for
is Gradle. Ant is too restrictive and too large. With Gradle, you can easily:
- compile different flavours or variants applications
- create simple class-script tasks
- manage and download dependencies
- custom keystores
- etc.
Android's Gradle plug-in is also specified by Google as a new standard compilation system, and Google continues to upgrade it.

project structure
There are two popular options for
: the old Ant & Eclipse ADT project structure; New Gradle & Android Studio project structure. You should choose the latter. If your project USES the old structure, replace it.
The old structure


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

The new structure


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

The main difference with the new structure is the split of the 'source code set' (main,androidTest), which is an idea from Gradle.
Using the highest level "app" helps to distinguish your app from other library items that your application references (e.g., library-foobar). settings.gradle then maintains the application's index to these libraries, while app/ build.gradle can point to these libraries.

Gradle configuration
general architecture please follow Google's guide on Gradle for Android;
Small tasks (scripts), you can use Gradle to make small tasks instead of Shell, Python, Perl, Gradle's documentation;
The password. In your application build.gradle you will need to define signingConfigs for publication compilation. The details are as follows:
Do not write as follows, this will appear in your version control system:


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

Instead, you should create an gradle.properties file that will not be added to the version control system


KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

This file will be automatically imported by gradle, so you can use it in build.gradle like this:


signingConfigs { 
  release {
  try{
    storeFile file("myapp.keystore")  
    storePasswordKEYSTORE_PASSWORD  
    keyAlias"thekey"
    keyPasswordKEY_PASSWORD
 } catch(ex) {
  thrownewInvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")  
  }
 }}

(refer to the original document if using Maven)

library
Jackson is a library of Java that converts objects to JSON data. Gson is a similarly good choice. However, we think Jsckson is better because it supports a variety of ways to handle JSON: streaming, memory tree model, and drive JSON-POJO data binding. But remember, Jackson is bigger than GSON, so you have to think about it, and if you want to avoid 65k methods limit it's better to use GSON. Other options: Json-smart and Boon JSON
Network, cache, and images. Use Volley or Retrofit. Volley can also be used to load and cache images. If you choose Retrofit, you can use Picasso to load and cache images. OkHttp is then used to execute a valid HTTP request. The three: Retrofit, Picasso and OkHttp all come from the same company, so they complement each other. OkHttp can be used to connect to Volley.
RxJava is a responsive programming library that handles, in other words, asynchronous events. (refer to the original document for details)
Retrolambda is an Java library that helps you use Android or other Lambda expressions on the JDK8 platform. (refer to the original document for details)
Finally, remember the dex method limit and don't use too many libraries. The Android application, when packaged as an dex file, has one maximum limit: 65535 reference methods [1][2][3]. Serious errors will occur if you exceed the limit. Therefore, don't use just too many libraries, use the dex-method-counts tool to decide which classes to use to stay within the limits, and especially avoid the Guava library, which contains more than 13k methods.)
Activities and Fragments
Fragments should be the default option for you to deploy UI in Android. Fragments can be reused in your application. We recommend using Fragements instead of activities to draw the interface based on the following points:

The solution is a multi-view layout. The main reason Fragments was introduced was to extend mobile apps to platform computers, so you can display both A and B views on a tablet, but only A or B on a phone. If your application starts with Fragment, it will be easier to use on multiple devices. Screen to screen communication. Android's API does not provide a suitable way to transfer complex data (such as Java objects) between Activity. However, with Fragment, you can use Activity as a channel for communication between its children Fragment. Even though this is much better than Activity-to-Activity communication, I still recommend that you adopt Event Bus architecture, such as Otto or greenrobot EventBus, as a more concise solution. If you don't want to take additional libraries, RxJava can also be used to implement 1 EventBus. Fragment can be used to do more than just lay out UI. You can add an Fragment without the UI interface as a backend server for Activity. You can even create one Fragment to implement Fragment switch logic instead of having Activity handle Fragment switch logic. Fragment can even manage ActionBar. You can choose one Fragment without the UI interface to manage ActionBar, or you can choose each currently visible Fragment to handle the parent Activity ActionBar by itself. See here. However, we do not recommend overusing nested Fragments, which can lead to matryoshka vulnerability. From an architectural perspective, your application should have 1 top-level Activity, which will contain most of the business-related fragments. You can also create some other supporting Activities, as long as their communication with the main Activity is simple -- it looks like Intent.setData () or Intent.setAction ().

Java package structure

The Java structure in the Android application is close to the MVC structure (Model-View-Controller). In Android, Fragment and Activity are actually controller classes. On the other hand, they are part 1 of the user interaction, that is, they belong to the view View class.
As a result, it is difficult to tell strictly whether Fragment (or Activity) is a controller or a view. So from the Java package point of view, it's best to put the Fragment in their own fragments package and then Activity in the most advanced package (follow the advice above). Of course, if you want to have two or more Activity, you create one activitys package.
In this case, the whole structure looks like a typical MVC structure. One Models package contains POJOs, which is used to convert Json data obtained by API interface. One views package contains Views, notifications, action bar views, widgets, etc. Adapters is an intermediate layer between the data and the view. However, they usually need to output View views via getView(), so you can place adapters in the subpackage location of views package.
Some application-level controller classes that belong only to the Android system should be in the managers package. Various data processing classes, such as DateUtils, can be placed in the utils package. Classes that interact with the backend server should be in the network package.
In short, the overall architecture from interacting with the server to interacting with the user can be designed as follows:


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

resource file
named
follows the prefix convention, similar to type_foo_bar.xml, such as fragment_contact_details.xml, view_primary_Robolectric.xml, activity_main.xml.

organization layout file
if you don't know how to normalize a layout XML file, refer to the following convention:

1 attribute per line, indent 4 Spaces; android:id is always placed in the first; android:layout_** attributes to be placed at the top; The style attribute is placed at the tail; End flag bit / > To monopolize 1 row, to help sort or add attributes;Do not write hard code, such as android:text, or Designtime attributes for Android Studio.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
>

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

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

</LinearLayout>

Related articles: