The Android Skeleton Project

How often has this happened to you? Some new library comes out and you want to try it, you have some kind of brilliant idea to solve a particular problem, or you’ve needed to build an example app for a new job you’re applying for. So you boot up Android Studio, hit New project, skip through the steps and then you’re presented with a new playground to work in. Amazing!

But then… you start to code. And you realise - I’m missing a tonne of the dependencies that I want. So you dig around in old projects trying to find them, copying and pasting as you go. Then you realise your old project is really out of date, so you start looking online for the latest versions. It’s been an hour already and you haven’t really achieved anything, and it’s starting to grate on you. You get distracted by Twitter for a bit.

Finally your dependencies are all in - I say “all”, I mean the ones you need to get started. You probably missed a few that you’ll need later. You write a little code, go to build and suddenly you’re hit with Gradle, complaining about a transient dependency. Your previous setup with out of date libraries was stable, but something you’ve updated has broken something else.

You sigh, and spend another hour trying to figure out what’s gone wrong. You get distracted and spend an afternoon on Reddit.

You get back to your project, and you realise that some clever extension function that you like is missing! So you open up the old project again, hunt around for the .kt file (what did I name it again?), and copy paste some more.

Then you realise you need to set up Dagger again.

You’ve forgotten why you started, and you never touch the project again.

I’ve done this countless times. What’s even worse is that I’ve done this when starting on a code challenge when interviewing for a new role - and setting up all that boilerplate has absolutely sucked all the energy out of me. So this is my attempt at making sure that I - and hopefully you - don’t go through this scenario again.

Why you should keep a skeleton project

If this resonated with you at all, I highly recommend that you do this dance just once more, and then keep this project around on which to base all of your new work. You’ll want to update it every now and again - if there’s a new library that you just started using, or a new AndroidX release: spend ten minutes updating your template. Use CI to check that it builds correctly.

Every time you create an awesome new extension function that you can’t live without? Dump it in your skeleton project. Takes 30 seconds. Keeps all of your best work in one place.

Just read about some awesome trick on a blog somewhere? Add that too, if you think it’ll add value to all of your projects.

As your approach to Android changes and evolves, update this skeleton with a very basic example of your new approach. Maybe create a template too so that you can streamline your workflow even more.

Think of it as occasionally watering your Android garden. Adding to this project and maintaining it, for just a few minutes a few times a month will save you tonnes of pain next time you start a new project. Just copy your skeleton project into a new folder, rename the package to something unique and start working on the good stuff. Banish boilerplate and work on what’s important.

What to include

My list of stuff that I like to keep in my skeleton project is pretty big. You may not need all of this, but here’s some ideas:

  • A master dependencies file. I recommend using buildSrc (see an example here) and writing it in Kotlin, but it doesn’t matter how you do it. Add any library that you might want, and don’t be afraid to include things that you’re unlikely to want in every project. This way you won’t have to wrack your brain for that obscure-but-handy library that you used once: you have a record of it in your skeleton project.
  • A basic build.gradle file in :app. This should include the dependencies that you know you’re going to want every time (AppCompat, Dagger, RxJava, Kotlin etc) and allow you to immediately get moving. Also include any common configuration options that you might normally set up, such as logging for tests, build type setups, ProGuard configs etc. Remember, the idea is to avoid as much boilerplate as possible.
  • A basic Dagger/Koin setup. Getting both of these things up and running is a total momentum killer for me. Create one or two artitrary classes and make sure that you’re able to inject them into a simple Activity. Now when you get coding, you can just build ontop of your existing DI/SL setup.
  • A :network module, with OkHttp/Retrofit/your-choice-of-network-stack setup already. It’s very very rare that this setup will need to change between apps, so avoid ever having to set it up from scratch again. Keep the dependencies tightly scoped to this module - :app doesn’t need to be aware that OkHttp exists, for instance.
  • A :testutils module. This can have commonly used test rules in it (for RxJava Schedulers or whatever else) and various helper functions. Just as an example, I like having fun <T>.just() = Observable<T>.just(this) available when testing for readability. I don’t like having to remember to add it to each project.

    • I’d also recommend having all of your testing dependencies - JUnit, Mocktio, Kluent etc - in this module exposed via api (rather than implementation). This way you can simply add a testImplementation dependency on :testutils and have everything that you need.
    • You may want an :androidtestutils module too for dependencies and helper functions specific to UI/Integration tests.
  • A basic CI script setup already. Setting up CI is something that I find particularly frustrating and painful. Do it in your skeleton project, and then tweak it as you need to for each new project.

  • A basic Fastlane script for deployment. If you’re a CD type person (which you probably should be), set this up too.

  • Code quality stuff. This includes ktlint, Jacoco test coverage reports, Sonar… whatever you like to use. Add these Gradle files to /quality, and apply them to your submodules.

  • A basic example of your preferred architecture. Add a simple ViewModel, add a Repository, wire it all together, test it, and inject it into an Activity.

    • If you’re feeling super productive, add a template that creates an Activity, ViewModel + test framework etc for you.
  • A feature module. Modularising as much as possible is super beneficial, so add an example of one with its own Dagger setup already sorted.

  • If you’re feeling really fancy, add a setup script which installs your preferred code style, templates, file headers etc into Android Studio. Make setting up the project for someone else to contribute to a one-liner.

  • Any extension or helper functions that you use regularly + tests for them. Keep adding these over time and put them in separate modules if appropriate.

What this gives you

Whilst a fair bit of work to get up and running, having one of these around will pay dividends in the future. If you’re inspired and just want to get cracking, you’ve probably saved yourself hours and hours of time (and most importantly, energy) getting set up. If you’ve got a code challenge to do for a prospective company, you can hit the ground running and also show that you’ve really thought about your project setup - effectively for free.

A skeleton project is also a memory bank. If you’ve done something clever worth saving, or something tedious that you’ll need to do again - put it in there as well. Having to re-solve problems that you know you’ve already solved before is hugely inefficient. Keep a collection of these solutions here.

All this being said - do be critical of what you store in your template project. Don’t chuck everything you’ve ever written in there - that’s not really the point - just the boilerplate that makes your life easier which you can use in every project.

Overall, it buys you tonnes of time. We all like solving problems, and keeping a project setup which allows you to just tackle the fun stuff is highly beneficial.

My project

I’ve made one of these and you can find it here. Feel free to fork it if you want, or copy some of the ideas/files and build your own. You’ll notice I haven’t done everything in this project which I suggested here - it’s still a work in progress and by no means comprehensive - but it works for me and I’ll keep adding to it and updating it over time. I’m sure someone will come up with a better version and I’d love to see it take off as many people’s default starting point, which they then customise to their needs.

I hope the ideas here were helpful to you: now go tend to your Android garden.

comments powered by Disqus