Logcat

for Android Developers

November 30, 2011
by jean
8 Comments

Basic Layout Attributes and How to Use Them

Dealing with Android layout xml files can be a bit daunting at first. It definitely takes some time to learn the ins-and-outs of layout parameters to get your UI looking just right. We previously discussed how to decide whether you should use RelativeLayout or LinearLayout. Now we’ve compiled an overview of basic layout attributes and how to use them.

First of all, layout attributes that start with “layout_” have to do with a View’s LayoutParams, which are used by views to tell their parents how they should be laid out. Now let’s take a look at some of the more commonly used attributes.

layout_width and layout_height

These two are without a doubt the most common layout parameters you will encounter. In fact, these attributes are required on every view, and define the width and height of the view. For these attributes, the most common used values are “match_parent”, which sets that dimension to be as big as its parent’s, and “wrap_content,” which sets the dimension to just enough to wrap the content. You may also be familiar with “fill_parent” which was deprecated in favor of “match_parent” at API Level 8. You can also set either to specific values such as “40dip”. Here are few examples of a simple layout with a TextView with different values for layout_width and layout_height.

layout_gravity and gravity

These two attributes can be incredibly confusing, but remember that the one with layout_ is a part of the LayoutParams, which deals with the view and its parent. So layout_gravity defines how the view is positioned in its parent, while gravity defines how content is positioned within the view itself. You can set gravity to any of these values. In RelativeLayout, rather than using layout_gravity, you can use the RelativeLayout-specific attributes, which will be described later.

In the below example, setting gravity=”center” on the vertical LinearLayout centers all the views vertically inside the LinearLayout. Setting layout_gravity=”right” on the green TextView makes it right-aligned. In the orange TextView, you can see that setting gravity in a TextView aligns the TextView contents, which is the text itself. For a more comprehensive explanation of how this works, check out this blog post, which has a great visual of layout_gravity and gravity.
layout_margin and padding

Margin specifies extra space outside of the view, similar to the idea of css margins. You can either specify layout_margin which will assign the value to all four sides of the view, or you can specify each side separately using layout_marginTop, layout_marginBottom, layout_marginRight and layout_marginLeft.

Padding specifies extra space inside the view, on any or all of the four sides. You can specify padding all around the view at once with padding or each side individually using paddingTop, paddingBottom, paddingLeft, and paddingRight. Here is an example with the same basic “Hello World” TextView with different values set for padding and layout_margin.
layout_weight

This layout parameter is used only in LinearLayouts and allows you to assign importance to child views within a LinearLayout. For example, if you have a few views in a horizontal LinearLayout, you can use layout_weight to specify how you want them to take up extra space. For example, the first image below shows three TextViews, each with layout_width=”wrap_content” and no layout_weight set (default value is 0). Below that, you can see how the layout_weight values determines how the views take up extra space in the LinearLayout.
RelativeLayout-specific attributes

RelativeLayouts have a set of rules that helps determine where to place child views in the RelativeLayout.

layout_alignParent[Top/Bottom/Left/Right] specifies the view’s alignment within the parent. For example, layout_alignParentRight=”true” would align the view with the right edge of the parent.

Another useful set of rules for aligning views with respect to one another (rather than the parent) is layout_to[Right/Left]Of and layout_above and layout_below. These are set to the id of another view and will position the view appropriately with respect to the referenced view.

The last set of RelativeLayout rules is layout_align[Bottom/Top/Left/Right]. These allow you to align an edge of the view with the corresponding edge of another view.

Here is an example that uses several of these rules:

Note: be careful of circular dependencies! For example, as noted in the documentation, you can’t have a RelativeLayout that has layout_height=”wrap_content” and a view within it that has layout_alignParentBottom=”true”.

Setting Layout Attributes Programmatically

Setting these attributes in xml is pretty straightforward, but it gets a little tricky when you set them programmatically. Here are some basic guidelines.

For any attributes that have to do with the view’s LayoutParam, you have to get the LayoutParam and set the values on it. Be sure to cast it to the appropriate LayoutParams depending on the parent view. For example, for a TextView within a LinearLayout:

TextView view = (TextView) findViewById(R.id.text);
LinearLayout.LayoutParams lp =
(LinearLayout.LayoutParams) view.getLayoutParams();
lp.height = LayoutParams.FILL_PARENT;
lp.topMargin = 50;

If the view is in a RelativeLayout, you will have to cast the LayoutParams to RelativeLayout. You can then set RelativeLayout-specific rules using addRule(), like so:

TextView view = (TextView) findViewById(R.id.text);
RelativeLayout.LayoutParams lp =
(RelativeLayout.LayoutParams) view.getLayoutParams();
lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
lp.addRule(RelativeLayout.RIGHT_OF, R.id.text2);

For other attributes that are not related to LayoutParams, you can set it directly on the view:

TextView view = (TextView) findViewById(R.id.text);
view.setPadding(10, 5, 10, 5);
view.setGravity(3);

Hopefully this overview of most-commonly used layout attributes is helpful, especially if you are just getting started with Android xml layouts. If you have any tips you’ve found to be especially helpful, feel free to chime in with a comment!

November 8, 2011
by daniel
10 Comments

The Hidden Pitfalls of AsyncTask

When AsyncTask was introduced to Android, it was labeled as “Painless Threading.” Its goal was to make background Threads which could interact with the UI thread easier. It was successful on that count, but it’s not exactly painless – there are a number of cases where AsyncTask is not a silver bullet. It is easy to blindly use AsyncTask without realizing what can go wrong if not handled with care. Below are some of the problems that can arise when using AsyncTask without fully understanding it.

