Pro Yearly is on sale from $80 to $50! »

KotlinでAndroid開発を気持ちよくしよう

 KotlinでAndroid開発を気持ちよくしよう

Cybozu Meetup #10 モバイル で発表した内容
-------------------------------
Kotlin はまだ使っていませんか?使っているけれど Java と比べて何が良いかがはっきりしませんか?
実は Java で当たり前な面倒くさい事いっぱいあるけれど Kotlin では当たり前な便利な事がいっぱいあります!
日々の開発が楽になり、「もっと早く Kotlin の事を知っとけばよかった!」と皆様が思うように説明させて頂きます。
Kotlin で Android の開発を気持ちよくしましょう。

05162bc961c3654218bf1839974a4f35?s=128

Benoît Quenaudon

January 30, 2018
Tweet

Transcript

  1. KotlinͰAndroid։ൃ Λؾ࣋ͪΑ͘͠Α͏ Benoît Quenaudon @oldergod

  2. None
  3. None
  4. Data Class

  5. public final class Task { @NonNulla private final String id;

    @Nullableb private final String title; @Nullablec private final String description; private final boolean completed; public Task(@Nullable String title, @Nullable String description, @NonNull String id, boolean completed) { this.id = id; this.title = title; this.description = description; this.completed = completed; }a }l
  6. this.description = description; this.completed = completed; }a @NonNulld public String

    getId() { return id; }b @Nullablee public String getTitle() { return title; }c @Nullablef public String getTitleForList() { if (!Strings.isNullOrEmpty(title)) { return title; } else { return description; }z }d @Nullableg public String getDescription() { return description; }e public boolean isCompleted() { return completed; }f public boolean isActive() { return !completed; }g public boolean isEmpty() { return Strings.isNullOrEmpty(title) && Strings.isNullOrEmpty(description); }h }l
  7. }e public boolean isCompleted() { return completed; }f public boolean

    isActive() { return !completed; }g public boolean isEmpty() { return Strings.isNullOrEmpty(title) && Strings.isNullOrEmpty(description); }h @Overrideh public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Task task = (Task) o; return Objects.equal(id, task.id) && Objects.equal(title, task.title) && Objects.equal(description, task.description); }i @Overridei public int hashCode() { return Objects.hashCode(id, title, description); }j @Overridej public String toString() { return "Task with title " + title; }k }l
  8. public final class Task { @NonNulla private final String id;

    @Nullableb private final String title; @Nullablec private final String description; private final boolean completed; public Task(@Nullable String title, @Nullable String description, @NonNull String id, boolean completed) { this.id = id; this.title = title; this.description = description; this.completed = completed; }a @NonNulld public String getId() { return id; }b @Nullablee public String getTitle() { return title; }c @Nullablef public String getTitleForList() { if (!Strings.isNullOrEmpty(title)) { return title; } else { return description; } }d @Nullableg public String getDescription() { return description; }e public boolean isCompleted() { return completed; }f public boolean isActive() { return !completed; }g public boolean isEmpty() { return Strings.isNullOrEmpty(title) && Strings.isNullOrEmpty(description); }h @Overrideh public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Task task = (Task) o; return Objects.equal(id, task.id) && Objects.equal(title, task.title) && Objects.equal(description, task.description); }i @Overridei public int hashCode() { return Objects.hashCode(id, title, description); }j @Overridej public String toString() { return "Task with title " + title; }k }l
  9. @Getter @AllArgsConstructor @EqualsAndHashCode @ToString public final class Task { @NonNull

    private final String id; @Nullable private final String title; @Nullable private final String description; private final boolean completed; @Nullable public String getTitleForList() { if (!Strings.isNullOrEmpty(title)) { return title; } else { return description; } } public boolean isActive() { return !completed; } public boolean isEmpty() { return Strings.isNullOrEmpty(title) && Strings.isNullOrEmpty(description); } } Lombok
  10. @AutoValue public abstract class Task { @NonNull abstract String getId();

    @Nullable abstract String getTitle(); @Nullable abstract String getDescription(); abstract boolean isCompleted(); public static Task create(@Nullable String title, @Nullable String description, @NonNull String id, boolean completed) { return new AutoValue_Task(id, title, description, completed); } public boolean isActive() { return !isCompleted(); } @Nullable public String getTitleForList() { if (!Strings.isNullOrEmpty(getTitle())) { return getTitle(); } else { return getDescription(); } } public boolean isEmpty() { return Strings.isNullOrEmpty(getTitle()) && Strings.isNullOrEmpty(getDescription()); } } AutoValue
  11. data class Task( val id: String, val title: String?, val

    description: String?, val completed: Boolean ) { val titleForList = if (title.isNotNullNorEmpty()) { title } else { description } val active = !completed val empty = title.isNullOrEmpty() && description.isNullOrEmpty() } Kotlin
  12. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean )
  13. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean ) • constructor • getters • setters (var only) • toString • equals & hashCode • copy • componentN
  14. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean ) • constructor • getters • setters (var only) • toString • equals & hashCode • copy • componentN
  15. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean ) • constructor • getters • setters (var only) • toString • equals & hashCode • copy • componentN
  16. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean ) • constructor • getters • setters (var only) • toString • equals & hashCode • copy • componentN
  17. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean ) • constructor • getters • setters (var only) • toString • equals & hashCode • copy • componentN
  18. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean ) • constructor • getters • setters (var only) • toString • equals & hashCode • copy • componentN
  19. data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean ) • constructor • getters • setters (var only) • toString • equals & hashCode • copy • componentN
  20. Sealed Class

  21. sealed class ViewHolder { data class HeaderViewHolder(val text: String) :

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  22. sealed class ViewHolder { data class HeaderViewHolder(val text: String) :

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  23. sealed class ViewHolder { data class HeaderViewHolder(val text: String) :

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  24. sealed class ViewHolder { data class HeaderViewHolder(val text: String) :

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  25. sealed class ViewHolder { data class HeaderViewHolder(val text: String) :

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  26. sealed class ViewHolder(val root: View) : RecyclerView.ViewHolder(view) { class HeaderViewHolder(root:

    View) : ViewHolder(root) class ItemViewHolder(root: View) : ViewHolder(root) class LoadingViewHolder(root: View) : ViewHolder(root) }z
  27. sealed class ViewHolder(val root: View) : RecyclerView.ViewHolder(view) { class HeaderViewHolder(root:

    View) : ViewHolder(root) class ItemViewHolder(root: View) : ViewHolder(root) class LoadingViewHolder(root: View) : ViewHolder(root) }z
  28. sealed class ViewHolder(val root: View) : RecyclerView.ViewHolder(view) { class HeaderViewHolder(root:

    View) : ViewHolder(root) class ItemViewHolder(root: View) : ViewHolder(root) class LoadingViewHolder(root: View) : ViewHolder(root) }z
  29. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } } }
  30. sealed class ViewHolder(val root: View) : RecyclerView.ViewHolder(view) { class HeaderViewHolder(root:

    View) : ViewHolder(root) class ItemViewHolder(root: View) : ViewHolder(root) class LoadingViewHolder(root: View) : ViewHolder(root) }d
  31. sealed class ViewHolder(val root: View) : RecyclerView.ViewHolder(view) { class HeaderViewHolder(root:

    View) : ViewHolder(root) class ItemViewHolder(root: View) : ViewHolder(root) class LoadingViewHolder(root: View) : ViewHolder(root) class FooterViewHolder(root: View) : ViewHolder(root) }d
  32. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } } }
  33. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } }z }d
  34. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { /*****/ }f }z }d
  35. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { /*****/ }f }z }d
  36. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { val footerVH = holder as FooterViewHolder footerVH.stuff() }f }z }d
  37. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { holder.stuff() }f }z }d
  38. override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { /*****/ }f }z }d
  39. Collections API

  40. List<Action> actions; List<Task> tasks = new ArrayList<>(actions.size()); for (Action action

    : actions) { Task task = new Task(action.title(), action.description()); tasks.add(task); }
  41. List<Action> actions; List<Task> tasks = new ArrayList<>(actions.size()); for (Action action

    : actions) { Task task = new Task(action.title(), action.description()); tasks.add(task); }
  42. List<Action> actions; List<Task> tasks = new ArrayList<>(actions.size()); for (Action action

    : actions) { Task task = new Task(action.title(), action.description()); tasks.add(task); }
  43. List<Action> actions; List<Task> tasks = new ArrayList<>(actions.size()); for (Action action

    : actions) { Task task = new Task(action.title(), action.description()); tasks.add(task); }
  44. List<Action> actions; List<Task> tasks = new ArrayList<>(actions.size()); for (Action action

    : actions) { Task task = new Task(action.title(), action.description()); tasks.add(task); }
  45. List<Action> actions; List<Task> tasks = new ArrayList<>(actions.size()); for (Action action

    : actions) { Task task = new Task(action.title(), action.description()); tasks.add(task); }
  46. valaactions:zList<Action> valbtasksz= ArrayList(actions.size) for (action in actions) { valctask =

    Task(action.title, action.description) tasks.add(task) }
  47. valaactions:zList<Action> valbtasksz= actions.map { Task(it.title, it.description) }

  48. • map() • filter() • find() • distinct() • any()

    • groupBy() • zip() • …
  49. • map() • filter() • find() • distinct() • any()

    • groupBy() • zip() • … val list: List<Int> = listOf(1, 2, 3) val map: Map<String, Int> = mapOf("a" to 1, "b" to 2) val set: Set<String> = setOf("a", "b", “c")
  50. • map() • filter() • find() • distinct() • any()

    • groupBy() • zip() • … val list: List<Int> = listOf(1, 2, 3) val map: Map<String, Int> = mapOf("a" to 1, "b" to 2) val set: Set<String> = setOf("a", "b", “c")
  51. Lazy Delegate

  52. private lateinit var viewModel: TaskViewModel private lateinit var taskId: String

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProviders .of(this, ViewModelFactory()) .get(TaskViewModel::class.java) taskId = arguments?.getString(ARGUMENT_EDIT_TASK_ID) }c
  53. private lateinit var viewModel: TaskViewModel private lateinit var taskId: String

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProviders .of(this, ViewModelFactory()) .get(TaskViewModel::class.java) taskId = arguments?.getString(ARGUMENT_EDIT_TASK_ID) }c
  54. private lateinit var viewModel: TaskViewModel private lateinit var taskId: String

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProviders .of(this, ViewModelFactory()) .get(TaskViewModel::class.java) taskId = arguments?.getString(ARGUMENT_EDIT_TASK_ID) }c
  55. private lateinit var viewModel: TaskViewModel private lateinit var taskId: String

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProviders .of(this, ViewModelFactory()) .get(TaskViewModel::class.java) taskId = arguments?.getString(ARGUMENT_EDIT_TASK_ID) }c
  56. private val viewModel: TaskViewModel by lazy { ViewModelProviders .of(this, ViewModelFactory())

    .get(TaskViewModel::class.java) }x private val taskId: String by lazy { arguments?.getString(ARGUMENT_EDIT_TASK_ID) }y override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) }c
  57. private val viewModel: TaskViewModel by lazy { ViewModelProviders .of(this, ViewModelFactory())

    .get(TaskViewModel::class.java) }x private val taskId: String by lazy { arguments?.getString(ARGUMENT_EDIT_TASK_ID) }y override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) }c
  58. private val viewModel: TaskViewModel by lazy { ViewModelProviders .of(this, ViewModelFactory())

    .get(TaskViewModel::class.java) }x private val taskId: String by lazy { arguments?.getString(ARGUMENT_EDIT_TASK_ID) }y override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) }c
  59. private val viewModel: TaskViewModel by lazy { ViewModelProviders .of(this, ViewModelFactory())

    .get(TaskViewModel::class.java) }x private val taskId: String by lazy { arguments?.getString(ARGUMENT_EDIT_TASK_ID) }y override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) }c
  60. private val viewModel: TaskViewModel by lazy { ViewModelProviders .of(this, ViewModelFactory())

    .get(TaskViewModel::class.java) }x private val taskId: String by lazy { arguments?.getString(ARGUMENT_EDIT_TASK_ID) }y override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) }
  61. Operators

  62. class TaskDetailFragment(val taskId: String) : Fragment()

  63. class TaskDetailFragment(val taskId: String) : Fragment() val fragment = TaskDetailFragment(taskId)

  64. class TaskDetailFragment(val taskId: String) : Fragment() val fragment = TaskDetailFragment(taskId)

  65. class TaskDetailFragment(val taskId: String) : Fragment() val fragment = TaskDetailFragment(taskId)

  66. val fragment = TaskDetailFragment()

  67. val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId)

  68. val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId)

    fragment.arguments = bundle
  69. class TaskDetailFragment : Fragment() { companion object { fun newInstance(taskId:

    String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c
  70. class TaskDetailFragment : Fragment() { companion object { fun newInstance(taskId:

    String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment.newInstance(taskId)
  71. class TaskDetailFragment : Fragment() { companion object { fun newInstance(taskId:

    String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment.newInstance(taskId)
  72. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment.newInstance(taskId)
  73. class Foo() { operator fun invoke(): String { return "invoked

    !" } } fun main(args: Array<String>) { val foo: Foo = Foo() println(foo()) // invoked ! }
  74. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment.newInstance(taskId)
  75. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment.newInstance(taskId)
  76. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment(taskId)
  77. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment(taskId)
  78. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle() bundle.putString(ARGUMENT_TASK_ID, taskId) fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment(taskId)
  79. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle().apply { this.putString(ARGUMENT_TASK_ID, taskId) }p fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment(taskId)
  80. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() val bundle = Bundle().apply { putString(ARGUMENT_TASK_ID, taskId) }p fragment.arguments = bundle return fragment }a }b }c val fragment = TaskDetailFragment(taskId)
  81. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment() fragment.arguments = Bundle().apply { putString(ARGUMENT_TASK_ID, taskId) }p return fragment }a }b }c val fragment = TaskDetailFragment(taskId)
  82. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { val fragment = TaskDetailFragment().apply { arguments = Bundle().apply { putString(ARGUMENT_TASK_ID, taskId) }p }p return fragment }a }b }c val fragment = TaskDetailFragment(taskId)
  83. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String): TaskDetailFragment { return TaskDetailFragment().apply { arguments = Bundle().apply { putString(ARGUMENT_TASK_ID, taskId) }p }p }a }b }c val fragment = TaskDetailFragment(taskId)
  84. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String) = TaskDetailFragment().apply { arguments = Bundle().apply { putString(ARGUMENT_TASK_ID, taskId) }p }p }a }b }c val fragment = TaskDetailFragment(taskId)
  85. class TaskDetailFragment : Fragment() { companion object { operator fun

    invoke(taskId: String) = TaskDetailFragment().apply { arguments = Bundle().apply { putString(ARGUMENT_TASK_ID, taskId) }p }p }a }b }c val fragment = TaskDetailFragment(taskId)
  86. Fin Benoît Quenaudon @oldergod