Documenting Kotlin Code for Android Using KDoc and Dokka

Learn how to use KDoc to document your Kotlin code and generate beautiful-looking documentation pages using Dokka. By Rajdeep Singh.

5 (2) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

Customizing Dokka

The first thing you’ll customize is the output directory for module-level HTML documentation.

If you remember the gradle tasks from before, dokkaHtml is the task responsible for generating HTML documentation for each individual module.

Open the root-level build.gradle file and replace TODO:8 with following:

tasks.named("dokkaHtml") {
  outputDirectory.set(file("$rootProject.name-$project.name-dokka"))
}

This updates the task to use a different output directory for each module. So, Dokka will use notktx-app-dokka, notktx-core-dokka and notktx-utilities-dokka for the respective modules.

But now, calling the clean task in gradle won’t delete the documentation directories because they aren’t under the build directory anymore.

To fix that, replace the TODO:9 line with the snippet shown below:

task cleanDokkaModuleDocs() {
  subprojects {
    delete file("$rootProject.name-$project.name-dokka")
  }
}

To invoke this task automatically when calling ./gradlew clean, update the clean task to depend on dokkaHtmlMultiModule. The task should look like this:

task clean(type: Delete, dependsOn: cleanDokkaModuleDocs) {
  delete rootProject.buildDir
}

This adds a gradle task that goes through all the subprojects and deletes the custom documentation directories. Run ./gradlew dokkaHtml dokkaHtmlMultiModule to generate documentation in the newly defined custom directory structure.

Whenever you want to delete those generated documentation directories, you need to run ./gradlew clean in the terminal. It will call cleanDokkaModuleDocs itself for you.

Adding External Documentation

There’s a minor problem in the documentation you generated in the last section. If you open the ImageLoaders.kt and look at the KDoc comment for loadImageFromUrl, you’ll see this snippet:

* @see Picasso

This should add a link to Picasso class in the See also section of loadImageFromUrl‘s documentation.

But if you open the multimodule documentation in a browser and click loadImageFromUrl in the utilities package, you’ll see it doesn’t provide a clickable link. Instead, it shows a text with the package name of Picasso.

Dokka see also section screenshot

Dokka needs to know the location of JavaDoc of any third-party library for this external linking to work. To do that, open the root-level build.gradle and replace TODO:10 with following snippet:

tasks.named("dokkaHtmlPartial") {
  dokkaSourceSets {
    named("main") {
      externalDocumentationLink {
        url.set(new URL("https://square.github.io/picasso/2.x/picasso/"))
      }
      externalDocumentationLink {
        url.set(new URL("https://bumptech.github.io/glide/javadocs/4120/"))
      }
    }
  }
}

One thing to keep in mind is that the external link has to end with a /.

Add the external documentation links for dokkaHtml task too by adding the below snippet in tasks.named("dokkaHtml"):

dokkaSourceSets {
  named("main") {
    externalDocumentationLink {
      url.set(new URL("https://square.github.io/picasso/2.x/picasso/"))
    }
    externalDocumentationLink {
      url.set(new URL("https://bumptech.github.io/glide/javadocs/4120/"))
    }
  }
}

This adds the links to Picasso’s and Glide’s documentation pages. loadRoundImageFromUrl uses Glide to load images.

Run ./gradlew clean dokkaHtmlMultiModule in the terminal to generate the documentation again. You’ll see that Dokka adds the link to the Picasso class in the documentation now. How it works under the hood goes beyond the scope of this article.

Dokka page with linked third party documentation

Dokka generates the See also section for @see block tag. It’s useful for cases when you want to point readers to other functions or classes to get a better understanding of the current one.

Say that you decide to deprecate loadImageFromUrl and add a new function, loadImageFromUrlV2, that uses Glide under the hood to load images instead of Picasso to get consistent with loadRoundImageFromUrl.

You’ll need to do three things:

  1. Add the new function and its documentation describing the library version in which it was added.
  2. Add a deprecation tag for loadImageFromUrl and a way to point users to its replacement function.
  3. Update the library version.

Open ImageLoaders.kt and replace TODO:11 with the following snippet:

/**
 * An extension function on [ImageView] receiver to load an image from some remote url.
 *
 * This function uses <b>Glide</b> which is a 3rd party library to handle all the networking and
 * caching side of things. Glide handles the loading w.r.t. the lifecycle of the view for you.
 *
 * <b>Sample Usage</b>
 *
 * ```
 * yourImageView.loadImageFromUrlV2(url = "https://someurl.com/someImage")
 * ```
 *
 * @receiver [ImageView]
 * @param url Url to load image from
 * @since v1.0.2
 * @see Glide
 */
fun ImageView.loadImageFromUrlV2(url: String) {
  Glide.with(this).load(url).centerCrop().into(this)
}

To deprecate the existing function, you need to add Deprecated annotation above its definition. And, to point users to the replacement function, you need to add @see loadImageFromUrlV2 in the KDoc comment.

After doing the above changes, loadImageFromUrl will look something like this:

// Truncated code above

 * @param url Url to load image from
 * @see Picasso
 * @see loadImageFromUrlV2
 */
@Deprecated(message = "Moving to Glide", replaceWith = ReplaceWith("loadImageFromUrlV2"),
    level = DeprecationLevel.WARNING)
fun ImageView.loadImageFromUrl(url: String) {

// Truncated code below

Finally, you need to update the library version. Open publish.gradle file and change LIB_VERSION variable to "1.0.2".

Run ./gradlew clean dokkaHtmlMultiModule and you’ll see documentation pages updated to these:

Dokka loadImageFromUrl deprecated function page

Dokka loadImageFromUrlV2 function page

Customizing Member Visibility

The next thing you’ll do is stop Dokka from showing all the methods and properties of parent classes in MainActivity.

Select the MainActivity tab in the generated docs, and you’ll see a lot of functions and properties listed there that you didn’t define. Those are from the parent classes and hide the functions and properties you actually care about.

Dokka docs screenshot

Dokka provides a flag to hide the members of the parent class you didn’t explicitly override.

Open the root-level build.gradle file and add suppressInheritedMembers.set(true) in both dokkaHtml and dokkaHtmlPartial tasks. Tasks should look like this:

// Truncated code above

tasks.named("dokkaHtml") {
  outputDirectory.set(file("$rootProject.name-$project.name-dokka"))
  suppressInheritedMembers.set(true)

// Truncated code

tasks.named("dokkaHtmlPartial") {
  suppressInheritedMembers.set(true)

// Truncated code below

Run ./gradlew clean dokkaHtmlMultiModule to see the changes:

Generated documentation screenshot

The functions and properties from the parent classes are gone, but the overridden onCreate method and other private methods and properties aren’t showing up either.

Dokka hides non public members by default. To show non-public properties and methods, you need to add includeNonPublic.set(true) in the main source set in the dokkaSourceSets block. It should look like this:

dokkaSourceSets {
  named("main") {
    includeNonPublic.set(true)
    externalDocumentationLink {
      url.set(new URL("https://square.github.io/picasso/2.x/picasso/"))
    }
    externalDocumentationLink {
      url.set(new URL("https://bumptech.github.io/glide/javadocs/4120/"))
    }
  }
}

If you want any property, method or class to not show up in the documentation, you can use @suppress tag. Open MainActivity.kt and replace TODO:15 with the snippet below:

/**
 * @suppress
 */

Run ./gradlew clean dokkaHtmlMultiModule to see the changes:

Documentation screenshot with non public members