AsyncTask and Rotation

AsyncTask’s primary goal is to make it easy to run a Thread in the background that can later interact with the UI thread. Therefore the most common use case is to have an AsyncTask run a time-consuming operation that updates a portion of the UI when it’s completed (in AsyncTask.onPostExecute()).

This works great… until you rotate the screen. When an app is rotated, the entire Activity is destroyed and recreated. When the Activity is restarted, your AsyncTask’s reference to the Activity is invalid, so onPostExecute() will have no effect on the new Activity. This can be confusing if you are implicitly referencing the current Activity by having AsyncTask as an inner class of the Activity.

The usual solution to this problem is to hold onto a reference to AsyncTask that lasts between configuration changes, which updates the target Activity as it restarts. There are a variety of ways to do this, though they either boil down to using a global holder (such as in the Application object) or passing it through Activity.onRetainNonConfigurationInstance(). For a Fragment-based system, you could use a retained Fragment (via Fragment.setRetainedInstance(true)) to store running AsyncTasks.

AsyncTasks and the Lifecycle

Along the same lines as above, it is a misconception to think that just because the Activity that originally spawned the AsyncTask is dead, the AsyncTask is as well. It will continue running on its merry way even if you exit the entire application. The only way that an AsyncTask finishes early is if it is canceled via AsyncTask.cancel().

This means that you have to manage the cancellation of AsyncTasks yourself; otherwise you run the risk of bogging down your app with unnecessary background tasks, or of leaking memory. When you know you will no longer need an AsyncTask, be sure to cancel it so that it doesn’t cause any headaches later in the execution of your app.

Cancelling AsyncTasks

Suppose you’ve got a search query that runs in an AsyncTask. The user may be able to change the search parameters while the AsyncTask is running, so you call AsyncTask.cancel() and then fire up a new AsyncTask for the next query. This seems to work… until you check the logs and realize that your AsyncTasks all ran till completion, regardless of whether you called cancel() or not! This even happens if you pass mayInterruptIfRunning as true – what’s going on?

The problem is that there’s a misconception about what AsyncTask.cancel() actually does. It does not kill the Thread with no regard for the consequences! All it does is set the AsyncTask to a “cancelled” state. It’s up to you to check whether the AsyncTask has been canceled so that you can halt your operation. As for mayInterruptIfRunning – all it does is send an interrupt() to the running Thread. In the case that your Thread is uninterruptible, then it won’t stop the Thread at all.

There are two simple solutions that cover most situations: Either check AsyncTask.isCancelled() on a regular basis during your long-running operation, or keep your Thread interruptible. Either way, when you call AsyncTask.cancel() these methods should prevent your operation from running longer than necessary.

This advice doesn’t always work, though – what if you’re calling a long-running method that is uninterruptible (such as BitmapFactory.decodeStream())? The only success I’ve had in this situation is to create a situation which causes an Exception to be thrown (in this case, prematurely closing the stream that BitmapFactory was using). This meant that cancel() alone wouldn’t solve the problem – outside intervention was required.

Limitations on Concurrent AsyncTasks

I’m not encouraging people to start hundreds of threads in the background; however, it is worth noting that there are some limitations on the number of AsyncTasks that you can start. The modern AsyncTask is limited to 128 concurrent tasks, with an additional queue of 10 tasks (if supporting Android 1.5, it’s a limit of ten tasks at a time, with a maximum queue of 10 tasks). That means that if you queue up more than 138 tasks before they can complete, your app will crash. Most often I see this problem when people use AsyncTasks to load Bitmaps from the net.

If you are finding yourself running up against these limits, you should start by rethinking your design that calls for so many background threads. Alternatively, you could setup a more intelligent queue for your tasks so that you’re not starting them all at once. If you’re desperate, you can grab a copy of AsyncTask and adjust the pool sizes in the code itself.

October 28, 2011
by jean
0 comments

Android 4.0 and SDK Tools Changes for Developers

New Android SDK releases are always exciting! We’ve compiled some of the main changes in the SDK, compatibility package, and tools that developers should be aware of.

New API features

If you are feeling adventurous and want to add some 4.0-specific features to your app, such as resizable widgets or Android Beam functionality, they are all well-documented on the Android Developer blog. We’ve focused more on changes that are relevant to existing apps, since that will affect developers immediately the most.

Compatibility Package
The full compatibility library changes can be found here, but here are some highlights:

  •  ViewPager improvements and bug fixes: Google released this ViewGroup a few months back, and it is being used by the official Google+, Calendar, and Gmail apps.
  • Support for Accessibility APIs
  • Changes to Fragments API, including bug fixes, as well as new API for menus and custom animations
  • LocalBroadcastManager allows you to broadcast within an application, rather than globally.

Targeting API 14
If you change your app to target API Level 14, keep these things in mind.

  • getBackgroundDataSetting() is deprecated. If you were using it, use getActiveNetworkInfo() instead.
  • If you don’t specify a theme, your default theme will be Theme.DeviceDefault, which will be the device’s defaults. If you want to have control over the themes, specify a theme (for instance, Theme.Holo if you were using Honeycomb’s default theme).

Android Development Tools (ADT) Improvements

