您的位置:首页 > 移动开发 > Android开发

Best practices in Android development

2016-03-05 14:02 627 查看


超级好的一片文章,推荐阅读 原文地址


Lessons learned from Android developers in Futurice.
Avoid reinventing the wheel by following these guidelines. If you are interested in iOS or Windows Phone development, be sure to check also our iOS
Good Practices and Windows
App Development Best Practices documents.





Summary


Use
Gradle and its recommended project structure


Put
passwords and sensitive data in gradle.properties


Use
the Jackson library to parse JSON data


Don't
write your own HTTP client, use Volley or OkHttp libraries


Avoid
Guava and use only a few libraries due to the 65k method limit


Use
Fragments to represent a UI screen


Use
Activities just to manage Fragments


Layout
XMLs are code, organize them well


Use
styles to avoid duplicate attributes in layout XMLs


Use
multiple style files to avoid a single huge one


Keep
your colors.xml short and DRY, just define the palette


Also
keep dimens.xml DRY, define generic constants


Do
not make a deep hierarchy of ViewGroups


Avoid
client-side processing for WebViews, and beware of leaks


Use
Robolectric for unit tests, Robotium for connected (UI) tests


Use
Genymotion as your emulator


Always
use ProGuard or DexGuard


Use
SharedPreferences for simple persistence, otherwise ContentProviders


Use
Stetho to debug your application


Android
SDK

Place your Android SDK somewhere in your home directory or some other application-independent
location. Some 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, or when changing IDEs. Also avoid putting the SDK in another system-level directory that
might need sudo permissions, if your IDE is running under your user and not under root.


Build
system

Your default option should be Gradle. Ant is much more limited and also more verbose. With Gradle,
it's simple to:

Build different flavours or variants of your app
Make simple script-like tasks
Manage and download dependencies
Customize keystores
And more

Android's Gradle plugin is also being actively developed by Google as the new standard build system.


Project
structure

There are two popular options: 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 uses the old structure, consider it legacy and start porting it to
the new structure.

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


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 is that the new structure explicitly separates 'source sets' (
main
,
androidTest
),
a concept from Gradle. You could, for instance, add source sets 'paid' and 'free' into
src
which will have source code for
the paid and free flavours of your app.

Having a top-level
app
is useful to distinguish your app from other library projects (e.g.,
library-foobar
)
that will be referenced in your app. The
settings.gradle
then keeps references to these library projects, which
app/build.gradle
can
reference to.


Gradle
configuration

General structure. Follow Google's guide on Gradle for Android

Small tasks. Instead of (shell, Python, Perl, etc) scripts, you can make tasks in Gradle. Just follow Gradle's
documentationfor more details.

Passwords. In your app's
build.gradle
you will need to define the
signingConfigs
for
the release build. Here is what you should avoid:

Don't do this. This would appear in the version control system.

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


Instead, make a
gradle.properties
file which should not be added to the version control system:
KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789


That file is automatically imported by gradle, so you can use it in
build.gradle
as such:

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.")
}
}
}


Prefer Maven dependency resolution instead of importing jar files. If you explicitly include jar files in your project, they will be of some specific frozen version, such as
2.1.1
.
Downloading jars and handling updates is cumbersome, this is a problem that Maven solves properly, and is also encouraged in Android Gradle builds. For example:

dependencies {
compile 'com.squareup.okhttp:okhttp:2.2.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'
}


Avoid Maven dynamic dependency resolution Avoid the use of dynamically versioned, 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.

Use different package name for non-release builds Use
applicationIdSuffix
for debug build
type 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 later on in the app's lifecycle, after it has
been published to the store.

android {
buildTypes {
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
}

release {
// ...
}
}
}


Use 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 releaseicon
in
app/src/release/res
. You could also change
app name per build type, as well as
versionName
(as in the above example).


IDEs
and text editors

Use whatever editor, but it must play nicely with the project structure. Editors are a personal choice, and it's your responsibility to get your editor functioning according to the project structure and build system.

The most recommended IDE at the moment is Android Studio, because it is developed by Google,
is closest to Gradle, uses the new project structure by default, is finally in stable stage, and is tailored for Android development.

Using Eclipse ADT for Android development is no longer a good practice. Google
ended ADT support at the end of 2015 and urges users to migrate to Android Studio as
soon as possible. You could still use Eclipse, but since it expects the old project structure and Ant for building, you need to configure it to work with Gradle, or if that fails, use the command line to build.

You can even use a plain text editor like Vim, Sublime Text, or Emacs. In that case, you will need to use Gradle and
adb
on
the command line.

Whatever you use, just make sure Gradle and the new project structure remain as the official way of building the application, and avoid adding your editor-specific configuration files to the version control system. For instance, avoid adding an Ant
build.xml
file.
Especially don't forget to keep
build.gradle
up-to-date and functioning if you are changing build configurations in Ant. Also,
be kind to other developers, don't force them to change their tool of preference.


