LoginSignup
13
11

More than 5 years have passed since last update.

Kotlinの紹介(社内プレゼン大会資料)

Posted at
1 / 13

先週のGoole I/O 2017で、KotlinがAndroidの公式言語の1つとなると、発表されました

Javaも残ります


Kotlinとは

  • JVM言語(Javaと相互運用できる)
  • 型推論
    • var str = "abc"
  • null安全
    • var strNullable: String?
    • var strNotNull: String
  • 関数型プログラミング
    • listOf(1, 2, 3).map { it * 2 }.filter { it > 2 }.forEach { print(it) }

実際のコードで紹介

  • 画像とテキストのViewをグリッド表示する
  • 各Viewは、スクロールin/outで再利用される

ss_png.png

各Viewを作るコードで見てみます


static class ViewHolder {
    TextView textView;
    ImageView imageView;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Viewを準備する
    ViewHolder holder;
    if (convertView == null) {
        // convertViewがなかったら、xmlからViewを作る
        convertView = LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null);

        // パフォーマンスのため、各sub viewをHolderに保持し、Holder自体もViewに保持しておく
        holder = new ViewHolder();
        holder.imageView = (ImageView) convertView.findViewById(R.id.icon); // ちょっと遅い
        holder.textView = (TextView) convertView.findViewById(R.id.text); // ちょっと遅い
        convertView.setTag(holder);
    } else {
        // convertViewがあれば、再利用する。
        holder = (ViewHolder) convertView.getTag();
    }

    // データをViewに反映する
    Data data = getItem(position);
    holder.imageView.setImageResource(data.imageId);
    holder.textView.setText(data.textId);

    return convertView;
}

internal class ViewHolder {
    var textView: TextView? = null
    var imageView: ImageView? = null
}

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
    var convertView = convertView
    // Viewを準備する
    val holder: ViewHolder
    if (convertView == null) {
        // convertViewがなかったら、xmlからViewを作る
        convertView = LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null)

        // パフォーマンスのため、各sub viewをHolderに保持し、Holder自体もViewに保持しておく
        holder = ViewHolder()
        holder.imageView = convertView.findViewById(R.id.icon) as ImageView // ちょっと遅い
        holder.textView = convertView!!.findViewById(R.id.text) as TextView // ちょっと遅い
        convertView.tag = holder
    } else {
        // convertViewがあれば、再利用する。
        holder = convertView.tag as ViewHolder
    }

    // データをViewに反映する
    val data = getItem(position)
    holder.imageView!!.setImageResource(data.imageId)
    holder.textView!!.setText(data.textId)

    return convertView
}

data classで、fieldとconstructorを同時に定義

- internal class ViewHolder {
-     var imageView: ImageView? = null
-     var textView: TextView? = null
- }
+ data class ViewHolder(val textView: TextView, val imageView: ImageView)

constructorを使えば1行

- holder = ViewHolder()
- holder.imageView = convertView.findViewById(R.id.icon) as ImageView // ちょっと遅い
- holder.textView = convertView!!.findViewById(R.id.text) as TextView // ちょっと遅い
+ holder = ViewHolder(convertView.findViewById(R.id.text) as TextView, convertView.findViewById(R.id.icon) as ImageView)

Kotlin Android ExtensionによるfindViewByIdのwrapperを使う

- holder = ViewHolder(convertView.findViewById(R.id.text) as TextView, convertView.findViewById(R.id.icon) as ImageView)
+ holder = ViewHolder(convertView.text, convertView.icon)

いちいち、一次変数を使いたくない

also

// convertViewがなかったら、xmlからViewを作る
- view = LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null)
- view.tag = ViewHolder(it.text, it.icon)
+ view = LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null).also {
+     it.tag = ViewHolder(it.text, it.icon)
+ }

run

// データをViewに反映する
- val data = getItem(position)
- holder.imageView!!.setImageResource(data.imageId)
- holder.textView!!.setText(data.textId)
+ getItem(position).run {
+     holder.imageView.setImageResource(imageId)
+     holder.textView.setText(textId)
+ }

ifは式なので、直接代入する

- var view: View
- if (convertView == null) {
    // convertViewがなかったら、xmlからViewを作る
-     view = LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null).also {
+ var view: View = if (convertView == null) {
+     LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null).also { 
          // パフォーマンスのため、各sub viewをHolderに保持し、Holder自体もViewに保持しておく
          it.tag = ViewHolder(it.text, it.icon)
      }
  } else {
      // convertViewがあれば、再利用する。
-     view = convertView
+     convertView
  }

?: 演算子で、if-nullをなくす

- var view: View = if (convertView == null) {
-     // convertViewがなかったら、xmlからViewを作る
-     LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null).also {
+ var view: View = convertView ?: LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null).also {
          // パフォーマンスのため、各sub viewをHolderに保持し、Holder自体もViewに保持しておく
          it.tag = ViewHolder(it.text, it.icon)
      }
- } else {
-     // convertViewがあれば、再利用する。
-     convertView
  }

元のJavaコード

static class ViewHolder {
    TextView textView;
    ImageView imageView;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Viewを準備する
    ViewHolder holder;
    if (convertView == null) {
        // convertViewがなかったら、xmlからViewを作る
        convertView = LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null);

        // パフォーマンスのため、各sub viewをHolderに保持し、Holder自体もViewに保持しておく
        holder = new ViewHolder();
        holder.imageView = (ImageView) convertView.findViewById(R.id.icon); // ちょっと遅い
        holder.textView = (TextView) convertView.findViewById(R.id.text); // ちょっと遅い
        convertView.setTag(holder);
    } else {
        // convertViewがあれば、再利用する。
        holder = (ViewHolder) convertView.getTag();
    }

    // データをViewに反映する
    Data data = getItem(position);
    holder.imageView.setImageResource(data.imageId);
    holder.textView.setText(data.textId);

    return convertView;
}

書き換えたKotlinコード

data class ViewHolder(val textView: TextView, val imageView: ImageView)

override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
    // Viewを準備する
    val view: View = convertView ?: LayoutInflater.from(mContext).inflate(R.layout.dialog_grid_menu_item, null).also {
        // パフォーマンスのため、各sub viewをHolderに保持し、Holder自体もViewに保持しておく
        it.tag = ViewHolder(it.text, it.icon)
    }

    // データをViewに反映する
    (view.tag as ViewHolder).let { (textView, imageView) ->
        getItem(position).run {
            textView.setText(textId)
            imageView.setImageResource(imageId)
        }
    }

    return view
}

thanks

13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11