Older blog entries for lucasr (starting at number 248)

Performance Tips for Android’s ListView

I’ve been messing around with Android-based code for a few months now while hacking on Native Firefox for Android. I noticed that the performance tips for ListViews are a bit scattered in different sources. This post is an attempt to summarize the ones I found most useful.

I’m assuming you’re already familiar with ListViews and understand the framework around AdapterViews. I’ve added some Android source code pointers for the curious readers willing to understand things a bit deeper.

How it works. ListView is designed for scalability and performance. In practice, this essentially means:

  1. It tries to do as few view inflations as possible.
  2. It only paints and lays out children that are (or are about to become) visible on screencode.

The reason for 1 is simple: layout inflations are expensive operationscode. Although layout files are compiled into binary form for more efficient parsingcode, inflations still involve going through a tree of special XML blockscode and instantiating all respective views. ListView solves this problem by recyclingcode non-visible views—called “ScrapViews” in Android’s source code—as you pan around. This means that developers can simply update the contents of recycled viewscode instead of inflating the layout of every single row—more on that later.

In order to implement 2, ListView uses the view recycler to keep adding recycled views below or above the current viewport and moving active views to a recyclable pool as they move off-screencode while scrolling. This way ListView only needs to keep enough views in memory to fill its allocated space in the layout and some additional recyclable views—even when your adapter has hundreds of items. It will fill the space with rows in different ways—from top, from bottom, etc—depending on how the viewport changedcode. The image below visually summarizes what happens when you pan a ListView down.

With this framework in mind, let’s move on to the tips. As you’ve seen above, ListView dynamically inflates and recycles tons of views when scrolling so it’s key to make your adapter’s getView() as lightweight as possible. All tips resolve around making getView() faster in one way or another.

View recycling. Every time ListView needs to show a new row on screen, it will call the getView() method from its adapter. As you know, getView() takes three arguments arguments: the row position, a convertView, and the parent ViewGroup.

The convertView argument is essentially a “ScrapView” as described earlier. It will have a non-null value when ListView is asking you recycle the row layout. So, when convertView is not null, you should simply update its contents instead of inflating a new row layout. The getView() code in your adapter would look a bit like:

public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.your_layout, null);
    }

    TextView text = (TextView) convertView.findViewById(R.id.text);
    text.setText(&#34Position &#34 + position);

    return convertView;
}

View Holder pattern. Finding an inner view inside an inflated layout is among the most common operations in Android. This is usually done through a View method called findViewById(). This method will recursively go through the view tree looking for a child with a given IDcode. Using findViewById() on static UI layouts is totally fine but, as you’ve seen, ListView calls the adapter’s getView() very frequently when scrolling. findViewById() might perceivably hit scrolling performance in ListViews—especially if your row layout is non-trivial.

The View Holder pattern is about reducing the number of findViewById() calls in the adapter’s getView(). In practice, the View Holder is a lightweight inner class that holds direct references to all inner views from a row. You store it as a tag in the row’s view after inflating it. This way you’ll only have to use findViewById() when you first create the layout. Here’s the previous code sample with View Holder pattern applied:

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.your_layout, null);

        holder = new ViewHolder();
        holder.text = (TextView) convertView.findViewById(R.id.text);

        convertView.setTag(holder);
    } else {
        holder = convertView.getTag();
    }

    holder.text.setText("Position " + position);

    return convertView;
}

private static class ViewHolder {
    public TextView text;
}

Async loading. Very often Android apps show richer content in each ListView row such as images. Using drawable resources in your adapter’s getView() is usually fine as Android caches those internallycode. But you might want to show more dynamic content—coming from local disk or internet—such as thumbnails, profile pictures, etc. In that case, you probably don’t want to load them directly in your adapter’s getView() because, well, you should never ever block UI thread with IO. Doing so means that scrolling your ListView would look anything but smooth.

What you want to do is running all per-row IO or any heavy CPU-bound routine asynchronously in a separate thread. The trick here is to do that and still comply with ListView‘s recycling behaviour. For instance, if you run an AsyncTask to load a profile picture in the adapter’s getView(), the view you’re loading the image for might be recycled for another position before the AsyncTask finishes. So, you need a mechanism to know if the view hasn’t been recycled once you’re done with the async operation.

One simple way to achieve this is to attach some piece of information to the view that identifies which row is associated with it. Then you can check if the target row for the view is still the same when the async operation finishes. There are many ways of achieving this. Here is just a simplistic sketch of one way you could do it:

public View getView(int position, View convertView,
        ViewGroup parent) {
    ViewHolder holder;

    ...

    holder.position = position;
    new ThumbnailTask(position, holder).execute();

    return convertView;
}

private static class ThumbnailTask extends AsyncTask {
    private int mPosition;
    private ViewHolder mHolder;

    public ThumbnailTask(int position, ViewHolder holder) {
        mPosition = position;
        mHolder = holder;
    }

    @Override
    protected Cursor doInBackground(Void... arg0) {
        // Download bitmap here
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (mHolder.position == mPosition) {
            mHolder.thumbnail.setImageBitmap(bitmap);
        }
    }
}

private static class ViewHolder {
    public ImageView thumbnail;
    public int position;
}

Interaction awareness. Asynchronously loading heavier assets for each row is an important step to towards a performant ListView. But if you blindly start an asynchronous operation on every getView() call while scrolling, you’d be wasting a lot of resources as most of the results would be discarded due to rows being recycled very often.

We need to add interaction awareness to your ListView adapter so that it doesn’t trigger any asynchronous operation per row after, say, a fling gesture on the ListView—which means that the scrolling is so fast that it doesn’t make sense to even start any asynchronous operation. Once scrolling stops, or is about to stop, is when you want to start actually showing the heavy content for each row.

I won’t post a code sample for this—as it involves too much code to post here—but the classic Shelves app by Roman Guy has a pretty good example. It basically triggers the async book cover loading once the GridView stops scrolling among other things. You can also balance interaction awareness with an in-memory cache so that you show cached content even while scrolling. You got the idea.

That’s all! I strongly recommend watching Roman Guy and Adam Powell’s talk about ListView as it covers a lot of the stuff I wrote about here. There’s nothing new about the tips in this post but I thought it would be useful to document them all in one place. Hopefully, it will be a useful reference for hackers getting started on Android development.

Syndicated 2012-04-05 11:24:21 from lucasr.org

Remote Debugging in Firefox Mobile

Debugging a page in Firefox Mobile

As you probably know by now, the DevTools team got together here in London last week. I attended their work week with the specific mission of getting remote debugging to work on Firefox Mobile (a.k.a Fennec).

The result? I wrote a couple of patches that allow you to debug JavaScript code from web pages running on Firefox Mobile. You can add breakpoints, step through your JS code, track the call stack and variable values from the experimental script debugger in Firefox’s Nightly build on desktop.

The script debugger uses the remote debugging protocol to send commands to Fennec via network. You have to connect your Android device to your computer via USB and map a localhost port using the follow adb command:

adb forward tcp:6000 tcp:6000

This will map port 6000 on your computer with the same TCP port on your mobile device. There’s no UI in the script debugger to connect to a remote Firefox instance yet but the DevTools team already have a patch series adding that. My patches simply implement the necessary actors that expose all browser tabs to the script debugger.

Remote debugging is especially important for mobile web developers. They need a way to easily tweak pages on the mobile device and see the results instantly. Right now, the remote debugging protocol only allows you to debug JavaScript code but  the long-term goal is to allow web developers to do much more: injecting code, inspecting DOM nodes, tweaking CSS rules, etc.

As you can see, there’s a lot of exciting work in progress here and many patches about to land in our repositories very soon. Stay tuned!

Syndicated 2012-03-28 15:43:27 from lucasr.org

My first 238 days at Mozilla

There’s nothing special about today’s date but I feel it’s a good time to write a bit about my experience at Mozilla so far.

First days. Joining Mozilla was, at least in the first few weeks, a rather scary experience. Mostly because it was an unknown territory—both socially and technically—and I had a lot of catching up to do. The amount of information you have to assimilate in order to understand how things are done is a bit overwhelming. But here I am, I survived! And still catching up.

Remote. One of the main concerns I had when I joined Mozilla was the working-from-home part. I’ve done it before but not for so long. It turned out to be a good experience and enjoyed it in many ways. But I still missed meeting workmates in person and having a more clearly separate environment for work. So, I’m glad that the awesome London office is now open!

Challenges. I  joined Mozilla in a very interesting moment. The company is growing a lot (we’re hiring) and has gone and is still going through many changes: new release pace, native UI for Firefox on Android, Boot to Gecko, Identity, Open Web Apps, and much more. New focus, projects, and products but the mission is still the same.

Hacker-friendliness. Mozilla is a very friendly environment for hackers: meritocratic, pragmatic, and virtually bullshit-free. Feels good. You’re pretty much free to decide what to do next with very simple guidance as to what has higher priority at point in the development process.