The Android 4.0 release was complemented by pretty significant Tools upgrades. Xavier Ducrohet has a very comprehensive list here, but I’ll list some highlights:

  • Improved build performance in Ant and Eclipse
  • Improved XML editor: the Android Eclipse plugin now includes a custom XML formatter. The Android XML formatter allows you to auto-format XML files, and it will use the appropriate styles depending on what kind of xml file it is.
  • Logcat improvements: You can now filter by application name or Java-style regexes.
  • Easier icon creation: This is available as a webapp but will not be available as part of the Android Eclipse plugin. It makes creating assets for ldpi, mdpi, hdpi and xdpi easier.
  • If you installed the latest SDK tools and had migration troubles, you may want to take a look at how library projects are handled now. Also ADT 14 had a few issues (listed here), some of which were fixed in the subsequent r15 release, so upgrade to ADT 15 if you haven’t already.

Device Tools

Ice Cream Sandwich brings some improvements to developer and user-friendly tools on the device. Here are a few:

  • Network usage tool: This is included on devices and allows users to see which apps are consuming the most data, as well as restrict data usage after a certain threshold. For developers, it can be useful for easily making sure that your data usage is in control.
  • More developer options: It looks like you can enable strict mode, show touches, show screen updates, and other useful options and displays right on the phone.
Did we miss anything else important? Let us know and we’ll add it!

 

October 24, 2011
by albert
1 Comment

Optimizing for Different Screen Sizes

This post was originally published as part of the Pulse Engineering blog.

Android developers are well aware that devices come in all shapes and sizes. In addition to the standard phone and tablets, there are gadgets like the Galaxy Note that defy classification. Furthermore, as screen resolutions get higher and higher, a 4″ phone tomorrow may have the same resolution as a 10″ tablet today. To ensure your app will always look beautiful, we’ll explore the technical adventures in developing for the myriad screens on Android.

Resource Folders Make Your Life Easier

By far, the easiest way to ensure your app looks the way you intended is to use Resource Folders (1.6+). With Honeycomb 3.2, the ability to distinguish between screen sizes becomes more granular, granting the developer greater control. However, as of this post’s writing, Ice Cream Sandwich is not out yet, so we’ll discuss the pre-Honeycomb version of resource folders.

Screen are split up into four categories: small, normal, large, and xlarge. These correspond to general form factors like phone, small tablets, and tablets. Each classification has a screen size range detailed below:

 

 

Resource files (xml files that describe things like layouts, dimensions, styles, etc.) are placed in folders in your Android project under the res directory. You can add modifiers to the name of a resource folder which  declare under what circumstances its files should be used.

For example, if you normally put your awsome_layout.xml file in layout, you can also place a version designed for large screens in a folder called layout-large. Thus, when the app runs on a tablet-sized device, the app will automatically use the awsome_layout.xml file found in ‘layout-large’ through no additional effort. Magic! We won’t go into the details of naming your folders, but a handy guide can be found here.

Be careful though, if your layouts are drastically different you must be certain you don’t refer to views in your code that only exist in one layout file without checking its existence. This can be prevented with thorough testing and good software design.

Detecting Screen Size In Code

You may also want to exhibit different behavior on larger screens in addition to having a separate layout. For tablets, one can allot more space for buttons on the Action Bar; on phones it is preferable to keep the layout uncluttered. An example taken from Pulse is in the tablet’s landscape mode. Clicking on a story causes the article to slide in from the right rather than completely covering the screen. This takes advantage of the extra real estate to browse stories while reading an article. To do this we need a way to tell if the device is xlarge, large, or normal in the code.

There is a class called DisplayMetrics that can give us some basic information about the device we’re running on. While this may seems like a great place to start, it could also lead to many layout bugs. Don’t simply use the screen width in pixels as a measure of device size; advances in screen density tosses this assumption out the window. A 4” phone can have a screen that is 540 pixels across, whereas a 7” tablet’s screen width is a mere 60 pixels wider at 600px. If you’re not careful you could end up with behavior intended for tablets on a phone, which would be wonky to say the least.

Instead, the screen size a particular device is using (equivalent to which modifier on a resource folder gets chosen) can be found in the Configuration class by using Resources.getConfiguration method. This is the same Configuration you use to see if the device is in landscape or portrait. Using the configuration object, you can retrieve the screenLayout field and see if the device is equal to the relevant constants. With this knowledge, your app can decide how to behave properly.

But what about dynamic values?

Using resources is a very painless way to incorporate device-dependent dimensions, but sometimes you want the layout to be more adaptable. For example, in Pulse there are horizontally scrolling tiles with each square taking up 1/3 of the screen width; even when the app is in landscape, the tile widths are the same.

Since we can’t possibly know what the screen width of the device is beforehand, we use a helper class to store these predicated constants. Our class follows the singleton pattern and is used whenever this parameter is needed. The parameters are initialized with the class and are available whenever they’re needed. Here is a super simple example of such a class:

/**
* Sample class from Pulse
*
* Class to store and provide useful dimensions
*/
public class DimensionCalculator {

  private static DimensionCalculator mInstance = null;
  private int mScreenWidth;
  private int mTileWidth;

  /**
   * This class is a singleton
   */
  public static DimensionCalculator getInstance() {
    return SingletonHolder.instance;
  }

  /**
   * We use the SingletonHolder solution which is widely considered to be the
   * standard implementation in Java. Thanks to Fredia from the comments!
   */
  private static class SingletonHolder {
    public static final DimensionCalculator instance = new DimensionCalculator();
  }

  public class DimensionCalculator() {
    DisplayMetrics dm = Resources.getSystem().getDisplayMetrics();
    mScreenWidth = Math.min(dm.widthPixels, dm.heightPixels);

