Remember to Breathe

Hey! I'm a Montreal-based software craftsman. I am passionate about anything related to software development, agile and collaborative work environments, mobile platforms, user experience design and human interactions.

Small team, multiple projects: an Agile approach to planning

Context: you have a small team of 5 people, evolving in a highly dynamic environment with small projects (2-4 weeks, sometimes less, sometimes more) coming all over the place for the team to realize. This is a very usual pattern observed in agencies, or smaller teams dedicated to professional services (services to clients).

How do you approach people planning (a.k.a "resource planning", although I won't hide my aversion for the term "resource" when referring to a person) in that kind of context? The inate approach to this problem seems to start assigning individual people from the team to different projects in the pipeline, trying to optimize utilization of people on an individual basis:

Slide1

On the diagram above, we have a fictive situation of 4 projects in the pipeline. The first 3 projects (A, B and C) are either already started or start at the beginning of week 1. The 4th project (D) starts on the 4th week.

Some observations:

  • Because we are assigning people as mere resources, suboptimal situations occur, such as people having nothing to do at specific times, for short period of times
  • Some people are clearly leads on some projects, while others are lugged between projects
  • Some people never participate in some projects, limiting knowledge to the few who worked on these projects
  • This is a quite simple situation, and it already looks a nightmare to manage. You quickly see the need for a new "traffic controller" job to manage and optimize people allocation. In a larger organization with more people, this quickly becomes a full-time job. 
  • For project D, which starts on the fourth week, only 1 person is assigned. You'll need to be very careful for the rest of the project to plan for knowledge transfer: this person could become sick any day, leaving you in the dust.
  • From my experience, this kind of planning encourages individuality, leaving you not with a team, but with a bunch of individuals working separately. These individuals tend to not be aware or even sensible to what others are doing and their problems. They will also have a tendency to stop being proactive and wait for job to be assigned to them

Far from ideal and not very agile! Unfortunately, it is a common situation.

I recently came up with a more systemic approach to the problem. Instead of assigning people to projects on an individual basis, why not see all projects as being the work to be done and the team as being the system which realizes the work to be done?

Start seeing the group representing the team as a whole, capable of a certain capacity of work. Then, split this capacity in value streams. When planning for projects, assign projects to these value streams instead of the individuals.

Slide2

Before any project starts, make sure you have an estimated and prioritized backlog of features. At the beginning of each sprint, pull some work from these backlogs according to the planned projects in each value stream:

Slide3

You may need a project to be put on the fast lane for any reason (the project is late, or there's no other project in the pipeline). Then, simply assign more value streams to this project. This will allow more work for this project to be selected and included in the sprint:

Slide4

When a sprint starts, leave the team alone. If you are a manager, trust the team to organize around the work to be done. Coach them to become more efficient in the way they work together. Always treat the team as a whole. Do not try to identify owners for projects yourself: they'll probably do it naturally. Encourage them to work in pairs for more complex problems. Make sure they take time to inspect how they work, then that they adapt.

When you start treating people as teams, some things start to happen naturally:

  • People start to care and worry for their team partners
  • Overall productivity increases
  • One person leaving (holidays, sickness) does not bring a project down anymore
  • People start actually enjoying their job a lot more

An important factor to the success of the approach is to only allow a number of value streams smaller than the number of individuals in the team. I would say a maximum of:

floor(team size / 2) + 1

Examples:

  • Team of 3: 2 value streams
  • Team of 6: 4 value streams
  • Team of 7: 4 value streams

This has multiple effects:

  • Since there is less projects than people, this fosters collaboration, thus enabling natural knowledge transfer within the team.
  • It effectively creates a real team: a group of individuals working on the same goals together as a whole.
  • Suboptimal situations, like people having nothing to do, are removed.

This approach also has a potential for scaling to much more than a single team. If the number of projects is too high for a single team, create multiple teams, assign projects to teams, then plan these projects based on their value stream. 

I've started this way of working about a month ago with the team I am leading, and they simply love it! Planning is also a lot simpler, allowing me (and others) to concentrate on other matters.

One thing that is clear is that the team bonding and productivity benefits do not happen overnight. As the Virginia Satir Change Model states, one must accept reduced or steep variations in productivity on the first few weeks following the change, especially if the so-called "team" has been working individually for a while before the change.

If you try this approach (or have already tried it, or a variation of it), please leave some feedback! I'm very interested in knowing how this works out for you.

Easier builders in Java

Anyone that has used the builder pattern for building simple Pojo-style Java classes is probably aware that writing these builder classes quickly becomes quite unpleasant and definitely not fun. You quickly realize that your builders often mimic the structure of your Pojo’s setters, finding yourself almost duplicating half of Pojo’s code for the sake of the pattern.

Following a recent post from Eric Mignot and a few prior reflections I had on optimizing the process of writing these builders, I have come up with a solution that will, I hope, greatly simplify trivial cases (that is, building simple pojos) and, eventually, as the tool evolves, allow for slightly more complex cases to be covered.

So, let me introduce you to the Fluent Interface Proxy Builder. The tool only requires the developer to write the builder interface, not the implementation. The actual implementation is assured by a dynamic proxy that will intercept method calls on your interface, then set the corresponding properties on your Pojo object.

Quick example. Suppose you have a simple Java Pojo:

public class Person {
    private String name;
    private int age;
    private Person partner;
    private List<Person> friends;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setPartner(Person partner) {
        this.partner = partner;
    }

    public void setFriends(List<Person> friends) {
        this.friends = friends;
    }

    ... getters omitted for brevity ...
}

To get a builder for this bean, write a builder interface following a few naming conventions:

public interface PersonBuilder extends Builder<Person> {
    PersonBuilder withName(String name);
    PersonBuilder withAge(int age);
    PersonBuilder withPartner(PersonBuilder partner);
    PersonBuilder havingFriends(PersonBuilder... friends);
    Person build();
}

Note: The super interface “Builder” used here is provided by the framework. This interface has a “T build()” method. I included the “build” method in the example above for the sake of clarity. You may also use your own super interface if using the one provided by the framework proves to be a problem.

To use your builder, first create an instance:

PersonBuilder builder = ReflectionBuilder
                           .implementationFor(PersonBuilder.class)
                           .create();

Then you may use this dynamic builder normally through your interface:

Person person = aPerson()
                .withName("John Doe")
                .withAge(44)
                .withPartner( aPerson().withName("Diane Doe") )
                .havingFriends(
                    aPerson().withName("Smitty Smith"),
                    aPerson().withName("Joe Anderson")
                ).build();

Have a look at the Github project page for all the details and instructions on how to use it in your own project. You may use this freely by the terms of the MIT license.

Get it here!


It is also worth mentioning other alternatives that exist and deserve consideration:

The slight annoyance I see with the latter two (code-generating approaches) is that since the code is generated, it will overwrite any naming customization you’d make after the initial generation. It also makes maintenance of the builder harder over time, as the objects being built evolve. From my point of view, adding a method on an interface is quicker and more natural than re-generating the builders (and possibly overwriting custom names).

Delivering software more efficiently

Organizations today are always looking for ways to improve how they build software. To stay competitive on fast-paced markets, they have to optimize the delivery pipeline to bring features from ideation to market more rapidly. Many rightfully seek solutions by adopting agile or lean practices. To be fully effective, these methodologies also need to be supported by rigorous engineering practices such as those brought forward by Extreme Programming. Executed correctly, these are all very good ways of optimizing the way you and your team build your software.

Delivery = PRODUCTION

Unfortunately, building the software itself is just a part of the big picture. Your sparking new shiny software is not worth anything until it’s out in the wild. To get the most out of any software project investment, organizations need to make sure their software is in the user’s hands as soon and as frequently as possible and with minimal overhead. This is what I mean here by “more efficient delivery”.

Delivering good software is demanding. Delivering good software fast is quite a challenge. What I present below are techniques and practices that, when adopted, will have a direct impact on the time required for a feature (or your software altogether!) to go from idea to your users. These practices will especially be helpful to agile and lean teams, who strive to build software in small, “potentially shippable” increments. Used correctly and alongside recognized engineering practices, they can help transform potentially shippable to definitely shippable.

Be always ready for deployment

One of the first mind shift teams must accomplish is to make sure their code is always ready for deployment. This requires the rigorous use of unit testing, use of slightly different software design paradigms, as well as working differently with source control.

Unit tests

Make sure your automated test coverage is top notch. Don’t necessarily aim for 100% figures, but make sure you’re confident that what’s covered is covered intelligently and correctly. Unit tests have become almost ubiquitous, but it’s unfortunate to see that people still write software without a good, pertinent test suite. Without a confidently complete test suite, your deployments might become much more embarrassing (and might be accompanied by much more praying, voodoo incantations and cute small animal sacrifices).

Feature toggles instead of feature branches

Design new, in-development features so that they can be toggled instead of isolating them in different source control branches. This allows for the new code to be continuously integrated instead of falling farther and farther behind the main line, resulting in painful and long merges. This practice also facilitates heavy and merciless use of refactoring, which feature branching often discourages.

Staged commits

Stage code commits in a special branch where tests are systematically (and automatically!) run to proof each commit, then (also automatically) promoted to the trunk/master/head/main if all tests pass. This way your main line stays as stable as possible. Modern VCSs, like Git or Mercurial, allow for much easier setup of that kind.

Minimize the feedback loop

Problems found early cost less to fix. For that reason, one must strive at making sure potential problems can be identified as early as possible. Make your unit tests run automatically upon each source control commit. Automate regular runs of your functional / performance tests suites. When tests fail, make sure the team is clearly (and again, automatically) notified so that they can switch their attention at fixing the error: they are not ready for deployment!

Automate everything

Deployment to any environment should be done by the push of a single button. Point. Final. Script everything. Allow nothing to be executed by a human. Where there are humans, there are errors. By having everything automated, you not only minimize possibilities of errors during deployment, you also make them quicker.

Use a tool for managing your database migrations. Almost all modern development platforms offer these tools. Research for the right one for your need. Database migrations can be generated by the tool and can be integrated in your deployment scripts so that they are applied automatically to the target environment. Also plan for the worse: your tool should allow for rollbacks (reverse migration) scripts as well.

To fully automate deployments, infrastructure configuration also needs to be taken care of. Use a configuration management tool for this (such as Puppet, Chef or CFEngine). Using a tool such as these, your servers can be provisioned and maintained automatically by the use of configuration “recipes”. Since these recipes are stored as text, they can be versioned and be an integral part of your code base, and evolve alongside your software.

Use a deployment pipeline

Stage your builds to at least a test environment where you can proof deployments. When a deployment is a success, it can be promoted to the next step in the deployment pipeline. Make unit and functional tests phases as integral parts of your deployment pipeline so that the entire deployment pipeline gets stuck if tests fail.

A deployment pipeline

Make sure your application is packaged only once for a given version and that this same package is deployed unchanged between the different environments. Store these packages in a central repository from which the deployment scripts can pull them upon deployment. This requires a clear separation between environment-specific configuration and code. Use your configuration management system to handle environment-specific configurations.

Monitor

When deployments become less of a pain and starts to become a non-event, you will be rapidly starting to think about deploying your code more often. Having an automated “health check” and smoke test suites ready will quickly become mandatory in order to make sure everything happened as planned to each environment. If you are going to use a deployment pipeline, run these tests after each deployment to a given environment and do not allow the pipeline to continue if one of these fail.

Form “delivery” teams

Reaching such a high level of build and deployment automation requires an extremely close collaboration between infrastructure and development teams. Make infrastructure part of the development team, instead of handing off obscure requirements to them late in the project. If possible (this is highly desired!), dedicate an infrastructure team member to your project. Not only will they have insights and knowledge on both your software and the infrastructure constraints, but they will also be able to work with the rest of the organization to help remove potential impediments to improving the delivery pipeline.

Believe!

Although these practices require a substantial amount of effort and collaboration to happen, the benefits teams get from adopting them quickly far outweigh the costs. Moreover, every single tip mentioned above can be implemented using solid and readily accessible open-source tools on most prevalent platforms.

Some also require an organizational mindset shift that transcends the delivery team’s boundaries. Corporate security policies, limited or restricted accesses, lack of trust between teams, teams jealously keeping control of their resources, communication barriers are all possible hurdles to improving the delivery efficiency of your team. Address them one at a time and continue to believe!

It’s never really done

Do not necessarily try to get the whole thing at first. Make a list of the improvement items that need to be addressed by your team, prioritize according to value and go step-by-step. This is a never ending process: there is always something to improve in your delivery pipeline. Regularly reflect on what more can be done to make your deliveries easier and more frequent.

Start this process as early as possible in your project so that you get the most of the additional value provided by these practices. Starting early has the nice side-effect of making teams think of automation every time they need to make a decision about their general software architecture. How will this impact our delivery pipeline? Can we automate this and that? If not, what could allow us to do so?

And hey, why are you still reading this? Go Deliver Something!

Plans for building a 8x12 shed (steps pictures included)

Just completed today my shed building project for the backyard at our new house! This was an awesome project and I had a great time with my father and brother. 

I thought I'd share some pictures and the rough plans for the project. I spent a great deal of time on the Web and into my local hardware store to find information related to the different steps of building the shed... Although I won't go into much details in this post, I hope the picture attached will help others get cues on how to do this and that. 

(download)

The project took my father, my brother and me about 6 full days to complete (we're not experts!) but the end result is awesome. Some others facts:

  • I made the plans with Google SketchUp
  • Floor is held on 6 concrete blocks
  • Floor is built with 2x6s, spaced at 12 inches on-center
  • Plywood sheets were used to cover floor
  • Walls and roof are made up of 2x4s lumber, spaced 16 inches on-center
  • Aspenite sheets were used for covering walls (1/2 inch) and roof (5/8 inch)
  • Tar paper and fiberglass BP shingles were used for roof finition, tacked with 1 inch roofing nails
  • Window and door were pre-made (slide-ins)
  • Vinyl siding and soffits were used, as well as aluminium fascias. Aluminium was tacked into place using white aluminium nails (non corrosive)
  • An electric cable runs underground to the house and into the main panel to bring light and electricity into the shed

(download)

Some random tips and afterthoughts:

  • Roof trusts can be made up-front (this is what we did), as long as dimensions are carefully thought out!
  • Use a pressure nailing gun with glued nails for carpentry works, this is fantastic and extremely fast
  • Use a pressure tacking gun for fixing aluminium and soffits
  • Building the shed with dimensions (width, depth and height) that are a multiple of 4 is convenient since most sheets are 4'x8'
  • Use aluminium trimming cisors to cut vinyl sheets. A handsaw works also but requires some help to hold the sheets while cutting.
  • We should have rented an aluminium folding machine for fascias: folding the fascias for sliding under the roof shingles was a real big pain.
  • We had to add some small pieces of lumber (3/4 x 3/4 inch) under the roof perimeter to allow for the aluminium fascia to be tacked. We should have used 1x4s on the extremities instead of 2x4s: this would have allowed the pre-shaped fascias fittings to correctly slide in and be tacked.
  • Finition is extremely time consuming it took 3.5 days to fully complete the structure and the roofing, then almost another 3 days to fully complete the shed (vinyl siding, soffits and fascias)

Hope this helps! If any question, please ask in the comments below!

Maven custom properties precedence

If you’ve worked with Maven before, you are probably aware that it allows you to define custom properties that can then be used throughout your build as placeholders (for value re-use or configuration purposes) or even as a mean of configuring your final build resources using filters. These come very handy for defining environment-specific configurations.

These custom properties can be defined at multiple locations. But what happens when you define (or re-define) the same property in multiple locations? Which location will have precedence on others? Amazingly, even if Maven is very popular in the Java ecosystem, I could not find any useful reference on this.

After research and thorough testing, I’ve come up with this order of precedence which Maven uses when resolving custom properties:

  1. System properties: set with -Dxyz=value on the command line.
  2. From currently active profile(s): settings.xml in user home directory first, then profiles.xml in project root directory, then in profiles defined in your pom.xml. If many profiles are active, and a property is defined in more than one of those, the order of precedence is based on the last profile in which this property is defined, in alphabetical order of profile name.
  3. In the properties section of your pom.xml.
  4. Lastly, in properties defined in filters. If a property is defined in multiple filters, then the last one (in order of appearance in your filters section) has precedence over the others.

Good to know!! This came handy recently for me so I share it here, hoping it will help someone else!

The leader and "his team"

People seem to have a hard time treating a group of individuals working on a common goal as a Team. I’ve observed that many people will naturally expect commitment and liability from leaders, even unofficially appointed leaders, or natural leaders, instead of teams.

But why is that so? Why are people seeing hierarchy in leadership?

The answer might come from us being deeply entangled in our Fayolism roots. For most of the 19th and 20th centuries, management styles have always focused on creating a hierarchy of command and control. This has worked great in traditional, repetitive and manual work environments (which were prevalent up to a few decades ago), and this management style still sneaks in our daily lives as software professionals. Even with the best intentions to get away from these management styles, most people still experience a few behaviours reminiscent of these roots. The leader leads the team, thus is responsible for “his team”. It looks like it is comforting to know that a single neck can be wrung if something happens.

It won’t be a surprise to anyone that writing software is certainly not repetitive (most of it at least, if it is for you, you should definitely consider giving your current job a good thought). A more collaborative, egalitarian work environment is often more appropriate, and has proven much healthier in many situations.

To help cultivate a more collaborative environment around me, I’ve come up with a few rules of thumbs that I try to honour continually as a team-focused leader:

  • Never, never commit on work on behalf of the team
  • Systematically use “My team and I” or “We” formulations when communicating those team commitments or decisions
  • Always estimate and plan in teams

Creating a team-focused mindset in daily communications with the different stakeholders will slowly but surely help in removing this wringable-leader delusion.

Introducing Less CSS plug-in for Grails

Less CSS is a CSS pre-processor that adds support for many advanced (and lifesaver) features to normal CSS, such as variables, mixins, nested definitions, etc, etc. You basically write .less files that have a syntax similar to CSS itself (with the added functionalities), and these files get compiled as CSS after on. I’ve been wanting to use it for a long time but support for Less in the Groovy/Java ecosystem is scarce. It has originally been developed by the Rails folks. The latest version of Less however has been re-written as pure Javascript. This opens up a full range of possibilities for integrating Less everywhere.

Grails developers, wait no more! I’ve just completed a first draft of an idea that I had this past summer after digging a little bit into the less.js implementation of Less, and this has finally taken the form of a Grails Less plug-in. The basic idea is to offer real-time compilation of Less files when developing your application, and statically compile your Less files as standard CSS when bundling your application for deployment (WAR).

NOTE: Some previous attempt had been made to integrate Less with Grails, but the solution required to pull out the full JRuby stack in order to work correctly. Now that Less has a javascript compiler, we are able to do exactly the same thing but with only Mozilla Rhino as a dependency. Rhino is a library to execute Javascript code directly in the JVM.

By using this new plug-in, you can now use Less transparently in your Grails projects. You first create a .less file in your web-app/css directory, then refer to it (without the file extension) in the HEAD section of your site using the available taglibs:

<less:stylesheet name="your_stylesheet" />
<less:stylesheet name="your_other_stylesheet" />
<less:scripts />

You may add any number of Less files to your page this way.

When in development mode, .less files will be parsed automatically and directly in the browser. Your changes will be reflected after each page reload. When building your project (using the war command), all your .less files will be compiled to standard CSS files, and the taglib will correctly refer to the static CSS files at runtime.

The plug-in should also play nicely with the ui-performance plug-in: as long as the ui-performance plug-in executes after lesscss, generated CSS files can be minified and bundled by the plug-in.

See the Github page for all the details on installing and using the plug-in.

Recipe: Using Hibernate event-based validation with custom JSR-303 validators and Spring autowired injection

JSR-303 (Bean Validation) is nice.

It allows to define validation rules directly on beans using simple annotations. Most cases are covered by the base annotations provided by the standard, and it even includes a way to develop custom validators that can be plugged-in as you see fit.

Once your beans are annotated, you can manually trigger validation as simply as:

Set<ConstraintViolation> constraintViolations = validator.validate(annotatedBeanInstance);

The latest and greatest Spring 3 now supports JSR-303 validation out of the box. One only needs this line in Spring configuration XML to enable the integration:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

Even better, custom validators developed in such a Spring environment can even beneficiate from Spring’s @Autowired injection, freebie!

Hibernate itself also offers an integration with JSR-303 through Hibernate events. Enabling the integration with Hibernate allows validation rules to be executed on those events for your model beans:

  1. pre-insert
  2. pre-update
  3. pre-delete

Will it blend?

At first sight, all of this looks very nice. You get standardized validation directly on your beans and invoking validation is a one-liner. But what happens if you mix all of this together?

In my current project, we wanted to build a custom validator that would check if an e-mail address already existed in the database before saving any instance of our Contact entity using Hibernate. This validator needed a DAO to be injected in order to check for the existence of the e-mail address in the database. To our surprise, what we thought would be a breeze was more of a gale. Spring’s injection did not work at all when our bean was validated in the context of Hibernate’s event-based validation (in our case, the pre-insert event).

At first glance, we did all that was required both sides:

  1. We enabled Spring 3 integration with JSR-303, as per documentation
  2. We enabled Hibernate event-based integration with JSR-303, as per documentation

After some digging, we found out that Hibernate did not use our Spring LocalValidatorFactoryBean, but rather used its own ValidatorFactory. It became quite obvious that it all did not blend that much.

Fortunately, a solution exists, and at this moment does not seem documented. Hence this page!

I’ve created a quick Maven project that I’ve published on GitHub that showcases a full working solution. Refer to the README on GitHub for details.

To summarize the solution, two things are required, in addition to the standard integration steps for both frameworks (Hibernate and Spring).

Spring XML configuration

<!-- The LocalValidatorFactoryBean is able to instantiate custom validators and inject autowired dependencies. -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

<!--
   This is the key to link Spring's injection to Hibernate event-based validation.
   Notice the first constructor argument, this is our Spring ValidatorFactory instance.
  -->
<bean id="beanValidationEventListener" class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener">
    <constructor-arg ref="validator"/>
    <constructor-arg ref="hibernateProperties"/>
</bean>

<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="annotatedClasses">
        <list>
            <value>com.github.davidmarquis.model.User</value>
        </list>
    </property>
    <property name="hibernateProperties" ref="hibernateProperties"/>

    <!--
      A reference to our custom BeanValidationEventListener instance is pushed for all events.
      This can of course be customized if you only need a specific event to trigger validations.
    -->
    <property name="eventListeners">
        <map>
            <entry key="pre-update" value-ref="beanValidationEventListener"/>
            <entry key="pre-insert" value-ref="beanValidationEventListener"/>
            <entry key="pre-delete" value-ref="beanValidationEventListener"/>
        </map>
    </property>
</bean>

The key part here is to force Hibernate to use a custom BeanValidationEventListener that will use Spring’s LocalValidatorFactoryBean instead of creating its own. This is the missing piece of the puzzle.

hibernate.properties

javax.persistence.validation.mode=none

In some cases, we found out that Hibernate still adds its own BeanValidationEventListener in addition to the one we define. Obviously, the second event listener (the one created by Hibernate) is not configured correctly so all validations based on injected beans fail with nice little NullPointerException. Specifying this property disables Hibernate automatic configuration process, and the duplicate event listeners all goes away.

That’s it! Hope this will be of some help!

IntelliJ IDEA 10 will be awesome!

Jetbrains just published a page detailing the new features that will be included in the upcoming release of their flagship product IntelliJ IDEA 10.

Among the new stuff, I noted those few very interesting improvements:

  • Android development tools now included in the free community version (nice move Jetbrains!)
  • Maven dependencies in Android projects
  • Custom integration of GitHub as VCS
  • Grails: Autocompletion of controller and action names in GSPs
  • Zen coding support for HTML and CSS
  • Improved Python and Ruby support
  • Support for Django projects (oh yes!)

Jetbrains are really positioning themselves to become THE IDE of choice for many software developers. With their excellent support for many languages and frameworks, IntelliJ is becoming the one-stop shop for software developers. As software developers, learning a new platform or language often requires a lot of involvement (new concepts, new tools, new IDEs, etc.) Having such a wide support in one IDE eases the learning curve of new tools or technologies, and encourages us to explore!

Thanks Jetbrains! You literally make our job more enjoyable!

Android ListView with images using Droid-Fu WebImageView and a custom list adapter

Droid-Fu library has a nice little widget called WebImageView which allows the display of an image downloaded from the Web, along with a nice little loading animation display. The widget cannot be simpler to use:

WebImageView imageView = ...
imageView.setImageUrl("http://...");
imageView.loadImage();

That’s it! The widget will automatically handle the display of an indeterminate progress animation, and display the image as soon as it is downloaded. Moreover: downloaded images are cached. Awesome!

There is little to no mention about it, but WebImageViews can also be used in ListViews in order to display multiple dynamically-loaded images coming from the Web. This article highlights the steps required to do so with an example application that loads a randomly chosen Picasa album feed and displays the thumbnail pictures of every image in the album.

Application screenshot

First, we need to create a layout for the list items:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:gravity="center"
              android:background="#FFF"
              android:padding="5dip">

    <com.github.droidfu.widgets.WebImageView android:id="@+id/webimage"
                                             android:layout_width="75dip"
                                             android:layout_height="75dip"
                                             android:background="#CCC"/>

    <TextView android:id="@+id/title"
              android:textStyle="bold"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:layout_gravity="left|center"/>

</LinearLayout>

Nothing fancy here, a WebImageView will be displayed on the left side of every item in the list. Next step would be to create a ListView in your main application layout. I’ll omit an example of this for the sake of brevity.

Let’s create an Adapter for our custom list and list items:

public class PhotoEntriesListAdapter extends BaseAdapter {

   List photos = Collections.emptyList();
   Context ctx;

   public PhotoEntriesListAdapter(Context ctx) {
       this.ctx = ctx;
   }

   public void setPhotos(List photos) {
       this.photos = photos;
       if (this.photos == null) {
           this.photos = Collections.emptyList();
       }
   }

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

   public Object getItem(int i) {
       return photos.get(i);
   }

   public long getItemId(int i) {
       Message item = (Message) getItem(i);
       return item.getLink().hashCode();
   }

   public View getView(int position, View convertedView, ViewGroup viewGroup) {

       Message entry = (Message) getItem(position);

       if (convertedView == null) {
           convertedView = LayoutInflater.from(ctx).inflate(R.layout.list_item, null);
       }

       WebImageView imageView = (WebImageView) convertedView.findViewById(R.id.webimage);
       TextView txtTitle = (TextView) convertedView.findViewById(R.id.title);

       txtTitle.setText(entry.getTitle());

       String imageUrl = entry.getMediaContentUrl();

       // calling reset is important in order to make sure an old image from the recycled
       // view is not displayed while loading
       imageView.reset();

       if (imageUrl != null) {
           imageView.setImageUrl(entry.getMediaContentUrl());
           imageView.loadImage();
       }

       return convertedView;
   }
}

This code should be pretty descriptive. One word about the reset() method though. As highlighted by the comment, it is important to call reset() on the WebImageView in the context of a list. Since views get recycled (re-used) by Android for performance, there is a good chance that WebImageView being re-used already displays an image. Calling reset() in the getView() method allows to old image to be discarded so that we don’t see that old image while the new image gets downloaded in a background thread.

Next, plug it all together in your main Activity code:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    lstImages = (ListView) findViewById(R.id.mainList);
    txtFeedName = (TextView) findViewById(R.id.feedName);

    listAdapter = new PhotoEntriesListAdapter(this);
    lstImages.setAdapter(listAdapter);

    loadPhotos();
}

private void loadPhotos() {
    new LoadPhotosTask().execute(FEED_URL);
}

private class LoadPhotosTask extends AsyncTask> {
    private String feedUrl;
    private ProgressDialog progressDialog;

    @Override
    protected void onPreExecute() {
        progressDialog = ProgressDialog.show(MainActivity.this,
                "Loading feed...", "Please wait...", true);
    }

    @Override
    protected List doInBackground(String... feedUrls) {
        this.feedUrl = feedUrls[0];

        try{
            FeedParser parser = FeedParserFactory.getParser(ParserType.SAX, feedUrl);

            return parser.parse();

        } catch (Throwable t){
            Log.e(getClass().getSimpleName() , t.getMessage(), t);
        }
        return null;
    }

    @Override
    protected void onPostExecute(List photoEntries) {

        try {

            txtFeedName.setText(feedUrl);

            listAdapter.setPhotos(photoEntries);
            listAdapter.notifyDataSetChanged();
        } finally {

            progressDialog.dismiss();
        }
    }
}

This snippet also highlights best practices for handling long-running tasks in Android, along with the display of a nice progress dialog while data is loading.

That’s it!

It is worth mentioning that, as of now, the current release of Droid-Fu’s WebImageView acts weirdly when used in a ListView (WebImageViews can flicker or display the wrong image). I have made a fix to the library which I plan to submit as a pull request on Droid-Fu project very soon.

UPDATE: Just submitted the pull request.

UPDATE 2: The pull request has been pulled in the main branch, so the fix in the latest release of Droid-fu!