天天看點

Android 101 for iOS Developers Android 101 for iOS Developers

the number of potential users that it can bring to a product can hardly be ignored.

In this article, I will introduce the core concepts of Android development within the context of iOS development. Android and iOS work on similar problem sets, but they approach many of these problems in different

illustrate how to accomplish the same tasks when developing for both platforms.

This article will not delve deeply into the user experience and design pattern differences between iOS and Android. However, it would be beneficial to understand some of the key UI paradigms in use on Android

There are many differences between Objective-C and Java, and while it may be tempting to bring some of Objective-C’s styling into Java, it can lead to a codebase that heavily clashes with the primary framework

that drives it. In brief, here are a few gotchas to watch for:

Leave class prefixes at home on Objective-C. Java has actual namespacing and package management, so there is no need for class prefixes here.

Instance variables are prefixed with <code>m</code>, not <code>_</code>. - Take advantage

of JavaDoc to write method and class descriptions for as much of your code as possible. It will make your life and the lives of others better.

Null check! Objective-C gracefully handles message sending to nil objects, but Java does not.

Say goodbye to properties. If you want setters and getters, you have to remember to actually create a getVariableName() method and call it explicitly. Referencing<code>this.object</code> will not call

your custom getter. You must use <code>this.getObject</code>.

Similarly, prefix method names with <code>get</code> and <code>set</code> to indicate

getters and setters. Java methods are typically written as actions or queries, such as <code>getCell()</code>, instead of<code>cellForRowAtIndexPath:</code>.

Android applications are primarily broken into two sections, the first of which is the Java source code. The source code is structured via the Java package hierarchy, and it can be structured as you please.

However, a common practice is to use top-level categories for activities, fragments, views, adapters, and data (models and managers).

The second major section is the <code>res</code> folder, short for ‘resource’ folder. The <code>res</code> folder

is a collection of images, XML layout files, and XML value files that make up the bulk of the non-code assets. On iOS, images are either <code>@2x</code> or not, but on Android

uses folders to arrange images, strings, and other values for screen density. The <code>res</code> folder also contains XML layout files that can be thought of as <code>xib</code> files.

Lastly, there are other XML files that store resources for string, integer, and style resources.

One last correlation in project structure is the <code>AndroidManifest.xml</code> file. This file is the equivalent of the <code>Project-Info.plist</code> file

Activities are the basic visual unit of an Android app, just as <code>UIViewControllers</code> are the basic visual component

on iOS. Instead of a <code>UINavigationController</code>, the Android OS keeps an activity stack that it manages. When an app is launched, the OS pushes the app’s main activity

onto the stack. Note that you can launch other apps’ activities and have them placed onto the stack. By default, the back button on Android pops from the OS activity stack, so when a user presses back, he or she can go through multiple apps that have been

launched.

contain extra data. Starting Activities with Intents is somewhat similar to creating a new<code>UIViewController</code> with a custom <code>init</code> method.

Because the most common way to launch new activities is to create an Intent with data, a great way to expose custom initializers on Android is to create static Intent getter methods. Activities can also return results when finished (goodbye modal delegates!)

by placing extra data on an Intent when the activity is finished.

One large difference between Android apps and iOS apps is that any activity can be an entrance point into your application if it registers correctly in the<code>AndroidManifest</code> file.

Setting an Intent filter in the AndroidManifest.xml file for a<code>media intent</code> on an activity effectively states to the OS that this activity is able to be launched as

an entry point with media data inside of the Intent. A good example might be a photo-editing activity that opens a photo, modifies it, and returns the modified image when the activity finishes.

As a side note, model objects must implement the <code>Parcelable</code> interface if you want to send them between activities

and fragments. Implementing the <code>Parcelable</code>interface is similar to conforming to the <code>&lt;NSCopying&gt;</code> protocol

on iOS. Also note that<code>Parcelable</code> objects are able to be stored in an activity’s or fragment’s savedInstanceState, in order to more easily restore their states after

they have been destroyed.

Let’s next look at one activity launching another activity, and also responding to when the second activity finishes.