    int numTiles = 3;
    int tileGap = 2;
    mTileWidth = (int) ((mScreenWidth - 4 * tileGap) / numTiles);
  }

  /**
   * Return the appropriate tile size for this device
   */
  public int getTileWidth() {
    return mTileWidth;
  }

}

Now that you have the tools to help create specialized layouts and designs for phones and tablets, you have absolutely no excuse for creating a tablet app that is just a blown up version of the phone app! Happy coding!

October 18, 2011
by daniel
5 Comments

When to Use LinearLayout vs. RelativeLayout

By far the most commonly used ViewGroups in Android are LinearLayout and RelativeLayout. LinearLayout aligns multiple views horizontally or vertically; RelativeLayout aligns its child Views in relation to each other (or itself). There are other, more specialized ViewGroups (such as FrameLayout, TableLayout, or GridView) but the bulk of your hierarchy will be a mixture of LinearLayouts and RelativeLayouts.

They are similar in function so the question of which to use regularly comes up. Both have their use cases, and neither of them are appropriate all of the time. Problems which can be difficult using one layout can be a breeze with the other but it’s not always obvious which is correct.

This article will help guide you towards the right choice of layout for your hierarchies. Here are a few guidelines for usage, which I will go into more detail below:

  • Use whichever layout requires the fewest Views (typically RelativeLayout).
  • Views layered on top of each other is RelativeLayout’s job.
  • Dynamically sizing multiple Views inside of a layout is done with LinearLayout.
  • Keep in mind how your hierarchy will work with different content and screen sizes.
  • All other things equal, LinearLayout is preferable due to its ease of use.

The Fewer Views, the Better

The number one goal for your layouts should be using the fewest number of Views possible. The fewer Views you have to work with, the faster your application will run. Excessive nesting of Views further slows down your application.

A RelativeLayout hierarchy will typically use fewer Views and have a flatter tree than a LinearLayout hierarchy. With LinearLayout, you must create a new LinearLayout every time you want to change the orientation of your views – creating additional Views and a more nested hierarchy. As a result, it is recommended that you first use RelativeLayout for any layout that has any complexity. There is a high probability you will reduce the number of Views – and the depth of your View tree – by doing so.

As a reference, there is an excellent Android article on creating efficient layouts (which goes into more detail about reducing View usage). Here is a simpler version of their example:

Here is an abbreviated version of this layout using LinearLayouts. It requires two LinearLayouts and has a maximum depth of 3 (full source code):

<LinearLayout android:orientation="horizontal">
    <ImageView android:src="@drawable/icon" />
    <LinearLayout android:orientation="vertical">
        <TextView android:text="Title" />
        <TextView android:text="This is some summary text" />
    </LinearLayout>
</LinearLayout>

However, this version (using RelativeLayout) can do the same with fewer Views and a max depth of 2 (full source code):

<RelativeLayout>
    <ImageView android:id="@+id/icon" />
    <TextView android:id="@+id/title" android:layout_toRightOf="@+id/icon" />
    <TextView android:layout_below="@+id/title" android:layout_toRightOf="@+id/icon" />
</RelativeLayout>

That said – don’t try to force yourself to use nothing but RelativeLayout! There are situations where LinearLayout is a better solution, even if it uses a few more Views.

Layer Views with RelativeLayout

Sometimes you will want Views to be overlap each other. In those situations, RelativeLayout is a natural candidate over LinearLayout. There are two ways to align Views on top of each other with RelativeLayout. The first is to align the Views in relation to the parent (either by centering them, or by aligning them to the parent’s edges). The second is to align Views’ edges with each other. The example below uses both:


(Source code)

(Note: While you can technically layer Views with a LinearLayout via negative layout margins, RelativeLayout is almost always the right choice because it is better designed for it.)

Dynamically Weight View Sizes with LinearLayout

LinearLayout has a unique and useful layout parameter, layout_weight. With it you can size the Views inside of a LinearLayout in relation to each other – such as having two Buttons side by side, where one takes up 1/3rd the screen and the other takes up 2/3rds the screen.

(Source code)

RelativeLayout has no such facilities. On some level, its Views must have set bounds – whether it be set in itself, set in relation to other Views, or the parent itself. Its Views can expand and contract, but only in reaction to its bounds changing.

Consider the Extremes

Sometimes the choice of layout will be determined on the extreme circumstances of your hierarchy. “Extreme circumstances” can be anything from the content in your Views being unexpectedly large (lots of text in a TextView, an extra large bitmap in an ImageVIew), or the viewport being much smaller or larger than you had anticipated (an ldpi screen, a tablet, or even just the difference between portrait/landscape orientations).

Let’s look at a simple example – two TextViews, each in one of the corners of the screen. What happens with a naive RelativeLayout solution when the text inside of them becomes too long?


(Source code)

You can account for this problem by making sure they won’t overlap, but you can’t control how much of the width each View gets in this case – say, if we want both to take up at most half of the screen. To do that, you’ll end up using a LinearLayout:


(Source code)

I cannot give much advice since you’ll need to handle these on a case-by-case basis – but it’s something to consider while first planning your hierarchy. You may be surprised by how often you fall back to LinearLayout, though, to solve problems with extremes.

For Simple Hierarchies, Use LinearLayout

LinearLayout is easier to use than RelativeLayout. If your hierarchy is simple enough that it can be contained within a single LinearLayout, then there’s no reason to complicate things – just use LinearLayout. This advice applies whether the LinearLayout is the root view, or if you need to group a few Views further down the hierarchy.

