13 Apr 2019
|
Kotlin
함수 선언
함수의 기본 형태는 다음과 같습니다.
fun add(x: Int, y: Int): Int {
return x + y
}
위의 함수는 다음과 같이 조금씩 변형해서 사용할 수 있습니다.
fun add(x: Int, y: Int): Int = x + y
fun add(x: Int, y: Int) = x + y
변수 타입
코틀린은 자동 변환 기능을 허용하지 않습니다. 예를 들어 Java에서는 int
에서 double
이나 float
등으로 자동 변환이 가능했지만, 코틀린에서는 오류가 발생합니다. 다음과 같이 타입 변환을 항상 해야 합니다.
val i:Int = 1
val value:Long = i.toLong()
코틀린은 |
, &
와 같은 비트 연산을 or
또는 and
로 표현해야 합니다.
변수 추론 기능이 있어서 타입 선언을 생략하고 사용할 수 있다.
val i = 1
val hex = 0x23
val long = 4L
val double = 5.0
val float = 6.0F
val str = "Hello"
vararg
여러 개의 매개변수를 사용하고 싶을 때는 vararg
키워드를 사용합니다.
fun sum(vararg numbers: Int): Int {
var ret = 0
for (n in numbers)
ret += n
return ret
}
fun main(args: Array<String>) {
println(sum(1))
println(sum(1, 2, 3))
}
13 Apr 2019
|
Android
Kotlin
build.gradle
dependencies {
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/add_log_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Log"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
item_log.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
app:cardCornerRadius="4dp"
app:cardElevation="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:text="message"
android:textColor="@android:color/holo_blue_dark"
android:textSize="14sp"/>
<TextView
android:id="@+id/timestamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="timestamp"
android:textColor="@android:color/darker_gray"
android:textSize="10sp"/>
</LinearLayout>
</android.support.v7.widget.CardView>
LogListAdapter.kt
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.item_log.view.*
import java.text.SimpleDateFormat
import java.util.*
data class LogItem(val text: String, val timestamp: String)
class LogListAdapter(val ctx: Context) : RecyclerView.Adapter<ViewHolder>() {
private val list: ArrayList<LogItem> = ArrayList()
fun addLog(message: String) {
val c = Calendar.getInstance()
val date = Date(c.timeInMillis)
val sdf = SimpleDateFormat("yyyy/MM/dd hh:mm:ss", Locale.getDefault())
list.add(LogItem(message, sdf.format(date)))
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view: View = LayoutInflater.from(ctx).inflate(R.layout.item_log, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return list.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder?.message?.text = list.get(position)?.text
holder?.timestamp?.text = list.get(position)?.timestamp
}
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val message = view.message
val timestamp = view.timestamp
}
MainActivity.kt
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var i: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adapter = LogListAdapter(applicationContext)
recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.adapter = adapter
add_log_button.setOnClickListener {
i++
Log.i("snowdeer", "[snowdeer] Add log button is clicked!!")
adapter.addLog("Hello $i")
}
}
}
12 Apr 2019
|
Kotlin
data class
data class LogItem(val text: String, val timestamp: String)
data 클래스는 데이터만을 갖는 클래스입니다. 반드시 디폴트 생성자를 선언해야 하며, 인자는 val
또는 var
키워드를 꼭 사용해야 합니다. 컴파일러는 자동으로 equal()
및 toString()
함수를 생성해줍니다.
enum class
코틀린에서 enum
은 다음과 같은 형태로 선언할 수 있습니다.
enum class COLOR(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF),
}
enum class STATUS(val text: String) {
STARTED("Started"),
FINISHED("Finished"),
FAILED("Failed"),
UNKNOWN("Unknown"),
}
사용 방법은 다음과 같습니다.
var color = COLOR.BLUE
println(color)
println(color.rgb)
var status = STATUS.STARTED
println(status)
println(status.text)
sealed class
sealed 클래스는 프로그램 내부에서는 상속을 할 수 있지만, 외부 모듈에서는 상속을 할 수 없도록 하는 키워드입니다.
다음과 같이 사용할 수 있습니다.
sealed class SnowSDK {
}
같은 프로젝트 안에만 있다면 sealed 클래스를 상속한 클래스가 어느 파일에 위치하든지 상관이 없습니다.
object 타입
익명(anonymous) 클래스를 사용할 때 Java에서는 다음과 같이 사용했습니다.
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO
}
});
하지만 코틀린에서는 다음과 같이 object
키워드를 이용해서 익명 클래스를 사용할 수 있습니다.
button.setOnClickListener(object : View.OnClickListener() {
fun onClick(v: View) {
TODO("...")
}
})
12 Apr 2019
|
Kotlin
코틀린에서는 Java의 static main
함수를 다음과 같이 작성할 수 있습니다.
Main.kt
fun main(args: Array<String>) {
println("Hello, Kotlin")
}
12 Apr 2019
|
Android
Kotlin
build.gradle
dependencies {
implementation 'com.android.support:design:28.0.0'
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/add_log_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Log"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
item_log.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
app:cardCornerRadius="4dp"
app:cardElevation="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:text="message"
android:textColor="@android:color/holo_blue_dark"
android:textSize="14sp"/>
<TextView
android:id="@+id/timestamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="timestamp"
android:textColor="@android:color/darker_gray"
android:textSize="10sp"/>
</LinearLayout>
</android.support.v7.widget.CardView>
LogListAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
data class LogItem(val text: String, val timestamp: String)
class LogListAdapter(val ctx: Context) : BaseAdapter() {
private val list = ArrayList<LogItem>()
init {
list.add(LogItem("hello", "2019/04/15 13:00"))
list.add(LogItem("Nice to meet you", "2019/04/15 14:00"))
list.add(LogItem("Good bye", "2019/04/15 17:00"))
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var view: View
val holder: ViewHolder
if (convertView == null) {
view = LayoutInflater.from(ctx).inflate(R.layout.item_log, parent, false)
holder = ViewHolder()
holder.message = view.findViewById(R.id.message)
holder.timestamp = view.findViewById(R.id.timestamp)
view.tag = holder
} else {
view = convertView
holder = convertView.tag as ViewHolder
}
val item = list[position]
holder.message.text = item.text
holder.timestamp.text = item.timestamp
return view
}
override fun getItem(position: Int): LogItem {
return list[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return list.size
}
}
private class ViewHolder {
lateinit var message: TextView
lateinit var timestamp: TextView
}
MainActivity.kt
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adapter = LogListAdapter(applicationContext)
listview.adapter = adapter
}
}