Writing Android app with Kotlin


When I read about Kotlin, I thought of it as a functional port of Java which is (100% interoperable with Java). I have been playing with Scala for a bit. The biggest trouble I had with Scala is wide range of semantic alternatives. But it seems like, Kotlin has a decisive approach towards making Java more functional and more compact for developers.

Kotlin does support Androi and they do have a very verbose documentation about 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 with simulated API calls (had to do it quickly).

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.

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

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