Conclusion

Ultimately, the decision between LinearLayout and RelativeLayout is up to you. The rules above are just rough guidelines. There may be cases which are not covered that necessitate one or the other. Or it may be significantly easier to use a few LinearLayouts instead of one RelativeLayout and performance won’t be significantly affected by it.

You should focus your time on the hierarchies that matter the most. If you’ve only got a few Views on the screen and you could use either RelativeLayout or LinearLayout, take your pick. But if you’re working with a ListView row, you’ll want to reduce your View usage as much as possible for performance.

Good luck with making your hierarchies as effective as possible! If you want to play around with any of the code from this article, you can find the source code for the samples here.

October 10, 2011
by Indy
32 Comments

Handling ListViews with Multiple Row Types

When you start writing Android Apps it isn’t long before you need to use ListViews. ListViews are easy to get started with, but it’s also very easy to write inefficient lists that wreak havoc on scrolling performance. There are lot of things you can do to improve scrolling performance. You should always use convertViews to reduce creating new views. You should use the ViewHolder pattern outlined in the Android API example to reduce lookup time in layouts. If you have images in your lists the same principles outlined in my quora answer for iOS UITableViews applies to Android ListViews.

But what happens when not every item in your list view looks the same? This is often the case when you want to build a ListView that’s presenting some type of feed where some rows have images, some have videos, and some are just text and they come in no particular order. You can and should still use all the methods mentioned above. But item view reuse suddenly becomes much more complicated. You definitely don’t want to go back to not reusing the convertView, just to handle multiple row types. This is where the view type methods in the Adapter come in.

Before moving on let’s do a quick review of how ListViews and their adapters interact. If you’ve used ListViews and Adapters before before you can probably skip this paragraph. When you set an adapter on a ListView by using the setAdapater(Adapter) method, you are telling the ListView to use the adapter to tell it what to show in the list. The two key methods for the Adapter are getCount and getView. The list view calls the adapter’s getCount to know how many items exist in the list. Then only for the rows that are visible on the screen it calls getView which returns the view to show at that item.

The two additional methods android Adapters provide for managing different row types are: getItemViewType(int position) and getViewTypeCount(). The list view uses these methods create different pools of views to reuse for different types of rows.

Pools? ConvertViews? Huh?

Let’s step back for a minute and take look at how the whole convertView business works. Internally ListViews try to do a lot of work to scroll smoothly. One of the things they do is to reuse view instances when scrolling. Everytime a ListView gets a view through the getView method in your adapter, the ListView keeps that view in a pool of views that can be reused. The convertView parameter in getView is a view from this pool. If you get a non-null convertView in the getView method of your adapter, that means the ListView is telling you: “Sup dawg, I heard you want to show something here. Instead of wasting time by creating a new view, just take the one I am giving you and change its contents.”

So what about those type methods?

getViewTypeCount() tells the ListView how many of these view pools to keep. And getItemViewType(int position) tells the ListView which of these pools the view at this position belongs to. That way the ListView can give you just the right type of view as the convertView for reuse in later getView calls.

A good way to think about these pools is that ListView keeps an array of pools. The getViewTypeCount is the size of this pool array, and getItemViewType gives the index of the pool to use. What this means is that it’s important to return 0 indexed numbers in getItemViewType. It’s not a tag, it’s an index into an array.

It may help to think of a negative case to understand how this works. If you return the wrong index in getItemViewType for a particular row, then the ListView will obligingly pass you the wrong view in a convertView when you scroll. Your reuse code will then look for something that doesn’t exist and KABLAMO! Your app will crash. So it’s important to be careful about passing the right view type.

That’s a lot of words yo. Gimme some code. Show me how it really works.

Ok. Let’s use an example to explain. Let’s say we are making an app which helps you learn about animals. Let’s call this app… aah… Animals. On its home screen the app shows you an eclectic collection of Animals. Ideally you want to show an image and the name, but sometimes you don’t have an image for the animal. In that case you want to show a completely different layout in your row. Instead of the image you want to give a short description of the animal.

Animals App Screenshot

Our core model for this class is a POJO called Animal which has three fields: imageId, name, and description. The adapter is given a list of these animals to display. Since we have two types of rows our getViewTypeCount method for the adapter simply returns 2.

public int getViewTypeCount() {
    return 2;
}

The getItemViewType method returns the right index based on the data:

public int getItemViewType(int position) {

    //we have an image so we are using an ImageRow
    if (animals.get(position).getImageId() != null) return 0;

    //we don't have an image so we are using a Description Row
    else return 1;
}

Our getView method uses the same logic in getItemViewType and branch to a different way to fill up the view:

public View getView(int position, View convertView, ViewGroup parent) {
    //first get the animal from our data model
    Animal animal = animals.get(position);

    //if we have an image so we setup an the view for an image row
    if (animal.getImageId() != null) {
        ImageRowViewHolder holder;
        View view;

        //don't have a convert view so we're going to have to create a new one
        if (convertView == null) {
            ViewGroup viewGroup = (ViewGroup)LayoutInflater.from(AnimalHome.this)
                    .inflate(R.layout.image_row, null);

            //using the ViewHolder pattern to reduce lookups
            holder = new ImageRowViewHolder((ImageView)viewGroup.findViewById(R.id.image),
                        (TextView)viewGroup.findViewById(R.id.title));
            viewGroup.setTag(holder);

            view = viewGroup;
        }
        //we have a convertView so we're just going to use it's content
        else {
            //get the holder so we can set the image
            holder = (ImageRowViewHolder)convertView.getTag();

            view = convertView;
        }

        //actually set the contents based on our animal
        holder.imageView.setImageResource(animal.getImageId());
        holder.titleView.setText(animal.getName());

        return view;
    }
    //basically the same as above but for a layout with title and description
    else {
        DescriptionRowViewHolder holder;
        View view;
        if (convertView == null) {
            ViewGroup viewGroup = (ViewGroup)LayoutInflater.from(AnimalHome.this)
                    .inflate(R.layout.text_row, null);
            holder = new DescriptionRowViewHolder((TextView)viewGroup.findViewById(R.id.title),
                    (TextView)viewGroup.findViewById(R.id.description));
            viewGroup.setTag(holder);
            view = viewGroup;
        } else {
            view = convertView;
            holder = (DescriptionRowViewHolder)convertView.getTag();
        }

        holder.descriptionView.setText(animal.getDescription());
        holder.titleView.setText(animal.getName());

        return view;
    }
}

That’s all there is to it. You now know how to use the view type methods to handle different row layouts in your lists. Class is over.

Umm wait… That’s some ugly lookin’ code. Can’t we do better?

Glad you asked! There are three things particularly ugly about this code. First we are using magic numbers for the values returned by our getItemViewType and getViewTypeCount methods. Second, we are repeating the same branching pattern in two different methods, getView and getItemViewType. Third, that getView method is long. All these things together make this code brittle and hard to maintain over the long term.

So how do we deal with all these problems? We introduce the concept of a Row object. You can think of a Row as a controller for each item in your list. It’s an interface that is implemented by the two different types of Rows in our example: ImageRow and DescriptionRow. When we construct our adapter we take the list of animals it’s given and create the right Row object for each animal.

AnimalAdapter(List<Animal> animals) {
    rows = new ArrayList<Row>();//member variable

    for (Animal animal : animals) {
        //if it has an image, use an ImageRow
        if (animal.getImageId() != null) {
            rows.add(new ImageRow(LayoutInflater.from(AnimalHome.this), animal));
        } else {//otherwise use a DescriptionRow
            rows.add(new DescriptionRow(LayoutInflater.from(AnimalHome.this), animal));
        }
    }
}

So what do these Row objects actually do? Well let’s take a look at the interface definition:

public interface Row {
    public View getView(View convertView);
    public int getViewType();
}

This probably looks very familiar. That’s because these methods look almost exactly like getView and getItemViewType methods from the Adapter interface we talked about earlier. In each of these methods of the adapter we hand off the work to relevant method in the Row object itself. So when you call getView it gets the Row object for that position and asks it to return the correct view. For an ImageRow it returns a row where you have a title and an image, and for a DescriptionRow it returns a row that has a title and a description. Here’s what the getView and the getItemViewType methods on the adapter look like:

public int getItemViewType(int position) {
    return rows.get(position).getViewType();
}

public View getView(int position, View convertView, ViewGroup parent) {
    return rows.get(position).getView(convertView);
}

So what do view type methods actually return? We could just return 0 for ImageRows and 1 for DescriptionRows and when the the adapter’s getViewTypeCount method is called, return 2 and call it a day. But we wanted to avoid using magic numbers in our code so instead we use an Enum.

public enum RowType {
    IMAGE_ROW,
    DESCRIPTION_ROW
}

So getViewType for ImageRow returns RowType.IMAGE_ROW.ordinal(), and for DescriptionRow it returns RowType.DESCRIPTION_ROW.ordinal(). getViewTypeCount on our adapter simply returns RowType.values().length.

All in all our adapter looks like this:

private class AnimalAdapter extends BaseAdapter {
    final List<Row> rows;

    AnimalAdapter(List<Animal> animals) {
        rows = new ArrayList<Row>();//member variable

        for (Animal animal : animals) {
            //if it has an image, use an ImageRow
            if (animal.getImageId() != null) {
                rows.add(new ImageRow(LayoutInflater.from(AnimalHome.this), animal));
            } else {//otherwise use a DescriptionRow
                rows.add(new DescriptionRow(LayoutInflater.from(AnimalHome.this), animal));
            }
        }
    }

    @Override
    public int getViewTypeCount() {
        return RowType.values().length;
    }

    @Override
    public int getItemViewType(int position) {
        return rows.get(position).getViewType();
    }

    public int getCount() {
        return rows.size();
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        return rows.get(position).getView(convertView);
    }
}

As you can see our Adapter code is super simple! It’s because it passed all the hard work to the Row objects which have clear ownership of what their views look like and how they behave. Obviously you’re itching to see the code for the whole app and how it all works together. So you can download the whole Animals app here.

If you want to really understand how this pattern works do the following exercise with the downloaded code. Add a third type of row: ImageDescriptionRow. If you have all three pieces of data, image, title and description for an animal, then show the title and image just like the ImageRow but also show a description below spanning the width of the row.

October 4, 2011
by jean
6 Comments

Using Custom Fonts

In Android, the three default font options are monospace, sans serif and serif. You do have some flexibility with adding effects to the default fonts, but without custom fonts, you are pretty limited in how text in your Android appears to your users. Luckily, it’s fairly straightforward to set a custom font. You can find plenty of free custom fonts at sites like dafont.com – just download the .ttf file for the font of your choice, and add it to the assets/fonts directory of your codebase (create the directory if it doesn’t exist already).

