Hitting Publish is the Hardest Part of Blogging

I had been sitting on the draft of my post “When You Should Use Null in Kotlin” since November (for 3 months) because after I had a colleague review it, I wasn’t sure if my views were valid.  My colleague told me about “null, the billion-dollar mistake” and asked if I was just trying to “stir the pot” with a possibly unpopular opinion. That made me question if my views were actually valid, so I didn’t hit “Publish”.

Draft was Last Modified 3 Months Ago

Validation

Earlier this month, Roman Elizarov (@relizarov), from the Kotlin libraries team posted an article which validated my thoughts I shared in my draft post, null is something to use, and not completely avoid:

I was excited to see a like-minded post from one of my software idols who designs the Kotlin language:

Chatting with Roman at Google I/O 2018

Thanks to this validation, I finally got up the courage to finish my post which took many hours and reviews, but I finally published my article. 😄 Thanks Roman (@relizarov)!

Non-null Opinions

I encourage you to share your opinion on topics where you have spent enough time digging into a topic to develop one.  So much of computer science is subjective, and there will always be varying opinions.  As long as you have identified reasons why you feel a certain way, those are valid.

It’s okay to share your thoughts.  Your opinion is non-null 😂.  Be humble enough to listen to others and allow yourself to use objective reasoning to help shape your understanding.

Leverage The Community

The Android community has varying opinions on many things, but that isn’t a bad thing.  There is no single way to do something, and whether or not something is the right solution depends on the use case, and the skills of the team.

Many members of the community are there to help.  I encourage you to reach out and ask for feedback from more than one person as it will help you get well rounded feedback.  Before I published the post I got feedback from @molsjeroen, @ataulm, @ZakTaccardi, @gpeal8 and @jarvisapps.  Each person had slightly different insights, and it helped me create a higher quality post.

A Checklist for Hitting Publish

  1. Write your content
  2. Add applicable content/images/code
  3. Review your content as if you were a reader
  4. Ask for reviews from 2+ people
  5. Address feedback
  6. Set a time limit (3? days)

I put together this checklist to help guide me in the future, and hope it will allow me to publish more posts!  I have at least 5 more drafts in my head that I need to get to next.  By publishing these articles, I’m able to get to the next one, and hopefully help someone publish theirs.

Kotlin + buildSrc for Better Gradle Dependency Management

Multi-module Android projects are now the recommended way to take advantages of performance improvements with Android Gradle Plugin 3+.  However, as we add more modules to our project, we quickly run into the issue of dependency management.

Different ways of managing Gradle dependencies:
  1. Manual Management
  2. Google’s Recommendation using “ext”
  3. Kotlin + buildSrc

1) Manual Management 👎

This is the way most of us have been managing dependencies, but it requires a lot of manual changes whenever you upgrade a library to ensure that versions are updated correctly.

module_a/build.gradle

implementation "com.android.support:support-annotations:27.0.2"
implementation "com.android.support:appcompat-v7:27.0.2"
implementation "com.squareup.retrofit2:retrofit:2.3.0"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
implementation "io.reactivex.rxjava2:rxjava:2.1.9"

module_b/build.gradle

implementation "com.android.support:support-annotations:27.0.2"
implementation "com.android.support:appcompat-v7:27.0.2"
implementation "com.squareup.retrofit2:retrofit:2.3.0"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
implementation "io.reactivex.rxjava2:rxjava:2.1.9"

This is a lot of duplicated configuration that is hard to manage upgrades with, especially when you have a lot of modules.

2) Google’s Recommendation: Using Gradle Extra Properties 🙂

This is Google’s recommended way of doing this as seen in the Android documentation.  It is also used in lots of Android projects, like ButterKnife and Picasso.

This method is great for upgrading libraries like the support library.  Every support library dependency has the same version number, so only having to change this in one place is 💯.  The same things goes for Retrofit, and many other libraries.

Root-level build.gradle

ext {
  versions = [
    support_lib: "27.0.2",
    retrofit: "2.3.0",
    rxjava: "2.1.9"
  ]
  libs = [
    support_annotations: "com.android.support:support-annotations:${versions.support_lib}",
    support_appcompat_v7: "com.android.support:appcompat-v7:${versions.support_lib}",
    retrofit :"com.squareup.retrofit2:retrofit:${versions.retrofit}",
    retrofit_rxjava_adapter: "com.squareup.retrofit2:adapter-rxjava2:${versions.retrofit}",
    rxjava: "io.reactivex.rxjava2:rxjava:${versions.rxjava}"
  ]
}

