Photo by Fabian Grohs on Unsplash

5 things every iOS developer learning Android should know

Kane
Kin + Carta Created
6 min readMay 27, 2020

--

I recently started my journey into Android development after creating iOS apps for 5 years, and there are a few things I wish I knew that tripped me up at the start.

In this post, I’ll go over 5 of them, so if you’re learning (or thinking about learning) Android as well, I hope this post helps you!

1. Views & ViewGroups

On iOS, views are represented as UIView subclasses, similarly on Android views are represented as View subclasses.

On iOS, you can add a UIView as a subview of any other UIView. On Android, you can only add a View as a subview (technically, child view) inside a ViewGroup (even though ViewGroup is actually a subclass of View).

A ViewGroup is typically something like a LinearLayout, ConstraintLayout etc, and is designed to display multiple views (hence “group”). You can add other ViewGroups to a ViewGroup, which is how you build up a layout or hierarchy.

2. Activities & Fragments

On iOS you use a UIViewController to represent a whole screen, or part of a screen by embedding a child UIViewController into a UIViewController's root view.

On Android, you can use an Activity to represent a whole screen, or you can embed one or more Fragments inside an Activity to represent an entire screen or parts of a screen (hence, fragment).

Unlike a UIViewController, an Activity always uses the full screen. Since you can transition multiple full-screen Fragments in an Activity, it's completely possible to have a single Activity for your entire Android app.

3. The Lifecycle

On iOS, you typically have an app lifecycle like this:

- App launched <--------------|
- App enters foreground <--| |
- App becomes active | |
- App resigns active | |
- App enters background | |
- App suspended >----------| |
- App terminates >------------|

And then during the app’s life you can also have lifecycles of individual view controllers:

- init
- VC view did load
- VC will appear <----|
- VC did appear |
- VC will disappear |
- VC did disappear >--|
- deinit

An Android app has its own lifecycle too, but it’s mostly linked to the current activity or fragment (this is a simplified version of both, check out the links for a detailed explanation):

- onCreate
- onStart <---------|
(visible) |
- onResume <----| |
(interactive) | |
- onPause >-----| |
(not interactive) |
- onStop >----------|
(not visible)
- onDestroy

Additionally, the app itself has a couple of lifecycle events:

- onCreate
- onTerminate

Generally, you’ll just care about the lifecycle of the current activity or fragment.

As a user navigates around your Android app (or the system), any of these events can happen.

An activity (or fragment) is visible when it’s started and interactive when resumed. It can be paused if it’s obscured by something else like the Notification Drawer, or if the app is in split screen and no longer the “active” app.

The most important thing to know is that an activity can be recreated at any time by the system, which means that you cannot rely on state stored inside your activity (or any fragments it contains), since it will be a new instance! An example of when this can happen is when you rotate the device.

You can use ViewModels in your activities and fragments to hold state that persists between instances as needed. The system will manage whether to create a new view model for you, providing you create the ViewModel correctly.

It’s also worth mentioning that onDestroy and onTerminate aren’t guaranteed to be called (same as how applicationWillTerminate is not guaranteed to be called on iOS).

4. Contexts

In my opinion, this is the biggest difference between building an iOS app and an Android app.

On Android, you’ll often find many classes and functions requiring you to pass in this mystical object called a Context.

A Context is really just a class that provides access to app resources (like strings and images), system services (like Bluetooth adapters and notification managers), send Intents and information about the current environment.

Typically, you can just pass a reference to the current activity as the context, (which you can access from within fragments inside activities), and if you really have to, you can also use the application context.

Since you will find yourself passing around contexts quite often, it can be tempting to store a reference to a context in your custom classes and view models. It’s best to avoid this as much as possible, since it can cause memory leaks (for example, if the activity passed as the context was destroyed by the system, your class would still hold a permanent reference to it).

The concept of a context doesn’t really exist on iOS, although UITraitCollections are similar in that they provide information about the current environment, and can be accessed through UIViewController or UIScreen instances.

5. Backwards compatibility

I was going to include memory management as number 5, but given that’s more language specific than platform specific I changed my mind and went with backwards compatibility as the final thing you should know.

When you create a new iOS app, the general consensus is you should support the last two major versions of iOS, because the iOS platform has a great track record of getting users onto the latest versions of iOS, and Apple keep releasing new versions of iOS for older iOS devices.

When creating an Android app, you’ll straight away notice that when creating the app in Android Studio, it’ll ask you what versions of Android you want to target. As you change your selection, Android Studio will show you an estimate of how many devices that can be installed on.

If you choose the last two major versions like you would for iOS, you’ll likely be disappointed by the number Android Studio estimates.

Screenshot of a breakdown of app reach per Android OS version, according to Android Studio

It’s not as bad as you might think though, because of a difference between the way iOS and Android handle frameworks and backwards compatibility.

On iOS, all frameworks are bundled with the system, which means that you need people to be on the latest versions of iOS to use some APIs. On Android, it’s different. Some frameworks are added as dependencies to your app as needed, and Google put a lot of effort into creating support/compatibility frameworks which make APIs backwards compatible, like AndroidX, part of the Android Jetpack libraries.

During development of your Android app, and while looking at tutorials, you’ll see a lot of *Compat references, like SwitchCompat, and these provide backwards compatibility onto versions of Android that don’t support the standard versions like Switch.

Even with AndroidX, you’ll still want to balance supporting very old versions with how much testing you’re willing to carry out. Since there’s such a huge array of Android devices, the older you go, the harder it is to test your app well. Personally, I’ve added support to API level 26 (Android 8.0/Oreo), which means my app will run on roughly 61% of devices.

I can choose API level 26 keeping my user base in mind, since I know most people who will use my app (which connects to another device) will likely have newer phones.

What next?

Now that you know these 5 important things, there’s nothing left to do but start coding!

Download Android Studio (it’s free, and you don’t even need to create an account to use it!), create a new project and get going. Feel free to reach out to me if you have any questions. I’m still learning too, so we can learn together!

If you want to learn more about memory management on Android, this post is a great primer.

As with anything, it’ll feel alien at first, but in no time it’ll all start to click together and your biggest issue will be having to remember when to type let or val depending on what platform you’re developing for.

--

--

Kane
Kin + Carta Created

Senior multiplatform engineer. If you're not a fan of equality we won't get on.