Passion. Mozilla’s mission is taken very seriously. You see that reflected in every small and big decision inside the organization. Being a non-profit organization with such a worthy mission is very liberating because you can express your passion with no excuses. Mozillians are very passionate people.

Quick stats. I joined Mozilla 238 days ago. Since then, as part of my work at the company, I pushed 204 changesets, changed ~7,395 lines of code, fixed 106 bugs, gave 2 talks, travelled to 4 countries, and met a huge number of smart people.

Syndicated 2012-03-13 11:59:40 from lucasr.org

FOSDEM 2012

Mobillians by Brian King (CC-BY-NC)

This year’s FOSDEM was a special one for me. It was the first time I attended it as a Mozillian! I had already met quite a few European community members at MozCamp Europe last year but this FOSDEM was a great opportunity to meet even more Mozillians face-to-face. I stayed at the Mozilla DevRoom most of the conference but also spent some time catching up with my fellow GNOME hackers.

Chris and I gave a “State of Firefox Mobile” talk on Sunday. I usually don’t share my slides because they tend to be too short in content to be useful. However, we wrote some speaker notes that give enough information and context on what we talked about. So, here’s the deck alternating between slides and speaker notes—I wish Speaker Deck had proper support for speaker notes…

All in all, I had a great time at FOSDEM this year! PS: The weather during the conference was quite special too—in a painful way!

Syndicated 2012-02-09 16:09:09 from lucasr.org

Native UI for Firefox on Android

It’s been a month since Johnathan publicly announced the native UI for Firefox on Android. So it’s probably a good time to give everyone a quick status update. In case you haven’t heard about it yet, we are re-implementing Fennec’s UI using Android’s native platform to be able to deliver a much better performance and UX to our users on Android devices.

In terms of architecture, one of the key points of the native UI is to move Gecko and XUL out of Firefox’s startup path on Android. This way, the UI can start up and respond to user interaction immediately while Gecko and XUL load and run on a separate thread. The communication between Gecko and the native UI then happens through a simple message system. This means we’re replacing Electrolysis with a lighter architecture that brings similar benefits. For the curious, Mark Finkle wrote an architecture overview with more details.

We’re landing the new code on a separate repository called “birch” which will eventually be merged in mozilla-central. Large parts of the primary browser UI have already been implemented—AwesomeBar, tabs, bookmarking, notification popups, addons manager, preferences, context menus, and more. We also have a new panning/zooming implementation that is extremely fast and smooth. The design team is bringing a new phone UI for Firefox that is both beautiful and simpler. The new design is part of a wider effort to streamline the Firefox UX on all platforms, desktop and mobile.

This is all very exciting but there’s still a lot to do to make it all feature-complete, stable, and ready for users. If you want to help us with feedback and testing, install the native UI’s nightly build on your Android phone. Don’t have an Android phone? Mozilla can give you one! Have a look at our Test Drivers program page for more information.

It’s key to Mozilla’s mission to have a strong presence on the mobile web space. We’re working hard to make Firefox the most exciting mobile browser on Android. Development is moving insanely fast and I can’t wait to see the new UI delivered to our users next year!

Syndicated 2011-11-15 14:07:54 from lucasr.org

Get Involved in Firefox Mobile

I’ve volunteered to be a community steward for the Mobile team as part of the Contributor Stewards program that has been recently created in Mozilla. My role as a community steward is to find ways to get more people involved in Firefox Mobile.

As a first step, I thought it would be a good idea to create a Get Involved page for the Mobile team. This page is meant to have only the minimal steps to start contributing to different areas of the project—it shouldn’t feel overwhelming. For now, it only has content for hacking and testing but it will include other areas soon.

I have also compiled a list of bugs that are good for first-time contributors and assigned mentors to each of them. The mentors and other team members will assist you with any missing information and useful source code links.

If you’re still unsure where to start after reading the Get Involved page, we’re always on IRC to answer any questions you might have. Firefox Mobile is a key part of Mozilla’s future and is definitely an exciting project to be part of. Join us!

Syndicated 2011-10-10 11:15:07 from lucasr.org

HTML5 Form Validation in Firefox Mobile

My patches to add HTML5 form validation support to Firefox Mobile have landed in trunk yesterday. This feature has been available on desktop since Firefox 4 but it wasn’t implemented in Firefox Mobile until now.

In case you haven’t heard about it, HTML5 supports automatic input validation. This means that your browser can take care of validating form fields for you—no need to write custom JavaScript code to check for required fields or validate common types of input such as numbers, emails, URLs, etc.

