As with any technology, there’s knowing Android and then there’s really knowing Android. This guide offers a sampling of questions that are key to evaluating the breadth and depth of a candidate’s mastery of the Android mobile framework when looking to hire Android app developers part-time or full-time.

The Challenge

Android has become the dominant smartphone platform on the planet with over 81% market share (more than Apple iOS’ 15% and Microsoft Windows’ 4% combined) and 240 million mobile devices worldwide. Not too shabby. With that comes enormous demand for developer talent, so locating elite Android app developers can be a daunting task.

Finding them requires a highly-effective recruiting process, as described in our post In Search of the Elite Few – Finding and Hiring the Best Software Developers in the Industry. Such a process can then be augmented with questions—such as those presented herein—to identify those sparsely distributed candidates across the globe who are true Android experts.

Android is a smartphone operating system built on top of Linux based on Java and XML. Since the Android OS is not just a language, but a complete, rich and growing software framework, it has a lot to master. As of this writing, Android is in its 7th year, now at version 4.4 (“KitKat”) and has undergone 19 SDK releases.

Google introduced Android as an open source project in 2007 (see AOSP) so it could get a foothold in the emerging smartphone market. Numerous hardware vendors have used Android for their handsets (Samsung, HTC, Sony, Motorola and LG just to name a few), often adding their own custom features and code. This sometimes creates additional headaches for developers when incompatibilities or vendor-specific bugs arise (read: workarounds). Android itself isn’t a perfect mobile app development OS either, of course – with its sometimes lacking documentation and some quirky-behaving code – but it is still certainly a force to be reckoned with.

The Android application development platform offers a plethora of features and support classes:

User Interface, animation, graphics, varying screen size support and orientations

Touch screen keyboards and gesture recognition

Databases, content providers, content resolvers, adapters

Location detection, sensors, services

Threading options

Accelerated computation

Inter-app communication

Media playback and recording

Networking and connectivity

Google Play store and in-app billing

Localization

Debugging tools

And much more…

Such complexity can make any developer’s head spin, not to mention that of a hiring manager. So where do we start when interviewing Android programmers?

True Android experts will have a thorough and principled appreciation of the different implementation options available as well as their implications and ramifications.

What separates the expert Android mobile app developer from the neophyte goes beyond knowledge of how to code an app. When faced with a complex task, true Android experts will have a thorough and principled appreciation of the different implementation options available as well as their implications and ramifications. The questions presented in this guide can help you identify those rare Android gurus who have this understanding and who can significantly improve the productivity and throughput of your project as a result.

User Interface

The User Interface (UI) is the face of your app. An application’s UI is critical as it forms the basis of how users interact with and perceive your app. Android offers numerous classes that developers leverage and customize while also providing a general framework that users come to rely on.

For example, Android provides a general purpose solution for a top navigation system called the ActionBar. It also provides support for a NavigationDrawer that users can slide open and close by tapping an ActionBar menu button or swiping the left edge of the screen. Android provides an abundance of UI classes and widgets to lay out views, create animations, perform custom drawing, display drawables (icons, bitmaps, shapes, etc.), and more.

Much of an Android UI can be specified with XML, but one can also write custom subclasses that extend Android UI classes to create custom views and behaviors. The scope of the UI is quite broad (it even includes media playback, video, audio, phone vibration, for example), so we can’t cover everything here, but we’ll highlight some key areas that solid dedicated Android developers should be well versed in.

Q: What are Activities and Fragments? When and why should you use one over the other?

An Activity is a user interface component that represents the main focus of attention on a screen. In contrast, Fragments, introduced as tablets emerged with larger screens, are reusable components that are attached to and displayed within activities. Multiple fragments can be shown at once within an activity. While it’s possible to develop a UI only using Activities, this is generally a bad idea since their code cannot later be reused within other Activities. Elite developers know this and write fragments (sometimes used within trivial activities) to future proof their app. With this approach, the activity supports its attached fragments, letting the fragments, their layouts and views handle the lion’s share of user interface.

For example, let’s say you want the user to be able to horizontally scroll through a set of pages where each may show a list, photo, photo gallery, dashboard, or form. Here you might use a ViewPager in your Activity whose items are fragments that handle each of those unique user interface functions separately. If the developer had written these pages as Activities, they would have had to refactor them as fragments.

Also note that, while you can use an Activity without a Fragment, the reverse isn’t true.

Q: What are Adapters and when and how are they used?