Libraries

Jackson is a Java library for converting Objects into JSON and vice-versa. Gson is
a popular choice for solving this problem, however we find Jackson to be more performant since it supports alternative ways of processing JSON: streaming, in-memory tree model, and traditional JSON-POJO data binding. Keep in mind, though, that Jackson is a
larger library than Gson, so depending on your case, you might prefer Gson to avoid 65k methods limitation. Other alternatives: Json-smart andBoon
JSON

Networking, caching, and images. There are a couple of battle-proven solutions for performing requests to backend servers, which
you should use perform considering implementing your own client. Use Volley or Retrofit.
Volley also provides helpers to load and cache images. If you choose Retrofit, consider Picasso for loading and
caching images, and OkHttp for efficient HTTP requests. All three Retrofit, Picasso and OkHttp are created by the
same company, so they complement each other nicely. OkHttp
can also be used in connection with Volley.

RxJava is a library for Reactive Programming, in other words, handling asynchronous events. It is a powerful and promising paradigm, which can also be confusing since it's so different. We recommend to take some caution before using this
library to architect the entire application. There are some projects done by us using RxJava, if you need help talk to one of these people: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. We have written
some blog posts on it: [1], [2], [3], [4].

If you have no previous experience with Rx, start by applying it only for responses from the API. 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 Javadocs 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.

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 with for example with RxJava. To use it, install JDK8, set that as your SDK Location in the Android Studio Project Structure dialog, and set
JAVA8_HOME
and
JAVA7_HOME
environment
variables, then in the project root build.gradle:

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


and in each module's build.gradle, add

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 offers code assist support for Java8 lambdas. If you are new to lambdas, just use the following to get started:

Any interface with just one method is "lambda friendly" and can be folded into the more tight syntax
If in doubt about parameters and such, write a normal anon inner class and then let Android Studio fold it into a lambda for you.

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] [2] [3].
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 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.


Activities
and Fragments

There 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, bypassing the need for Fragments, but this still is not considered a widely recommendable practice in the community.

Because 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 specially important for their lifecycle and
for managing state. However, you are likely to see variation in these roles: activities might be take UI roles (delivering
transitions between screens), and fragments might be used solely as
controllers. We suggest to sail carefully, taking informed decisions since there are drawbacks for choosing a fragments-only architecture, or activities-only, or views-only. Here are some advices on what to be careful with, but take them with a grain of
salt:

Avoid using nested fragments extensively, because matryoshka
bugs 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.
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.
Don't abuse Android-level APIs such as heavily relying on Intent for your app's internal workings. You could affect the Android OS or other applications, creating bugs or lag. For instance, it is known that if your app uses Intents for internal
communication between your packages, you might incur multi-second lag on user experience if the app was opened just after OS boot.


Java
packages architecture

Java architectures for Android applications can be roughly approximated in Model-View-Controller.
In Android, Fragment and Activity are actually controller classes. On the other hand, they
are explicity part of the user interface, hence are also views.

For this reason, it is hard to classify fragments (or activities) as strictly controllers or views. It's better to let them stay in their own
fragments
package.
Activities 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.

Otherwise, the architecture can look like a typical MVC, with a
models
package containing POJOs to be populated through the
JSON parser with API responses, and a
views
package containing your custom Views, notifications, action bar views, widgets,
etc. Adapters are a gray matter, living between data and views. However, they typically need to export some View via
getView()
,
so you can include the
adapters
subpackage inside
views
.

Some controller classes are application-wide and close to the Android system. These can live in a
managers
package. Miscellaneous
data processing classes, such as "DateUtils", stay in the
utils
package. Classes that are responsible for interacting with
the backend stay in the
network
package.

All in all, ordered from the closest-to-backend to the closest-to-the-user:
com.futurice.project
├─ network
├─ models
├─ managers
├─ utils
├─ fragments
└─ views
├─ adapters
├─ actionbar
├─ widgets
└─ notifications


Resources

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
.

Organizing layout XMLs. If you're unsure how to format a layout XML, the following convention may help.

One attribute per line, indented by 4 spaces
android:id
as the first attribute always
android:layout_****
attributes at the top
style
attribute at the bottom
Tag closer
/>
on its own line, to facilitate ordering and adding attributes.
Rather than hard coding
android:text
, consider using Designtime
attributes available 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>


As 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.

The exceptions are:

android:id
should obviously be in the layout files
android:orientation
for a
LinearLayout
normally
makes more sense in layout files
android:text
should be in layout files because it defines content
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

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:

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


Applied to TextViews:

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


You 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.

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.

colors.xml
is
a color palette. There should be nothing else in your
colors.xml
than just a mapping from a color name to an RGBA value.
Do not use it to define RGBA values for different types of buttons.