Custom Fonts in Views

If, for example, you’d like to set the font for a TextView with id=name, it’s as simple as adding the following to your code:
TextView name = (TextView) findViewById(R.id.name);
Typeface typeface = Typeface.createFromAsset(getContext().getAssets(),
    "fonts/customFont.ttf");
name.setTypeface(typeface);
That’s fine when you have just one or two TextViews with custom fonts, but it gets to be a pain when you want customized fonts on all your TextViews. That’s a lot of boilerplate code to have in your activities! It would be convenient to be able to specify the font name in xml. To do this, you can extend TextView:
public class CustomTextView extends TextView {
  private static final DEFAULT_FONT="defaultFont.ttf";
 
  public CustomTextView(Context context) {
    this(context, null);
  }

  public CustomTextView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView, 0, 0);
    String fontName = arr.getString(R.styleable.CustomTextView_fontName);
    // Sets to a default font if none is specified in xml
    if (fontName == null) {
      fontName = DEFAULT_FONT;
    }
    setFont(fontName);
  }

  private void setFont(String fontName) {
    Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/" + fontName);
    setTypeface(typeface);
  }
}
In your attrs.xml (in res/values/, create the xml file if it doesn’t exist already), add an attribute for CustomTextView as follows:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomTextView">
       <attr name="fontName" format="string"/>
    </declare-styleable>
</resources>
Now you can add a custom font to a TextView in xml, without any additional code to your activities:

<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:example="http://schemas.android.com/apk/res/com.example.customfonts"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
    <com.example.customfonts.CustomTextView
       example:fontName="customFont2.ttf"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" />
</LinearLayout>

That’s it! Now you can easily set custom fonts for views in xml.

Custom Fonts in WebViews

For webviews, you still want to copy the .ttf file into your assets/fonts directory, and then you can create new font-faces in your css and use them by setting font-family:
<style type="text/css">
    @font-face {
        font-family:"customFont1";
        src:url('file:///android_asset/fonts/customFont.ttf');
    }
    @font-face {
        font-family:"PTS55F";
        src:url('file:///android_asset/fonts/customFont2.ttf');
    }

    body { font-family:'customFont'; }
    h1 { font-family:'customFont2'; }
</style>

Using custom fonts gives you a lot more control over the visual appearance of your application, but when don’t get carried away — using too many random fonts can make an app seem very disjointed. In general, try to use at most a few fonts that go well together. To get you started, here are 40 free designer fonts.

September 26, 2011
by daniel
7 Comments

Working with JSON

JSON (JavaScript Object Notation) is one of my preferred data formats for Android.  It is a wonderful mixture of ease-of-use, compactness and speed. You can use it to pass data between Activities (much easier than Parcelables, but for most cases not prohibitively slower), store data on the disk (easier than setting up an SQLite database for small amounts of data), or transfer data to and from your application to the internet (and quite compact when combined with gzip).

In this post, we’ll examine the different ways you can handle JSON, their relative strengths and weaknesses, as well as some examples to get you started.

Three Ways of Handling JSON

There are three basic methods for handling JSON:

Tree Model – The JSON document is a mutable in-memory tree.  There is a built-in org.json package that uses the tree model (via JSONObject and JSONArray).

Streaming – The JSON document is read and written in a streaming fashion.  In Honeycomb, JsonReader and JsonWriter were introduced as the streaming solution for handling JSON.  (If you want to use this library pre-Honeycomb, you can download the google-gson-streaming library, which has the same classes.)

Data Binding – Automatic conversion between JSON and a POJO (Plain Old Java Object).  There is no built-in Android functionality for this method, however there are plenty of libraries out there.

The primary battle between the tree model and streaming is memory vs. ease of use.  The tree model can run into memory problems: not only does the entire JSON document need to be in memory, but you can end up storing unnecessary data you don’t need.  In some situations you will have duplicates of the data in memory (e.g., if you convert the tree to Java objects or vice versa). On the other hand, it is much easier to read and manipulate data via a tree model since the entire object is held in memory; with streaming, you have to hand-hold the data closely.

As a secondary concern, streaming tends to be faster than the tree model.  For most situations this won’t be consideration – if you need speed, chances are you’re already parsing so much data that you’d be using streaming anyways out of memory concerns.

Data binding is convenient, but it’s not as flexible as the tree model nor as fast as streaming. Additionally, it does not save much effort – you still have to write the code to map JSON to a POJO. I think there is potential to make data binding much easier by automatically generating POJOs from a JSON template – thus justifying its deficiencies in comparison to the other methods – but I do not know of a library that does this yet.

I will not be covering data binding since Android has no built-in API; you’ll have to find a library on your own that utilizes it and read their documentation, as the implementation differs in the varying libraries.

Using JSONObject and JSONArray (Tree Model)

Here is a sample JSON object that we want to parse:

{
    "name": "Joe Shmoe",
    "height": 68.5,
    "age": 31,
    "hungry": true
}

With the tree model, initial parsing is simple:

String data = "{\"name\": \"Joe Shmoe\",\"height\": 68.5,\"age\": 31,\"hungry\": true}";
JSONObject person = new JSONObject(data);

To read data, you can either use getX() or optX() (where X is the data type).  The difference between the two is that getX() requires the field to be there and will throw exceptions if the field does not exist.  As a result, I typically use optX() methods with fallbacks:

String fullName = person.optString("name", null);
double height = person.optDouble("height", 0);
int age = person.optInt("age", 0);
boolean hungry = person.optBoolean("hungry", false);
String faults = person.optString("faults", null);

