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. 2.
  2. 3.
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 12.

    data class Task( val id: String, val title: String?, val

    description: String?, var completed: Boolean )
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 21.

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

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  19. 22.

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

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  20. 23.

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

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  21. 24.

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

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  22. 25.

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

    ViewHolder() class ItemViewHolder(val data: String) : ViewHolder() object LoadingViewHolder : ViewHolder() }z
  23. 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
  24. 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
  25. 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
  26. 29.

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } } }
  27. 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
  28. 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
  29. 32.

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } } }
  30. 33.

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } }z }d
  31. 34.

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { /*****/ }f }z }d
  32. 35.

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { /*****/ }f }z }d
  33. 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
  34. 37.

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { holder.stuff() }f }z }d
  35. 38.

    override fun onBindViewHolder(holder: ViewHolder, position: Int) { return when (holder)

    { is HeaderViewHolder -> { /*****/ } is ItemViewHolder -> { /*****/ } is LoadingViewHolder -> { /*****/ } is FooterViewHolder -> { /*****/ }f }z }d
  36. 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); }
  37. 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); }
  38. 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); }
  39. 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); }
  40. 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); }
  41. 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); }
  42. 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")
  43. 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")
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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) }
  53. 61.
  54. 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
  55. 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)
  56. 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)
  57. 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)
  58. 73.

    class Foo() { operator fun invoke(): String { return "invoked

    !" } } fun main(args: Array<String>) { val foo: Foo = Foo() println(foo()) // invoked ! }
  59. 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)
  60. 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)
  61. 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)
  62. 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)
  63. 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)
  64. 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)
  65. 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)
  66. 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)
  67. 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)
  68. 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)
  69. 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)
  70. 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)