So, how does HTML5 form validation look in Firefox Mobile? Very similar to Firefox on desktop. If you submit a form that contains any invalid data—an invalid email address, a required field that was not filled in, and so on—the form will not be submitted, all invalid fields will be marked with a subtle red border, and the first invalid element will be automatically focused showing its respective validation message (see image above).

As far as I know, the only mobile browsers that support HTML5 form validation right now are Firefox and Opera. You can try this feature on our mobile nightly build. As usual, general feedback, bug reports, and patches are welcome!

Syndicated 2011-09-20 14:38:18 from lucasr.org

Firefox for Tablets on Nightly

Firefox for Tablets

We, Firefox Mobile front-enders, have been working hard for the last few weeks to get the new Firefox UI for tablets in place for general testing. It has now reached a functional state that is good enough for getting some early feedback. So, how can you help us?

First of all, you can simply install Fennec’s nightly build on your Android tablet and give us some thoughtful feedback on the UI. File bugs for the missing bits from the planned design, report interaction problems, let us know about broken bits, etc.

Secondly, if you want to contribute code, have a look at our current list of tablet-related bugs—see the dependent bugs—and let us know what bugs you want to work on. Setting up a Fennec development environment is fairly simple, you can find instructions in the wiki.  Feel free to ask for help either on IRC (#mobile at irc.mozilla.org) or on the specific bug reports. Just ping mfinkle, mbrubeck, wesj, sriram, or me.

Keep in mind that this is very early stage work. There are lots of rough edges and design is continuously evolving. In case you missed it, Ian Barlow, from our Mobile design team, has blogged about the tablet UI design a couple of weeks ago—definitely worth reading. This is all looking very promising and we can’t wait to get it out to users once it’s ready!

Syndicated 2011-09-13 04:57:29 from lucasr.org

Hello Mozilla!

This is my first post aggregated on both Planet Mozilla and Planet Mozilla Mobile. I guess it’s a good time to introduce myself to the Mozilla community. I joined Mozilla about a month ago to work on Firefox  Mobile. I’ll be mostly focusing on UI-related bits and pieces of Fennec as part of the front-end group—which is in fact what I’m most passionate about.

Before Mozilla, I worked for three years at litl—a Boston-based startup—where I hacked on the cloud-based OS that powers the webbook. The litl OS is almost entirely written in JavaScript and it was while working on it that I really got hooked into the language. Before litl, I was part of Maemo’s UI framework team at Nokia where I worked throughout the entire development cycle of  the N810 internet tablet.

I’m also a long time GNOME contributor. I’ve done all sorts of things in the project such as being a member of GNOME Foundation’s Board of Directors, being part of GNOME’s release team, and maintaining a few official modules. I don’t hold any official positions in the project anymore but I’m still working on a cool spare-time project based on GNOME platform.

My first month at Mozilla has been great overall. To be honest, I felt a bit overwhelmed in the first couple of weeks. It’s a quite humbling experience to join such a large community full of extremely talented and passionate contributors. It’s a whole new world to me and I’m learning quite a bit everyday—which is the very reason I joined Mozilla anyway. I hope to be blogging soon about the latest news on Fennec development. For instance, there’s some really exciting work being done on the tablet UI for Fennec now! Stay tuned!

Syndicated 2011-08-23 00:11:00 from lucasr.org

Desktop Summit 2011

I could not attend GUADEC last year for a very good reason. So I’m really happy that I’ll be able to go to Berlin for the second Desktop Summit this year! This is my first GNOME conference without holding any official roles in the project since 2007. This means I’ll hopefully have more time to just hang out with my fellow hackers. I’ll arrive on the 6th of August and leave on the 10th.

I guess it’s a good time to announce that I’ll be giving two talks this year. The first one is about GNOME development in JavaScript with Gjs. It will be on the 7th of August (Sunday) at 9h40 in the morning. Hopefully, a few attendees will wake up earlier for this talk!

The second talk is about The Board, one of my current pet projects, which you have probably heard about. I’ll demonstrate the current features and talk about the future plans for the app. I hope to finish some awesome new features in time for the conference. Let’s see. This talk will be on the 8th of August (Monday) at 14h40.

This is also my first open source conference as a Mozillian. So, if you want to know a bit more about Firefox Mobile, just find me at the conference venue for a chat. All in all, I’m very excited about the conference this year! See you all there!

Syndicated 2011-08-02 05:17:01 from lucasr.org

239 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!