Don't do this:

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


You can easily start repeating RGBA values in this format, and that makes it complicated to change a basic color if needed. Also, those definitions are related to some context, like "button" or "comment", and should live in a button style, not in
colors.xml
.

Instead, do this:

<resources>

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

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

</resources>


Ask for this palette from the designer of the application. The names do not need to be color names as "green", "blue", etc. Names such as "brand_primary", "brand_secondary", "brand_negative" are totally acceptable as well. Formatting colors 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.

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:

<resources>

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

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

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

</resources>


You 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.

strings.xml

Name 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.

Bad

<string name="network_error">Network error</string>
<string name="call_failed">Call failed</string>
<string name="map_failed">Map loading failed</string>


Good

<string name="error.message.network">Network error</string>
<string name="error.message.call">Call failed</string>
<string name="error.message.map">Map loading failed</string>


Don'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
on
a TextView.

Bad

<string name="error.message.call">CALL FAILED</string>


Good

<string name="error.message.call">Call failed</string>


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:

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

<RelativeLayout
...
>

<LinearLayout
...
>

<LinearLayout
...
>

<LinearLayout
...
>
</LinearLayout>

</LinearLayout>

</LinearLayout>

</RelativeLayout>

</LinearLayout>


Even 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.

A couple of problems may occur. You might experience performance problems, because there are is a complex UI tree that the processor needs to handle. Another more serious issue is a possibility of StackOverflowError.

Therefore, try to keep your views hierarchy as flat as possible: learn how to use RelativeLayout,
how to optimize your layoutsand to use the
<merge>
tag
.

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 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 TextViews or Buttons.


Test
frameworks

Android SDK's testing framework is still infant, specially regarding UI tests. Android Gradle currently implements a test task called
connectedAndroidTest
which
runs JUnit tests that you created, using an extension of JUnit with helpers
for Android. This means you will need to run tests connected to a device, or an emulator. Follow the official guide [1] [2] for
testing.

Use Robolectric only for unit tests, not for views. It is a test framework seeking to provide tests
"disconnected from device" for the sake of development speed, suitable specially for unit tests on models and view models. However, testing under Robolectric is inaccurate and incomplete regarding UI tests. You will have problems testing UI elements related
to animations, dialogs, etc, and this will be complicated by the fact that you are "walking in the dark" (testing without seeing the screen being controlled).

Robotium makes writing UI tests easy. You do not need Robotium for running connected tests
for UI cases, but it will probably be beneficial to you because of its many helpers to get and analyse views, and control the screen. Test cases will look as simple as:

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



Emulators

If you are developing Android apps as a profession, buy a license for the Genymotion emulator. Genymotion emulators run
at a faster frames/sec rate than typical AVD emulators. They have tools for demoing your app, emulating network connection quality, GPS positions, etc. They are also ideal for connected tests. You have access to many (not all) different devices, so the cost
of a Genymotion license is actually much cheaper than buying multiple real devices.

Caveats are: Genymotion emulators don't ship all Google services such as Google Play Store and Maps. You might also need to test Samsung-specific APIs, so it's necessary to have a real Samsung device.


Proguard
configuration

ProGuard is normally used on Android projects to shrink and obfuscate the packaged code.

Whether you are using ProGuard or not depends on your project configuration. Usually you would configure gradle to use ProGuard when building a release apk.

buildTypes {
debug {
minifyEnabled false
}
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}


In 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. Android
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.

A 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. This means one out of two things:

ProGuard has removed the class, enum, method, field or annotation, considering it's not required.
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.

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

In order to prevent ProGuard from stripping away needed classes or class members, add a
keep
options to
your ProGuard config:
-keep class com.futurice.project.MyClass { *; }


To prevent ProGuard from obfuscating classes or class members, add a
keepnames
:
-keepnames class com.futurice.project.MyClass { *; }


Check this template's ProGuard config for
some examples. Read more at Proguard for examples.

Early on in your project, make a release build to check whether ProGuard rules are correctly keeping whatever is important. Also whenever you include new libraries, 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.

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.

DexGuard. If you need hard-core tools for optimizing, and specially obfuscating release code, consider 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.


Data
storage


SharedPreferences

If you only need to persist simple flags and your application runs in a single process SharedPreferences is probably enough for you. It is a good default option.

There are two reasons why you might not want to use SharedPreferences:

Performance: Your data is complex or there is a lot of it
Multiple processes accessing the data: You have widgets or remote services that run in their own processes and require synchronized data


ContentProviders

In the case SharedPreferences is not enough for you, you should use the platform standard ContentProviders, which are fast and process safe.

The 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,
which significantly reduces the effort.

You 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.


Using
an ORM

We 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.


Use
Stetho

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.


Thanks
to

Antti 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.


License

Futurice Oy Creative Commons Attribution 4.0 International (CC BY 4.0)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: