Writing Android app with Kotlin


When I read the description about kotlin, I thought of it as a very beautiful port of Java (as its a JVM based language and 100% interoperable with Java). I have been trying to like Scala for a lot time now, but hell lot of options for everything, complex semantics makes the code unreadable and confusing (for me). But kotlin, according to me is a decisive approach towards making Java more functional and more compact for developers.

The first thing I searched when I read about Kotlin was, about Android support. Scaloid being more and more popular and I being completely not in love with Scala, this was going to be an interesting thing for me. Kotlin does have support for Android and they do have amazing documentation about both language as well as Android support, So I went ahead and tried one simple list app with an adapter and a fragment, just to simulate a simple part of general Android application.

Setup

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:0.9.206"
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

The Application

I started with writing a HackerNews listing app. But then restricted it to simulating the API call with a stub so as to focus onto the Kotlin more than the actual functionality of the application.

Code

Let’s dive into some code.

Home

It’s the main activity (launcher) of the application.

open class Home(): ActionBarActivity(){

    val logTag = "###Home###"

    override fun onCreate(savedInstanceState: android.os.Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home)
        val transaction = getSupportFragmentManager().beginTransaction()
        transaction.replace(R.id.posts_container, PostListFragment.Maker.Create())
        transaction.commit()
    }
}

Things I loved

PostListFragment

This is the fragment that contains list of posts. It’s a DialogFragment, so as to make it available to be used as a dialog as well.

open class PostListFragment() : DialogFragment() {
    val logTag = "###PostListFragment###"
    var postList: ListView? = null
    var baseView: View? = null
    var postsAdapter: PostListAdapter? = null
    var handler: Handler? = null

    object Maker {
        fun Create(): PostListFragment {
            return PostListFragment()
        }
    }

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        baseView = inflater?.inflate(R.layout.fragment_post_list, container, false)
        postList = baseView?.findViewById(R.id.post_list) as ListView
        postsAdapter = PostListAdapter(getActivity(), postList as AbsListView)
        postList.setAdapter(postsAdapter)
        handler = Handler()
        return baseView
    }

    override fun onResume() {
        super.onResume()
        Post.Maker.GetList {
            Log.d(logTag,"Testing get list =>" + it.get(0).post)
            postsAdapter?.postList?.addAll(it)
            handler?.post {
                this.postsAdapter?.notifyDataSetChanged()
            }
        }
    }
}

Things I loved

Things I hated

Post
This is the model class containing info related with each post.

data class Post(val id: Long, val post: String, val by: String, val postedAt: Date) {
    object Maker {
        fun GetList(onSuccess: (posts: List) -> Unit) {
            val posts = ArrayList()
            for (a in 1..10) {
                posts.add(Post(a.toLong(), "Test", "Akshay", Date()))
            }
            onSuccess(posts)
        }
    }
}

Things I loved

PostListAdapter

This is the list adapter for post list view.

open class PostListAdapter(val context:Context,val listView: AbsListView): BaseAdapter(){

  private val logTag: String = "###PostListAdapter###"
  var postList = ArrayList()

  override fun getCount(): Int {
      return postList.size
  }

  override fun getItem(position: Int): Any? {
      if(position >= postList.size)
          return null
      return postList.get(position)
  }

  override fun getItemId(p0: Int): Long {
      if(p0 >= postList.size)
          return -1
      return postList.get(p0).id
  }

  override fun getView(position: Int, view: View?, parent: ViewGroup): View? {
      var cachedItem: ItemCache?
      var contentView: View ? = view
      when (contentView) {
          null -> {
              contentView = LayoutInflater.from(context).inflate(R.layout.layout_post_item, parent, false)
              cachedItem = ItemCache(textView = contentView?.findViewById(R.id.post) as TextView)
              contentView?.setTag(cachedItem)
          }
          else -> {
              cachedItem = contentView?.getTag() as ItemCache
          }
      }
      val currentPost = getItem(position) as Post
      cachedItem?.textView?.setText(currentPost.post)
      return contentView
  }

  class ItemCache(val textView: TextView?)
}

This all works well. The source code is available at https://github.com/akshaydeo/kotlin_android.

Some analysis of APK

-XX:MaxPermSize=1024m -XX:MaxHeapSize=256m -Xmx256m

Important Links for Kotlin

I will be updating this post as I progress in analysing the side effects of using Kotlin for Android development.


Comments