Showing posts with label code. Show all posts
Showing posts with label code. Show all posts

Thursday, September 12, 2013

Lazy Lists

Let's talk about laziness. No, let's not just talk about being lazy - let's do something about it. Let's be lazy.

There's a common pattern that I use in Android programming where I will create objects lazily, especially when these objects will not necessarily or frequently be needed at runtime. This is especially true for code that I write for the Android framework, where we like to be as lean as possible and leave more memory available for the system and the application.

Often, these objects are collections. My personal favorite is ArrayList (ever since I moved on years ago from the original, but somewhat crusty, Vector class), although I am also known to use Hashmap for those key/value pair situations (especially after I got used to ActionScript's paradigm of everything-is-a-hashmap).

Of course, you can't simply start poking into a lazily-created collection willy-nilly, unless you're a big fan of NullPointerExceptions. So you need to first check whether the thing is null, and then create it as necessary. Similarly, if you're removing an item from the collection, you might want to check if it's now empty and reset the field to null again.

None of this is difficult... but it is tedious. And it tends to bloat the code that you have to read and write and maintain all over the place. And it's exactly the kind of thing that is easy to get wrong because your mind just blurs over the repeated pattern like it's yet another pile of dirty laundry next to the bed.

So I wondered if there was a way I could encapsulate the behavior I wanted to make my laziness easier, simpler, and more readable. And it turns out there was such a way (or else this would be a very short article that would have ended right around... now).

But first, let's look at the problem a bit more, to understand what we're trying to fix.

I have a class called LazyLists with a couple of List fields and some methods for adding and removing items of various types. First, there are the fields:

List<Integer> intList = null;
List<Float> floatList = null;

Then there are add/remove fields for the int/float types I care about:

public void addItem(int item) {
    if (intList == null) {
        intList = new ArrayList();
    }
    if (!intList.contains(item)) {
        intList.add(item);
    }
}

public void removeItem(int item) {
    if (intList != null) {
        intList.remove((Object) item);
        if (intList.isEmpty()) {
            intList = null;
        }
    }
}

public void addItem(float item) {
    if (floatList == null) {
        floatList = new ArrayList();
    }
    if (!floatList.contains(item)) {
        floatList.add(item);
    }
}

public void removeItem(float item) {
    if (floatList != null) {
        floatList.remove(item);
        if (floatList.isEmpty()) {
            floatList = null;
        }
    }
}

There are a few things to notice about these methods:
  • There's all of that boilerplate code I mentioned before that lazily creates and nulls out the appropriate list based on the state of the list at the time. This is what we'd like to clean up, since this code is repeated as many times as we have to access these list fields.
  • I run a uniqueness check in the addItem() methods because it suits me; I only want to add unique items, not the same items over and over. That's kind of a detail that's specific to my situation, but produces more boilerplate that I'd love to get rid of.
  • There an interesting nuance to the int variation of removeItem(). Do you see it? It's the cast to Object prior to removing the item from intList. This is because of the awkward crossover between primitive types (int, float, etc.) and Object types (Integer, Float, etc.) in Java. There are actually two remove() methods on List, one that takes an int and one that takes an Integer. The one that takes an int removes the item at that index, whereas the Integer variant removes that item itself. That's a pretty huge distinction. And maybe it's well-known to you if you've worked with Lists and ints, but I hit it when working on this example, and thought it was interesting enough to call out.
Anyway, moving on.

We can call the methods above and produce lists that dynamically change with the items that we add/remove. For example, this code creates the class, adds items to the two lists, and removes those items:

LazyLists lists = new LazyLists();
lists.addItem(0);
lists.addItem(1f);
lists.removeItem(0);
lists.removeItem(1f);

Adding a bit of tracing code gives us this output:

starting lists = null, null
populated lists = [0], [1.0]
ending lists = null, null

So there's not too much cruft above, but I figure the second time I'm repeating the same code, I should think about refactoring it in a way that avoids the repetition. And it's easy to imagine that there might be several places in real code that wants to add/remove items, or several different types going into several different types of collections. Then it's easy to see the little bits of repeated code above bloating into more than you might want to manage in the long haul.

There are various ways that you could do this, depending on the collection(s) you want to support, the extra logic you'd like (like my requirement for uniqueness in the lists), and stylistic elements about static methods, etc. But here's what I wound up with:

public class LazyListManager {

    public static  List add(List list, T item) {
        if (list == null) {
            list = new ArrayList();
            list.add(item);
        } else if (!list.contains(item)) {
            list.add(item);
        }
        return list;
    }

    public static  List remove(List list, T item) {
        if (list != null) {
            list.remove(item);
            if (list.isEmpty()) {
                list = null;
            }
        }
        return list;
    }
}

This simple class has two static methods on it to support adding and removing from an arbitrary List object. As needed, it will create a new List (actually, an ArrayList, but that's an implementation detail). It will check for uniqueness in the add() method, check for nullness in the remove() method, and null out an empty list in remove() as appropriate.

There is an important piece here that makes this work - callers must supply their target list as both a parameter to the function and as the recipient of the return value; this is what makes it possible for these utility methods to allocate or null-out the list as appropriate (since they do not have access to the original list, but only have a reference to it).

Given these two static utility methods, we can now write new addItem() and removeItem() methods that are a significantly better (you can't get less than one line of code, unless I missed that part in my CS education):

public void addItemBetter(int item) {
    intList = LazyListManager.add(intList, item);
}

public void removeItemBetter(int item) {
    intList = LazyListManager.remove(intList, item);
}

public void addItemBetter(float item) {
    floatList = LazyListManager.add(floatList, item);
}

public void removeItemBetter(float item) {
    floatList = LazyListManager.remove(floatList, item);
}

Calling these methods looks remarkably similar to what we saw before:

lists.addItemBetter(0);
lists.addItemBetter(1f);
lists.removeItemBetter(0);
lists.removeItemBetter(1f);

and results in exactly the same output (which shouldn't be a surprise. If the results were different, this approach wouldn't be a utility as much as a bug):

starting lists = null, null
populated lists = [0], [1.0]
ending lists = null, null
populated lists = [0], [1.0]
ending lists = null, null

The LazyListManager class has taken out all of the tedious boilerplate related to null checks, uniqueness, allocation, and nullification, and has left us with just one line of code to write whenever we want to add or remove items to/from one of our lists. That's just about the right amount of code for me to write without making a typo or a copy/paste error along the way.

If this were public API, I could envision the manager class offering various different kinds of collections and options, or maybe wrapping more of the capabilities of collections classes (like isEmpty() or contains()). But for now, it's a nice little internal class that can help me simplify my code whenever I need to use this lazy-allocation pattern.

All of the interesting code is inline above, but if you want the two source files, you can download them here.


Friday, August 9, 2013

DevBytes: Cartoon Animation Techniques

This time, we wrap up the series on cartoon animation techniques with a demo that shows a few of the techniques in the context of a larger application. Because it's nice to know how to write the code, but you might also be wondering why you might want to.

For some real-world context, you could also check out games such as Candy Crush Saga (a horribly addictive game I've gotten sucked into that's less like casual gaming and more like casual crack). It uses a veritable plethora of cartoon animation techniques to keep the player engaged with the game and disengaged from their life.

This and other cartoon animation techniques were discussed in the talk A Moving Experience at Google I/O 2013

Code: http://developer.android.com/shareables/devbytes/ToonGame.zip

YouTube: https://www.youtube.com/watch?v=8sG3bAPOhyw&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0

Friday, August 2, 2013

DevBytes: Squash & Stretch

Cartoon animation uses a technique called "squash & stretch" for achieving different effects of objects interacting with their environment.

This episode shows how we can use similar techniques to get more organic and lively animations in user interfaces.

This and other cartoon animation techniques were discussed in the talk A Moving Experience at Google I/O 2013.

Code: http://developer.android.com/shareables/devbytes/SquashAndStretch.zip

YouTube: https://www.youtube.com/watch?v=wJL1oW6DlCc



Or, in illustrated form:



Friday, July 26, 2013

DevBytes: Anticipation & Overshoot, Part 2

Like my previous DevBytes episode, Anticipation and Overshoot, Part I," this episode covers cartoon animation techniques for making UI elements more engaging and playful. The code in this episode shows how to change and animate how a button is drawn to make it seem more alive and organic.

This and other cartoon animation techniques were discussed in the talk A Moving Experience at Google I/O 2013.

Code: http://developer.android.com/shareables/devbytes/Anticipation.zip

YouTube: DevBytes: Anticipation and Overshoot - Part 2

Friday, July 19, 2013

DevBytes: Anticipation and Overshoot, Part 1

Some principles of cartoon animation can be used to provide more engaging and more interactive experiences in applications.

This episode demonstrates principles of anticipation and overshoot with a simple button click, showing how to animate changes in the button's appearance to make it interact more playfully with the user.

This and other cartoon animation techniques were discussed in the talk A Moving Experience at Google I/O 2013

Code: http://developer.android.com/shareables/devbytes/LiveButton.zip

YouTube: https://www.youtube.com/watch?v=uQ7PTe7QMQM


Friday, July 12, 2013

DevBytes: Curved Motion

This is a demo that +Romain Guy and I showed in our A Moving Experience talk at Google I/O this year, showing how to use the existing TypeEvaluator and Animator APIs to get curved motion for your animations.

In the real world, things don't move in straight lines. Moving items around on the screen should feel as natural as possible; sometimes curved motion can help.

This episode shows how to use the existing animation APIs to get easy curved motion for your UIs.

The helper classes come from an article I posted on my blog last year:
http://graphics-geek.blogspot.com/2012/01/curved-motion-in-android.html

YouTube: https://www.youtube.com/watch?v=JVGg4zPRHNE

Code: http://developer.android.com/shareables/devbytes/CurvedMotion.zip

Friday, June 28, 2013

DevBytes: Animating Multiple Properties in Parallel

Suppose you want to animate multiple properties in parallel on some target object. How would you do it? ValueAnimator? Multiple ObjectAnimators?

This episode covers different ways of animating multiple properties, and specifically covers the use of the lesser-known PropertyValuesHolder class.

YouTube: https://www.youtube.com/watch?v=WvCZcy3WGP4

Code: http://developer.android.com/shareables/devbytes/MultiPropertyAnimations.zip

Friday, June 21, 2013

DevBytes: Animating ListView Deletion: Now on Gingerbread!

In this episode, I tried to anticipate the question I knew would come up on my previous show about animating ListView deletion: "But how would I do this on Gingerbread?"

Here's how.

YouTube: https://www.youtube.com/watch?v=PeuVuoa13S8&list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0&index=1

Code: http://developer.android.com/shareables/devbytes/ListViewItemAnimations.zip

Friday, June 14, 2013

DevBytes: Animating ListView Deletion

It's Friday: must be time for another DevBytes episode.

Finally, here is the DevBytes episode around the ListView animation demo in the talk A Moving Experience that I gave with Romain Guy at Google I/O last month.

The code is nearly the same as that in the I/O talk, except I tweaked it to make it more general-purpose. Specifically, it no longer depends on the setHasTransientState() method (introduced in Jellybean 4.1) to keep the views around while fiddling with layout. Instead, it uses an adapter with stable itemIds, and uses those Ids to track where the content is before and after layout.

As written, the code is still dependent on Android 4.1, but that's only because of the use of ViewPropertyAnimator.withEndAction() method, which is really just syntactic sugar around adding a listener and running the end-action code in the onAnimationEnd() callback. So you could totally port this code all the way back to Android 3.1 (when ViewPropertyAnimator was introduced) or even 3.0 (if you use ObjectAnimator instead).

Watch the video. Check out the code. Play with ListView. Animate. Enjoy.

A Moving Experience: http://www.youtube.com/watch?v=ihzZrS69i_s

DevBytes on YouTube: http://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0

Code: http://developer.android.com/shareables/devbytes/ListViewRemovalAnimation.zip

Friday, June 7, 2013

DevBytes: Custom Activity Animations

It's Friday: time for another DevBytes.

It's been a while, but they're back. At least until the queue runs out again and I write another glut of demos to talk about.

This episode, and most of the upcoming ones (teaser alert!) are around demos/code that we showed in A Moving Experience, the animation talk that +Romain Guy and I gave at Google I/O 2013.

Custom Activity Animations:
Window animations provide an easy way to animate transitions between activities. The animations can be customized to some extent, but there's only so much interaction between the launching and launched activities that you can take advantage of with the standard window animations.
This episode covers a different technique for fully customizable animations.

Video: http://www.youtube.com/watch?v=CPxkoe2MraA

Code: http://developer.android.com/shareables/devbytes/ActivityAnimations.zip

Friday, May 17, 2013

Google I/O Presentations Now Live

Romain Guy and I gave two talks at Google I/O yesterday which are now live on YouTube:

Android Graphics Performance: http://www.youtube.com/watch?v=vQZFaec9NpA



Slides for Android Graphics Performance are posted on Romain's blog.


A Moving Experience: http://www.youtube.com/watch?v=ihzZrS69i_s



A Moving Experience Slides:

The code from the animation demos will be posted soon, probably in conjunction with future DevBytes episodes.

Thursday, March 28, 2013

For API Nerds: Interfaces and Inner Classes

This article is for API developers only. If you're writing an application, you may not care about APIs, because you probably don't have any. But if you're writing a library that others will use, public API comes into play.

API is like a pile of laundry: you can either spread the huge, reeking mess out all over your floor, or you can stuff it into a nice, clean hamper. While the first approach provides the convenience of being able to select each day's pre-soiled attire quickly, since it is arrayed out in front of you when you get out of bed, the second solution presents a clean interface to people that make the mistake of walking into your pathetic, slovenly life.

Good APIs prefer hampers.

I was implementing a new piece of API and functionality and wondered the following: Is there any reason to not put my implementation (which I did not want in the public API, and which would be the only implementation of said interface) inside the interface itself? It seems odd, perhaps, maybe even a bit tawdry, but is there anything wrong with it?

My motivation was simple: I'm adding this API and implementation into a package that already has many classes to wade through. Should I bother adding more noise to the list for an implementation detail of this single interface? Why not put it into the interface file, and just bundle up that implementation in a logical place, tightly bound to the interface that it implements?

So I did this, coming up with something like the following:

public interface A {
    void a();

    static class AImpl implements A {

        @Override
        public void a() {
            // ...
       }
   }
}

Additionally, an existing class exposed a single method giving a reference to this interface:

public A getA() {
    return new AImpl();
}

This worked well - the users of the public getA() method got what they needed: an object of type A with its spectacular, if slightly under-documented, method a(). And I successfully hid the implementation class inside of this same file, as a package-private static class, saving my package the unbearable burden of yet another file.

Done!

Then I ran JavaDocs on my project and realized my mistake: my supposedly package-private implementation class was now part of the public API, showing up as the public class A.AImpl. What th-... I didn't say it was public! In fact, I explicitly made it package-private, so that the class exposing the new getA() method could instantiate an instance of that class. So what happened?

Interfaces happened. Interfaces do not use the same access rules as classes. Instead, all members of an interface are public by default. So while I used the correct (to my mind) syntax for package-private access, I was actually using the correct (to the mind of my interface) syntax for declaring that inner class public, and the JavaDocs did the rest.

Do I hear you yelling, "You could make it private!?" Or is that just the echo of my internal shouting when I first saw the problem? This is what I tried to do. This fails for (at least) two reasons. One is that I actually needed this class to be package-private (not private), so that I could instantiate it and override it from outside of this interface. An even better reason is that you cannot declare different access permissions than the default that the interface uses. In this case, that means that I cannot have a public interface with a private inner class. I could declare the entire interface to be private... but that defeats the whole thing I was going for by exposing the interface A as a public API.

There are other ways around this. For example, there is a mechanism we use in Android framework code, @hide, to solve the problem of having to expose API internally but not wanting it to be a part of the public API (a workaround for the language not having the ability to differentiate between internal and external access to library APIs). But at the point where I considered using this workaround, the awkwardness of putting the class inside of the interface just got to be too much.

In the end, I just pulled the class out and put it at the same level as A. It added another file to the package, but that really wasn't that big a deal anyway. And it was certainly better than the mess I was creating with my class-inside-interface approach.

The moral of the story is: API design is tricky. Consider not only the internal implementation details ("Can I make my life easier by implementing the solution in this particular way?"), but also (and wayyyyy more importantly), "Can I make the API, and therefore the lives of external developers, better by doing it in this other way?"

Here is a technical diagram, illustrating the problem and the original solution:



Friday, March 22, 2013

DevBytes: Layout Transitions

The LayoutTransition class (added in Android 3.0) enables easy fade/move/resize animations when items are added to or removed from a ViewGroup, usually with just one line of code. This video shows how this works and also shows the new ability added in JellyBean (Android 4.1) to animate other changes to the layout as well, not limited to items being added or removed.

YouTube:
https://www.youtube.com/watch?v=55wLsaWpQ4g

Code:
http://developer.android.com/shareables/devbytes/LayoutTransChanging.zip

Friday, March 15, 2013

DevBytes: PictureViewer

PictureViewer: How to use ViewPropertyAnimator to get a cross-fade effect as new bitmaps get installed in an ImageView.

TransitionDrawable is a handy and easy facility for cross-fading between two drawables. But if you want to cross-fade between an arbitrary set of images, you might want something more general-purpose. Here's one approach.

YouTube: https://www.youtube.com/watch?v=9XbKMUtVnJA

Code: http://developer.android.com/shareables/devbytes/PictureViewer.zip

Friday, March 8, 2013

DevBytes: Request During Layout

Horrible things can result from calling requestLayout() during a layout pass. DON'T DO THIS.

The demo that I wrote to show why this is bad seems very contrived, but I have since run across application code that did nearly the exact same thing, explicitly calling requestLayout() during onLayout(). Ugh. Typically, the cases where this problem occurs are a tad more subtle than that.

YouTube: https://www.youtube.com/watch?v=HbAeTGoKG6k

Code: http://developer.android.com/shareables/devbytes/RequestDuringLayout.zip

Thursday, January 31, 2013

DevBytes: BitmapAllocation

This example shows how to speed up bitmap loading and reduce garbage collection by reusing existing bitmaps.

Note that the reused bitmap must be mutable and of the same size and configuration as the bitmap you load into it. Not sure if this is clear from the video, although it is documented in the API.

Code: http://developer.android.com/shareables/devbytes/BitmapAllocation.zip

Video: http://www.youtube.com/watch?v=rsQet4nBVi8