Reading JSONArray data is similar, except you reference indices instead of fields.

To write the above JSON using the tree model, you can just create a JsonObject then start placing data into it.  Once you’re done, you can use JsonObject.toString() to write out the JSON document as a String:

JSONObject person = new JSONObject();
person.put("name", "Joe Shmoe");
person.put("height", 68.5);
person.put("age", 31);
person.put("hungry", true);
person.putOpt("faults", null);
String data = person.toString();

putOpt() only inserts an entry when both the name and the value are non-null.  This creates a handy shorthand so you don’t have to null-check data in variables before putting them into a JsonObject.

Using JsonReader and JsonWriter (Streaming)

Streaming parsing of JSON via JsonReader is more complex.  First, you need to create a Reader for the constructor based on your input (String, InputStream, etc.):

JsonReader reader = new JsonReader(new StringReader(data));

The JsonReader works by iterating through field names/values and parsing each one by hand. You also have to explicitly tell the JsonReader when an object or array has begun. Parsing the JSON above uses a standard JsonReader pattern for parsing objects:

reader.beginObject();
while (reader.hasNext()) {
    String name = reader.nextName();
    if (reader.peek() == JsonToken.NULL) {
        // Ignore null values
        reader.skipValue();
    }
    if (name.equals("name")) {
        fullName = reader.nextString();
    }
    else if (name.equals("height")) {
        height = reader.nextDouble();
    }
    else if (name.equals("age")) {
        age = reader.nextInt();
    }
    else if (name.equals("hungry")) {
        hungry = reader.nextBoolean();
    }
    else if (name.equals("faults")) {
        faults = reader.nextString();
    }
    else {
        // Skip fields we don't want to parse
        reader.skipValue();
    }
}
reader.endObject();

Two things to pay attention to: JsonReader.peek() lets you take a look at the type of the value, which is helpful in parsing to avoid parsing null values (or when there are multiple potential data types in a field).  JsonReader.skipValue() lets you skip a field and all its children, which is not only required for ignoring fields you don’t want to parse but also speeds up parsing by allowing you to skip parts of the data.

JsonWriter is very similar to JsonReader.  First you create a Writer to write your data to, then you explicitly declare objects and arrays and place data into them:

StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
writer.beginObject();
writer.name("name").value("Joe Shmoe");
writer.name("height").value(68.5);
writer.name("age").value(31);
writer.name("hungry").value(true);
writer.endObject();
String data = stringWriter.toString();

Other JSON Libraries

The built-in JSON handlers are not the best or the brightest.  The org.json library lacks a streaming read/write method (which creates extra memory headaches) and the google-gson JsonReader/JsonWriter are not the fastest streaming JSON solutions.  Their main advantage is that they are built-in – no need to include extra libraries that increase the APK size.

Luckily there are plenty of good, free, open source alternatives out there.  Keeping in mind that benchmarks can be misleading, the jvm-serializers project does a good job of comparing the relative speeds of different JSON parsers.  You can also use the page as a reference to check out feature sets of each library.

Personally, I have used Jackson to great success, parsing through large amounts of data efficiently and would recommend it if you are looking for a high-performance JSON reader/writer.  Additionally, its library is very similar in nature to the built-in Android APIs and so it’s not difficult to adapt your code if you want to switch to it at a later date.

September 21, 2011
by jean
11 Comments

Not Just Another Android Development Blog

If you’ve ever Googled to find a solution for a technical Android development problem, you’ve probably ended up on Stackoverflow, which is great for specific problems, but not as great for more comprehensive good-practice tips and overviews. The official Android developer blog is well-maintained and has high-quality posts, but we think there’s room for a collaborative development blog run by app developers. We want to provide a reputable place where Android developers can trust that the posts are technically accurate, and just generally interesting and awesome content.  That’s where we come in.

Who are we?

We are Android developers who work daily on some of the most downloaded and top-rated apps in Android Market. Here’s a little more about us:

Daniel Lew

Daniel is an Android developer for Mobiata, working on travel apps such as FlightTrack, FlightBoard, HotelPal and Expedia Hotels.  He’s also written a number of free, open source Android apps (most notably Rage Faces and Headset Blocker).  When he’s not in front of a computer, Daniel plays music, swims and fails to win at board games.

Indy Khare

Indy specializes in client-side mobile development at Bump, both on Android and iOS. Before joining Bump, Indy founded a mobile startup that created some of the most popular early iPhone apps. Indy did his Masters at Stanford focusing on HCI and design after graduating from UCSD. To clear his mind, Indy spends his weekends hiking and trying out delicious new restaurants.

Albert Lai

Albert began working on Pulse for Android while on vacation in China during the summer of 2010. His first foray into Android development was for the 2009 Android Developer’s Challenge and has been enamored with the mobile world since. He received his Bachelor’s in EECS from UC Berkeley followed by a Masters in CS at Stanford. Music, snowboarding, and college football compete with coding for his attention and you can follow Albert on twitter @albertlai

Jean Hsu

Jean is an Android developer at Pulse, a popular reading app that brings together your favorite websites. Before she entered the startup world last year, she worked at Google on some experimental payment apps. Jean holds a Bachelor’s of Engineering in Computer Science from Princeton University. She blogs and tweets about her startup adventures and Android tips at jeanhsu.com and @jyhsu.

How can we help?

We want this blog to provide the most value possible for other Android developers out there. What are you working on, and what topics would you like to hear more about?