質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

1回答

1400閲覧

取得したアダプターの型チェックやキャストをする方法

tokumei000

総合スコア17

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2020/03/02 12:01

前提・実現したいこと

ListViewがあり、文字列を格納したリストとArrayAdapterで連携しているとします。
また、ListViewの項目をタップした際にアイテムを削除して画面を更新するとします。

上記を実現するために、リスナを設定する際にアダプターを取得し処理を記述する必要があるのですが、取得したアダプターの型のチェックやキャストをする正しい方法がわかりません。

asを用いて型変換を行うとコンパイルは通り、アプリは正常に動作するのですが以下の警告が出ます。

警告

Unchecked cast: Adapter! to ArrayAdapter<String>

もちろん最初にリストビューにリストを設定する際に宣言し使用したアダプターをリスナ内で使えば警告なしでコンパイルすることはできるのですが、リスナを設定する際にparent.adapterで取得したアダプターを使って記述する方法が知りたくて質問させていただきました。
よろしくおねがいします。

該当のソースコード

Kotlin

1class MainActivity : AppCompatActivity() { 2 3 override fun onCreate(savedInstanceState: Bundle?) { 4 super.onCreate(savedInstanceState) 5 setContentView(R.layout.activity_main) 6 7 val list = mutableListOf("アイテム1", "アイテム2", "アイテム3") 8 val adapter = ArrayAdapter<String>(applicationContext, android.R.layout.simple_list_item_1, list) 9 lv.adapter = adapter 10 11 lv.setOnItemClickListener { parent, view, position, id -> 12 val adapter = parent.adapter as ArrayAdapter<String> 13 adapter.remove(adapter.getItem(position)) 14 adapter.notifyDataSetChanged() 15 } 16 17 } 18 19}

試したこと

isを用いた場合は以下のエラーが出ました。parent.adapterの返り値がAdapter!のため中身の型情報を持っていないことが原因と考えられます。

Kotlin

1lv.setOnItemClickListener { parent, view, position, id -> 2 val adapter = parent.adapter 3 if(adapter is ArrayAdapter<String>) { 4 adapter.remove(adapter.getItem(position)) 5 adapter.notifyDataSetChanged() 6 } 7 }

エラー

Cannot check for instance of erased type

次にArrayAdapter<*>として型のチェックを行うとadapter.removeに渡す引数のところでエラー出ました。

Kotlin

1lv.setOnItemClickListener { parent, view, position, id -> 2 val adapter = parent.adapter 3 if(adapter is ArrayAdapter<*>) { 4 adapter.remove(adapter.getItem(position)) 5 adapter.notifyDataSetChanged() 6 } 7 }

エラー

Type mismatch: inferred type is Any! but Nothing! was expected. Projected type ArrayAdapter<*> restricts use of public open fun remove(@RecentlyNullable p0: T!): Unit defined in android.widget.ArrayAdapter

parent.adapterを使用する際、どのように実装すれば警告、エラー無しで実装できるのでしょうか?
それとも、そもそもリスナ設定内でparent.adapterを用いて処理を書くことが書き方的に間違っているのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2020/03/02 23:34

「アイテム」ってクラスではなく単なる文字列でしょうか? 余計なお世話ですが、ArrayAdapter は非常に単純な文字列のリストのためのものなので、普通は BaseAdapter のサブクラスを自作した方がいいと思います。
tokumei000

2020/03/03 13:49

単なる文字列です、分かりづらくて申し訳ありません。ご指摘ありがとうございます。
guest

回答1

0

tokumei000さんこんにちは。

お役に立たない意見かもしれませんがおっしゃる通り、

それとも、そもそもリスナ設定内でparent.adapterを用いて処理を書くことが書き方的に間違っているのでしょうか?

例内のような処理をparent.adapterでなければ実現できないようなユースケースが想定できません。
じゃあparent.adapterはどういうケースで使うのかと訊かれてしまうと、すぐには思いつかないのですが…

よくある似たケースとしては、以下の2つの関数は同じシグネチャを持つ関数としてコンパイルエラーになるというのがあるかもしれません。

Kotlin

1fun doSomething(list: ArrayList<String>) { 2} 3 4fun doSomething(list: ArrayList<Int>) { 5}

ArrayListになってしまうと、どのような型を格納していても内容そのものはAnyになってしまう(JavaではObject型)というケースに似ているのかも。

投稿2020/03/02 12:39

quadii.shii

総合スコア257

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tokumei000

2020/03/03 13:46

なるほど、わざわざparent.adapterとしてアダプタを取得し処理を記述することはほとんど無い感じなんですね、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問