It’s tough to develop an Android app without using an adapter somewhere because they are so important.

Where do adapters fit in? They bridge the Model and View (e.g. AdapterViews such as ListViews, GridViews, Spinners and ViewPagers) with underlying data. They provide access to data items and are responsible for creating a view for each item in the data set.

Android doesn’t adopt the MVC pattern per se. You define the Model that works for you. Android helps you layout and render views, and you customize Android’s Activities and Fragments that typically act as Controllers.

Novice developers might try to get away with using simple helper adapters like ArrayAdapter , SimpleAdapter and SimpleCursorAdapter when possible, but these are usually too limiting for some of the more complex views typically required by today’s apps. Master developers will write adapters that extend BaseAdapter directly, because it is more powerful and flexible than the subclass helpers mentioned above.

The following snippet shows a custom ContactAdapter that displays contacts in a ListView. (Note: Only the more important methods required are shown.)

// A basic data model for illustrative purposes class Contact { public int id; public String name; public String phone; } public class ContactAdapter extends BaseAdapter implements ListAdapter { Context mContext; List<Contact> mContacts; public ContactAdapter(Context context) { mContext = context; } // Call this method to attach data to this adapter, and call when the data changes. public void newData(List<Contact> data) { mContacts = data; // Inform AdapterView that data has change and to redraw if necessary. notifyDataSetChanged(); } // The crux of the adapter -- bind data to the view layout. @Override public View getView(int position, View convertView, ViewGroup parent) { Contact contact = mContacts.get(position); LinearLayout view = (LinearLayout) convertView; if (view == null) { // "Inflate" our contact.xml view into existence. LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = (LinearLayout) inflater.inflate(R.layout.contact, null); } // Bind the data to their appropriate TextViews in the layout. ((TextView)view.findViewById(R.id.name)).setText(contact.name); ((TextView)view.findViewById(R.id.phone)).setText(contact.phone); // ... etc. ... return view; } }

Performance and Responsiveness

Users are so demanding. Your app must perform and be responsive or people will become frustrated and simply stop using it.

While requirements for an app should clearly define acceptable response times (although shorter is always better), developers should themselves have a general sense for what is reasonable and take measures to optimize performance accordingly. For example, when fetching a lot data from a server, steps should be taken to avoid locking up the user interface (i.e., by loading the data on a background thread).

Seasoned Android developers can be expected to have a variety of performance optimization tricks up their sleeves. The questions that follow aim to evaluate their acumen in this regard.

Q: What are some ways to optimize View usage?

If not careful, the unwitting Android developer can easily get carried away with creating more views in their layouts than necessary. The more views you can remove from your layouts, the more responsive your app becomes. Fewer views means less memory consumed and reduced garbage collection, as well as less work initializing, laying out, drawing, and traversing views.

Poor design becomes quickly apparent, for example, when trying to scroll rapidly through unoptimized layouts, which can appear sluggish and jerky. If particularly bad, the scrolling experience might become unusable, especially on lower-end devices with slower CPUs. Here are some view optimization techniques an experienced Android developer should be expected to be familiar with.

Technique #1: Optimize views in layouts.

Layouts are XML resource files that define views for activities and fragments. Because their design is so important to application performance, Google has written an entire training guide on the subject of Optimizing Layout Hierarchies.

Let’s take the following layout as an example:

This layout consists of four views: a root level horizontal LinearLayout that encapsulates an ImageView and a vertical LinearLayout that contains two TextViews . This results in a three level hierarchy.

This layout can be optimized by flattening its hierarchy to two levels by using a single root RelativeLayout and dropping the second LinearLayout altogether. The ImageView can be positioned to hug the left side of the parent RelativeLayout and the TextViews can hug the ImageView or the right side of the parent. The savings in speed and memory may not seem like much individually, but when applied to numerous ListView elements (for example), it can add up quickly and dramatically affect performance.

Technique #2: Use the <merge> tag in your layout files.

It’s smart to use the <merge> tag if possible when defining a view that is intended to be inflated and added to an existing ViewGroup , such as a GridView or ListView . This avoids creating an unnecessary middleman ViewGroup such as RelativeLayout or LinearLayout just to encapsulate child views. The <merge> tag is simply a placeholder for the parent view that its children will be attached to. In the following example, only the ImageView will be added to the parent, thereby eliminating the need for one of the encapsulating views.

Consider the following layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>

The above use of RelativeLayout , though standard practice, can be eliminated by using a <merge> tag as follows, thereby optimizing this layout:

<!-- The merge tag represents the parent view of this layout --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </merge>

Now we’re using one less view!

Technique #3: Consider using a ViewHolder pattern, but do so judiciously.

Use of the ViewHolder pattern can improve performance, but it is not a perfect solution. In fact, some would argue that it is really an anti-pattern. In the next question, we discuss the advantages and disadvantages of the ViewHolder approach. These issues should all be carefully weighed and considered before deciding if, where, and when to employ this technique.

Q: What is the ViewHolder pattern and how is it employed? What are some reasons for, and against, using it? What are some alternatives?

One of the first patterns novice Android developers are introduced to is the ViewHolder pattern—which, as previously noted, and as will be further discussed, some might refer to as an anti-pattern.

When we wish to display lists of items in Android UI, we typically use:

A concrete AdapterView subclass such as ListView , GridView , etc.

subclass such as , , etc. An underlying data set, typically an array of POJOs or a Cursor (a set of database rows)

An Adapter class responsible for creating and populating Views with specified data elements

The AdapterView attempts to recycle Views that are no longer displayed on-screen. This simple but effective technique allows applications to avoid:

Incurring the cost of garbage collection

Incurring the cost of layout inflation

An additional cost that can be avoided relates to calling View.findViewById() repeatedly to locate child views within a layout. Calls to View.findViewById() are expensive because sizable chunks of the layout (a hierarchical structure) must be traversed on each call to find a desired child View within a potentially complex layout. There can be noticeable lag when rapidly scrolling through a list with nested layouts, leaving most developers with an ugly problem in search of a solution.

Enter the ViewHolder caching pattern. But first, let’s put this into historical perspective. Before Android 2.2 (Froyo), the performance of the Dalvik VM and its Garbage Collector were dismal, so it was in this context and to help address this issue that the ViewHolder pattern came into being.

However, with the inclusion of a JIT compiler and vast improvements in the Garbage Collector, the cost of not caching View.findViewById() has decreased dramatically (although it’s still worthwhile and not expensive in terms of developer effort). ViewHolder has therefore become a less necessary approach, which is particularly problematic given some of its negative side effects, such as:

Code clutter

Breaking the Separation of Concerns Principle

Breaking the Single Responsibility Principle

Here’s the latest that Google has to say about ViewHolder, in a nutshell. Define a class to cache the results of View.findViewById() :

static class ViewHolder { TextView text; TextView timestamp; ImageView icon; ProgressBar progress; int position; }

And then in getView() of your Adapter class, cache its results:

ViewHolder holder = new ViewHolder(); holder.icon = (ImageView) convertView.findViewById(R.id.listitem_image); holder.text = (TextView) convertView.findViewById(R.id.listitem_text); holder.timestamp = (TextView) convertView.findViewById(R.id.listitem_timestamp); holder.progress = (ProgressBar) convertView.findViewById(R.id.progress_spinner); convertView.setTag(holder);

Savvy developers recognize that ViewHolder is a struct that is populated via calls to View.findViewById() . The ViewHolder struct is stored in the parent View via View.setTag() . When recycling a View, we can tap the ViewHolder cache:

ViewHolder holder = (ViewHolder) convertView.getTag();

Now this technique is great for writing tutorials. However, for example, when you need to add OnClickListeners , change drawables according to state changes, etc, you wind up with your Adapter class doing a huge amount of work that it should not be doing.

What can we do differently? Referencing the ContactAdapter code from a previous question, we’ll modify the inflated View (in this case LinearLayout ) to cache child views in a separate concern, the parent View itself:

@Override public View getView(int position, View convertView, ViewGroup parent) { Contact contact = mContacts.get(position); ContactView view = (ContactView) convertView; if (view == null) { // "Inflate" our contact.xml view into existence. LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = (LinearLayout) inflater.inflate(R.layout.contact, null); } // Bind contact data to appropriate child Views in the layout. view.setModel(contact); return view; }

All we need to do now is edit our Contact layout and replace its root element with ContactView (shown below) instead of LinearLayout , say. That’s it! We now have proper separation of concerns, single purpose (less cluttered) classes, and we avoid using View.setTag() and View.getTag() methods without overhead while caching child Views.

public class ContactView extends LinearLayout { private Contact model; private TextView name; private TextView phone; @Override protected void onFinishInflate() { this.name = (TextView)view.findViewById(R.id.name); this.phone = (TextView)view.findViewById(R.id.phone); } public void setModel(Contact model) { this.model = model; bindModel(); } private void bindModel() { this.name.setText(model.name); this.phone.setText(model.phone); } }

Q: What is an ANR? What causes them and how can they be avoided?

ANR refers to Android’s infamous Application Not Responding dialog that apps can trigger when they spend too much time computing on the main thread. The main thread handles the Android UI, so doing more work there slows down responsiveness. An ANR is therefore often a kick-in-the-pants when you aren’t backgrounding longer running tasks.

Examples of tasks that can cause ANR’s include:

Uploading/loading data to/from the cloud

Saving/loading cached data to/from disk

Sorting, filtering and searching data

What these operations have in common is that they can all be slow. They are often resource bound, meaning that they often take time, sometimes much longer than desired or expected.

With that in mind, any work to be performed that is not UI-related, especially the above types of resource-bound tasks, should be done on a background thread. Android has several ways to accomplish background work and has spawned some good 3rd party open source libraries for this as well.

Several threading options exist, each with its own advantages and disadvantages. Asynchronous computation is inherently complex and these classes and interfaces attempt to simplify the effort. Check out Google’s Processes and Threads guide for more detailed info.

Let’s explore some of the more useful threading options in Android:

AsyncTask

AsyncTask is a helper class that lets you spawn a short background operation. It’s most commonly used to display results on the UI thread. This is usually the first class novice developers learn how to use when dealing with asychronicity, since it avoids having to setup and use threads directly.

Unfortunately, AsyncTask has some serious gotchas. It has become somewhat of a crutch when other, more advanced, threading options ought to be used. Google has flip-flopped over the years on the runtime behavior of AsyncTask , from first being run serially (with other AsyncTasks on a single background thread), to being run in parallel, and then back to serial! This means that, if the type of concurrency (i.e., serial vs. parallel) is important to your app, you must check the running SDK version of Android before using an AsyncTask . Developers may be better off using a HandlerThread or Executor as a result.

Thread

The Thread class is Android’s most basic execution environment with its own call stack, arguments, and local variables. Every app has one main thread (for user interface) and other threads in a system thread group. You can either (a) subclass Thread and execute code within its run() method or (b) pass a Runnable to its constructor which then starts its execution by calling its start() method. Once started, the thread can yield to other threads or can sleep. You can’t externally stop a thread though; your only options are to interrupt it, wait for it to complete on its own, or join() it.

HandlerThread

Whereas Threads don’t have Loopers by default, a HandlerThread is a Thread that has a Looper attached. The Looper provides a Handler that allows message passing between threads. A Handler also allows for executing Runnable tasks on its attached thread, either immediately or at a later point in time.

Here is how you might instantiate a HandlerThread on which to post tasks to be executed:

class VotingActivity { private Runnable processVotes = new Runnable() { public void run() { } }; public void onCreate (Bundle savedInstanceState) { HandlerThread handlerThread = new HandlerThread("Voting Tasks"); handlerThread.start(); Handler handler = new Handler(handlerThread.getLooper()); // Now let's execute a Runnable task ASAP on the new thread we just created: handler.post(new Runnable() { public void run() { // Accept a vote, say. } }); // Let's also schedule a task to execute 10 seconds in the future on the new thread: handler.postDelayed(processVotes, 10000); } }

And here’s how we might set up a HandlerThread to process messages sequentially:

class DownloadThread extends HandlerThread { public static final int START_MSG = 0; public static final int STOP_MSG = 1; DownloadThread(String name) { super(name); } @Override public void handleMessage(Message msg) { switch (msg.what) { case START_MSG: // Start downloading... break; case STOP_MSG: // Stop downloading... break; default: break; } } }

And then we could spawn and use this thread as follows:

class MainActivity extends Activity { public void onCreate (Bundle savedInstanceState) { // Set up our DownloadThread for receiving messages. DownloadThread downloadThread = new DownloadThread("Image Downloader"); downloadThread.start(); Handler downloadHandler = new Handler(downloadThread.getLooper()); } public void startDownloading() { downloadHandler.sendEmptyMessage(DownloadThread.START_MSG); } public void stopDownloading() { downloadHandler.sendEmptyMessage(DownloadThread.STOP_MSG); } }

ExecutorService and ThreadPoolExecutor

ThreadPoolExecutor implements the ExecutorService interface that executes submitted tasks on one of several pooled threads. Thread pooling usually improves performance when executing many tasks due to the reduced overhead of per-task invocation. If you need to execute numerous tasks asynchronously, you can spawn workers fairly easily with this mechanism. Google notes that ThreadPoolExecutor is somewhat of a configurable kitchen sink, and developers are encouraged to use preconfigured versions such as newCachedThreadPool() , newFixedThreadPool() and newSingleThreadExecutor() .

Q: What are Loaders? When and why are they used?

In the incessant quest to offload work from the main thread, Android introduced Loaders (see LoaderManager and Loader classes). Loaders simplify asynchronous loading of data in activities and fragments that usually feed adapters. They monitor their data source and deliver new results when content changes. So, instead of blocking and waiting for data to arrive (from your cloud or disk, for example), use a Loader. See Google’s Loaders Guide for more details.

Q: What is RxJava and why is it so cool?

Not every Android developer knows about this gem, so it scores major brownie points in our book when they do. It’s a big innovation and perhaps the most exciting part of our post. RxJava is Netflix’s open source port of Microsoft’s Reactive Extensions library. Reactive programming is a programming paradigm concerned with data flow and change. Reactive programming has been around for a while, but RxJava hasn’t. RxJava is super useful for writing synchronous/asynchronous, event-based observable sequences. It was designed for efficiently querying and consuming data (in motion).

RxJava is not an Android-specific library, but can make a huge impact on Android apps, depending on how it’s used. It’s useful with concurrent and/or asynchronous apps that require low latency. For example, a prime use case for it would be to load data asynchronously without having to think too much about threads, handlers, or executors. You might use RxJava to load data for adapters; e.g., subscribe to data of interest on the UI thread, schedule the work to be performed on a background thread, then observe the results back on the UI thread for display.

RxJava allows you to chain data and events, and create sequences that select, filter, transpose, compose, and combine data before a final observer is notified with results. We can’t possibly cover RxJava here in the depth it deserves, but we wanted to mention it because elite developers should be aware of it. You can read more about it here.

Q: How would you cache numerous large images from the net?

If you are developing an image gallery app like Instagram or Pinterest, caching many (large) images from your server becomes critical. In the quest for optimal performance, you want to present images rapidly, so caching them to avoid reloading them from the network is essential. Since you can’t cache too many large multi-megabyte images in RAM (since Android memory is volatile and is a limited resource), you really have no alternative but to cache images on disk (flash).

Rather than writing your own cache class(es), you could instead leverage and wrap DiskLruCache . It’s an indispensable open source solution that experienced Android developers should be aware of. It can be used to cache any kind of data to a file system directory, bounded by a size that you specify.

Beyond Android Proper

While Google’s Android team employs many great engineers, it can’t supply or anticipate every solution imaginable for new problems developers face. That’s where 3rd party open source, and even other Google teams, come in.

Savvy Android developers will therefore be familiar with a number of the more valuable libraries that have emerged in recent years. Theses can be used to retrofit new Android features to older handsets, augment existing features, or introduce new functionality.

Those that extend new Android features to older handsets, however, are becoming less crucial as users have been upgrading to newer Android versions and devices. But that said, Android developers do have a large fragmentation of Android devices, versions and brands to contend with, unlike iOS.

Q: What are some of the more useful Android open source libraries and how can you leverage them?

There are numerous open source libraries and add-ons available, from Google and elsewhere, that seasoned Android developers will commonly leverage. Some of the more useful ones include:

ActionBarSherlock — ActionBarSherlock is an extension of Android’s support library designed to facilitate the use of the action bar design pattern across all versions of Android with a single API. It allows you to easily develop an application with an action bar for every version of Android from 2.x and up.

DiskLruCache — As mentioned above, DiskLruCache is a powerful, yet simple, least-recently-used (LRU) caching implementation for storing data on disk, with bounded pool size.

Espresso — Announced by Google in October 2013 and still in developer preview, Espresso is a new UI testing framework whose goal is to make it easy for developers to write reliable UI tests. Most importantly, Espresso removes the need to think about the complexity of multi-threaded testing. Espresso is already being used by a number of Google applications (Drive, Maps, Google+, and more).

Guava — Google’s Guava project contains several core libraries actively used by Google internally: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and somewhat of a mishmash of very useful classes. See Guava’s wiki for more information. Its purpose is to make Java “more pleasant,” improve defensive programming, add optimizations and improve efficiency. It fills out and improves upon common classes like Collections, Math, Reflection, strings, Ranges, Hashing, I/O and more.

NineOldAndroids — NineOldAndroids makes the dramatically new and improved Android Honeycomb (3.0) animation API available to older versions back to 1.0 and forward compatible to the latest release of Android. Animation prior to Honeycomb was pretty darn limited. The new API offers much more power and flexibility to animate objects and actually reposition views with rotation, translation, alpha and scale primitives, for example. The library provides a wrapper that works across all Android versions.

Protocol Buffers — Google’s Protocol Buffers is a language-neutral, platform-neutral, extensible mechanism for serializing structured data, that provides a viable alternative to JSON or XML. It’s an efficient way to transport object data, for instance in its original binary format without needing to (un)marshal. Data transported is “smaller, faster, simpler”—in Google’s words.

RxJava — As mentioned above, RxJava is a Reactive Extension that lets you create asynchronous, event-based code using observable sequences, which can be invaluable in many circumstances.

Volley — Volley is a relatively recent Google library introduced at Google I/O May 2013 that makes networking for Android apps faster and easier. Oddly, Google hasn’t yet published its own tutorial or documentation other than the source, making some developers skeptical or wary of it, but several have written tutorials such as this and this. Highlights include a view that automatically loads images, HTTP request queuing with prioritization, and automatic Android-version-specific selection of the best HTTP library.

Debugging and Tuning

Experienced developers rely on great tools to help them build great software, especially for testing and optimization purposes. Android was a bit slow at first to offer them, but its tool chest has finally filled out. Android offers runtime detection of problems, attached classes that can help detect problems. There are also external tools like DDMS to view memory usage, find leaks, view thread usage, observe view hierarchies and more.

Q: What is the Don’t Keep Activities developer option and why is it useful?

Google offers a wide array of runtime debugging options for devices that can be activated under Settings > Developer options. One of the more useful ones is Don’t keep activities which immediately destroys an activity when the user leaves it. It’s useful for testing activity save and restore (i.e., the onSaveInstanceState(Bundle) and onCreate(android.os.Bundle) code path), which would otherwise be difficult to trigger. It can also uncover other symmetry problems with your activity’s life cycle, such as properly opening and closing resources between onResume() and onPause() callbacks, for instance.

Q: What is StrictMode and why is it useful?

In the never-ending quest to improve app responsiveness and keep the UI running smoothly, StrictMode is a valuable Android tool to help detect accidental disk and network access on the main thread (or any thread for that matter).

In the development version of your app (never leave StrictMode enabled in a released app!), you tell Android what problems you’re interested in finding and define the “penalties” to be applied (i.e., what to do) if they’re detected. While not every problem that it finds necessarily needs to be fixed, nor can you be certain that it will find every problem, it provides a highly useful window into your app’s imperfections (if any).

Here’s how you might enable StrictMode in your Application’s onCreate method:

public void onCreate() { // Only enable when developing your app! if (DEVELOPER_MODE) { // Tell Android what thread issues you want to detect and what to do when found. StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .detectNetwork() // or use .detectAll() for all detectable problems .penaltyLog() .build()); // Tell Android what VM issues you want to detect and what to do when found. StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .detectLeakedClosableObjects() .penaltyLog() // Log the problem .penaltyDeath() // Then kill the app .build()); } super.onCreate(); }

Q: What is the “lint” tool? What does it do and how would you use it?

Lint is an Android tool that scans your project and generates a detailed report containing errors and warnings in your code and resource files that you might consider fixing. It’s not perfect, and sometimes it report false positives (that top developers know to take with a grain of salt), but it’s still a useful tool. For example, it can:

Detect unused files and resources to reduce app bloat

Tell you where you should be recycling TypedArrays after use

after use Identify where you might be overdrawing backgrounds of overlaying views

… plus many other issues

You can enable your IDE to alert you to these issues in source files as you edit, but it’s often a good idea to run lint on the command line anyway to generate a complete report periodically, or as a biproduct of your automated build. For more info, see Improving your code with lint.

Wrap Up

We’ve only just scratched the surface of Android app development, highlighting some of the more important aspects and nuances of the platform, as well as tools to leverage.

Given Android’s complexity, it can take a mobile application developer years to become truly proficient. Android offers enormous potential given its massive market penetration today and its rich framework. Finding Android Jedi masters is a challenge given their demand and the time it takes to become one. We hope you find the questions presented in this post to be helpful toward that goal as you search for elite, cream-of-the-crop developers.