module_a/build.gradle

implementation libs.support_annotations
implementation libs.support_appcompat_v7
implementation libs.retrofit
implementation libs.retrofit_rxjava_adapter
implementation libs.rxjava

module_b/build.gradle

implementation libs.support_annotations
implementation libs.support_appcompat_v7
implementation libs.retrofit
implementation libs.retrofit_rxjava_adapter
implementation libs.rxjava

This is a huge step ahead from manual management, but IDE support is lacking.  Check out this screencast of migrating to use Gradle Extra Properties (“ext”), and this Github pull request of the results.

While you can be content with using “ext” properties, I think you will be excited to use Kotlin in a buildSrc directory.

3) Kotlin + buildSrc == Android Studio Autocomplete 😎 🎉

You can create a buildSrc module with Kotlin code to manage dependencies and get IDE completion support.

From the Gradle Documentation:

When you run Gradle, it checks for the existence of a directory called buildSrc. Gradle then automatically compiles and tests this code and puts it in the classpath of your build script. You don’t need to provide any further instruction.

You just need 2 files in your buildSrc module:

  1. build.gradle.kts
  2. Kotlin Code (In this case,Dependencies.kt)

buildSrc/build.gradle.kts

plugins {
    `kotlin-dsl`
}

buildSrc/src/main/java/Dependencies.kt

object Versions {
    val support_lib = "27.0.2"
    val retrofit = "2.3.0"
    val rxjava = "2.1.9"
}

object Libs {
 val support_annotations = "com.android.support:support-annotations:${Versions.support_lib}"
 val support_appcompat_v7 = "com.android.support:appcompat-v7:${Versions.support_lib}"
 val retrofit = "com.squareup.retrofit2:retrofit:${Versions.retrofit}"
 val retrofit_rxjava_adapter = "com.squareup.retrofit2:adapter-rxjava2:${Versions.retrofit}"
 val rxjava = "io.reactivex.rxjava2:rxjava:${Versions.rxjava}"
}

After we have done a Gradle Sync, following making the changes above, we can now access any of the values in Android Studio.

The result looks very similar to what “ext” looked like, but we have autocomplete and click support (to take you to the definition).

module_a/build.gradle

implementation Libs.support_annotations
implementation Libs.support_appcompat_v7
implementation Libs.retrofit
implementation Libs.retrofit_rxjava_adapter
implementation Libs.rxjava

module_b/build.gradle

implementation Libs.support_annotations
implementation Libs.support_appcompat_v7
implementation Libs.retrofit
implementation Libs.retrofit_rxjava_adapter
implementation Libs.rxjava

Check out this screencast and this Github pull request showing migration from Gradle Extra Properties “ext” to use Kotlin + buildSrc.

Conclusion

I highly recommend the “Kotlin + buildSrc” option.  It may not seem like it’s that big of a deal, but managing Gradle dependencies is a pain, and having autocomplete and click support is a game changer.  No more switching back and forth between files manually!

Related Caster.io Lessons on Gradle Dependency Management (FREE)

  1. Gradle Dependency Management: Using Gradle Extra Properties (ext)

  2. Gradle Dependency Management: Using Kotlin and buildSrc for build.gradle Autocomplete in Android Studio

Related Links

Hat Tips/Thanks

Questions/Comments?

Reach out to me on Twitter at @HandstandSam

How do I write static methods in Kotlin?

When I was starting to write Kotlin code, and one problem I faced was how the heck do I do static methods like I can add in Java?

The solution… The companion object in your Kotlin class.

class MyClass() {
  companion object {
    fun myStaticMethod() {
      //Do Stuff Here
    }
  }
}

Accessing this static method via Kotlin:

MyClass.myStaticMethod()

Accessing this static method via Java:

MyClass.Companion.myStaticMethod()

To avoid having to use the “.Companion” syntax, use the @JvmStatic annotation, allowing you to access the method without “.Companion”:

class MyClass() {
  companion object {
    @JvmStatic
    fun myStaticMethod() {
      //Do Stuff Here
    }
  }
}

Accessing this static method via Java and @JvmStatic:

MyClass.myStaticMethod()