to Android and came around somewhat recently in Android 3.0. Fragments are mini controllers that can be instantiated to fill activities. They store state information and may contain view logic, but there may be multiple fragments on the screen at the same

time – putting the activity in a fragment controller role. Also note that fragments do not have their own contexts and they rely heavily on activities for their connection to the application’s state.

allow you to break up your UI and controller logic into smaller, reusable chunks. But beware! The fragment lifecycle, detailed below, is more nuanced.

Android 101 for iOS Developers Android 101 for iOS Developers

Fragments are the new way of structuring apps on Android, just like<code>UICollectionView</code> is the new way of structuring

it is initially easier to avoid using fragments and instead use nothing but activities, you could regret this decision later on. That said, resist the urge to give up on activities entirely by swapping fragments on a single activity – this can leave you in

a bind when wanting to take advantage of intents and using multiple fragments on the same activity.

Let’s look at a sample <code>UITableViewController</code> and a sample <code>ListFragment</code> that

Android 101 for iOS Developers Android 101 for iOS Developers
Android 101 for iOS Developers Android 101 for iOS Developers

In the next section, let’s decipher some of the unique Android components.

<code>ListViews</code> are the closest approximation to <code>UITableView</code> on

Android, and they are one of the most common components that you will use. Just like <code>UITableView</code> has a helper view controller, <code>UITableViewController</code>,

ListView also has a helper activity,<code>ListActivity</code>, and a helper fragment, <code>ListFragment</code>.

Similar to<code>UITableViewController</code>, these helpers take care of the layout (similar to the xib) for you and provide convenience methods for managing adapters, which we’ll

discuss below. Our example above uses a <code>ListFragment</code> to display data from a list of<code>Prediction</code> model

objects, similar to how the table view’s datasource uses an array of <code>Prediction</code> model objects to populate the <code>ListView</code>.

Speaking of datasources, on Android we don’t have datasources and delegates for<code>ListView</code>. Instead, we have adapters.

Adapters come in many forms, but their primary goal is similar to a datasource and table view delegate all in one. Adapters take data and adapt it to populate a <code>ListView</code> by

instantiating views the <code>ListView</code>will display. Let’s have a look at the array adapter used above:

You’ll note that the adapter has an important method named <code>getView</code>, which is very similar to <code>cellForRowAtIndexPath:</code>.

Another similarity you’ll notice is a pattern for reusing views, similar to iOS 6. Reusing views are just as important as on iOS, and this substantially helps performance! This adapter is rather simple, because it uses a built-in superclass, <code>ArrayAdapter&lt;T&gt;</code>,

for adapters working with array data, but it illustrates how to populate a <code>ListView</code> from a dataset.

In place of Grand Central Dispatch on iOS, on Android we have access to <code>AsyncTasks</code>.<code>AsyncTasks</code> is

a different take on exposing asynchronous tools in a more friendly way. <code>AsyncTasks</code> is a bit out of scope for this article, but I highly recommend looking over some

Android 101 for iOS Developers Android 101 for iOS Developers

In essence, the activity lifecycle is very similar to the UIViewController lifecycle. The primary difference is that the Android OS can be ruthless with destroying activities, and it is very important to make

sure that the data and the state of the activity are saved, so that they can be restored from the saved state if they exist in the<code>onCreate()</code>. The best way to do this

is by using bundled data and restoring from the savedInstanceState and/or Intents. For example, here is the part of the<code>TripListActivity</code> from our sample project that

is keeping track of the currently shown subway line:

A note on rotation: the lifecycle completely resets the view on rotation. That is, your activity will be destroyed and recreated when a rotation occurs. If data is properly saved in the

saved instance state and the activity restores the state correctly after its creation, then the rotation will work seamlessly. Many app developers have issues with app stability when the app rotates, because an activity does not handle state changes properly.

Beware! Do not lock your app’s rotation to solve these issues, as this only hides the lifecycle bugs that will still occur at another point in time when the activity is destroyed by the OS.

similar to the activity lifecycle, with a few additions.

Android 101 for iOS Developers Android 101 for iOS Developers

One of the problems that can catch developers off guard is regarding issues communicating between fragments and activities. Note that the <code>onAttach()</code>happens before <code>onActivityCreated()</code>.

This means that the activity is not guaranteed to exist before the fragment is created. The <code>onActivityCreated()</code>method should be used when you set interfaces (delegates)

to the parent activity, if needed.

Fragments are also created and destroyed aggressively by the needs of the operating system, and to keep their state, require the same amount of diligence as activities. Here is an example from our sample project,

where the trip list fragment keeps track of the <code>TripList</code> data, as well as the subway line type:

Notice that the fragment always restores its state from the bundled arguments in<code>onCreate</code>, and that the custom setter

for the <code>TripList</code> model object adds the object to the bundled arguments as well. This ensures that if the fragment is destroyed and recreated, such as when the device

is rotated, the fragment always has the latest data to restore from.

stored as human-readable XML files in the<code>res/layouts</code> folder.

Android 101 for iOS Developers Android 101 for iOS Developers

Here is the same view on iOS with a <code>UITableView</code> and a <code>UIButton</code> pinned

to the bottom via Auto Layout in Interface Builder:

Android 101 for iOS Developers Android 101 for iOS Developers
Android 101 for iOS Developers Android 101 for iOS Developers

You’ll notice that the Android layout file is much easier to read and understand what is going on. There are many parts to laying out views in Android, but we’ll cover just a few of the

important ones.

views and expose properties to arrange them on screen.

A good example is the use of a <code>RelativeLayout</code> above. A relative layout allows us to use <code>android:layout_alignParentBottom="true"</code> in

our layout above to pin the button to the bottom.

Lastly, to link layouts to fragments or activities, simply use that layout’s resource ID during the <code>onCreateView</code>:

of pixels directly.

Don’t bother nudging items for layouts in the visual editor – often the visual editor will put individual points of spacing on objects instead of adjusting the height and width as you might like. Your best bet is to adjust the XML directly.

If you ever see the <code>fill_parent</code> value for a layout height or width, this value was depreciated years ago in API 8 and replaced with <code>match_parent</code>.

on Android are also very similar to what is available on iOS:

In-memory objects

storage &lt;-&gt; saving to the documents directory

What we’ve discussed so far barely scratches the surface. To really take advantage of some of the things that make Android special, I recommend checking out some of these features:

<a target="_blank" href="http://developer.android.com/guide/topics/ui/actionbar.html">Action Bar, Overflow Menu, and the Menu Button</a>

<a target="_blank" href="https://developer.android.com/training/sharing/index.html">Cross-App Data Sharing</a>

<a target="_blank" href="http://developer.android.com/guide/components/intents-common.html">Respond to common OS actions</a>

Take advantage of Java’s features: generics, virtual methods and classes, etc.

<a target="_blank" href="http://developer.android.com/tools/support-library/index.html">Google Compatibility Libraries</a>

While some of the pure implementation details are very different on Android, it is very easy to bring problem-solving skills and patterns learned on iOS to bear. Who knows? Maybe understanding

how Android works just a little bit better might prepare you for the next version of iOS.

<a target="_blank" href="http://www.prnewswire.com/news-releases/strategy-analytics-android-captures-79-percent-share-of-global-smartphone-shipments-in-2013-242563381.html">Source</a>

<a target="_blank" href="http://www.objc.io/issue-11/android_101_for_ios_developers.html#fnref:1">↩</a>

<a target="_blank" href="http://www.objc.io/issue-11/android_101_for_ios_developers.html#fnref:2">↩</a>

<a target="_blank" href="http://developer.android.com/reference/android/content/Intent.html">Intents documentation</a>

<a target="_blank" href="http://www.objc.io/issue-11/android_101_for_ios_developers.html#fnref:3">↩</a>

<a target="_blank" href="http://www.objc.io/issue-11/android_101_for_ios_developers.html#fnref:4">↩</a>

<a target="_blank" href="http://www.objc.io/issue-11/android_101_for_ios_developers.html#fnref:5">↩</a>

繼續閱讀