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

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

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

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

Kotlin

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

Q&A

解決済

2回答

4758閲覧

Roomを用いてDB接続を行い、adapterにセットし、ListViewに表示できない

negoto

総合スコア13

Android

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

Kotlin

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

0グッド

0クリップ

投稿2020/01/25 05:00

Roomを用いてDB接続を行い、取得結果をArrayAdapterにセットし、ListViewに表示しようとしていますができません。
ソースコードは以下になります。

Kotlin

1class ResultActivity : AppCompatActivity() { 2 companion object { 3 lateinit var database: ResultRoomDatabase 4 } 5 override fun onCreate(savedInstanceState: Bundle?) { 6 super.onCreate(savedInstanceState) 7 setContentView(R.layout.result) 8 9 database = Room.databaseBuilder(this, ResultRoomDatabase::class.java, "kotlin_room_sumple.db").build() 10 11 //戻るオブジェクト取得 12 val btBack = findViewById<Button>(R.id.btBack) 13 14 //エラー箇所--- 15 GlobalScope.launch(Dispatchers.Unconfined){ 16 val arrayAapter: ArrayAdapter<Result> = ArrayAdapter(this, android.R.layout.simple_list_item_1, create()) 17 result.adapter = arrayAapter 18 } 19 //---ここまでエラー 20 result.adapter = adapter 21 22 } 23 24 fun create(): List<Result> { 25 val dao = database.resultDao() 26 dao.insertAll(Result(0, "09:00", "17:30", 8, "2020/01/23", 1)) 27 var resultList: List<Result> = dao.getAll() 28 return resultList 29 } 30 31 fun onBack(view: View){ 32 finish() 33 } 34 35 override fun onDestroy() { 36 super.onDestroy() 37 } 38}

GlobalScope内のadapterでエラーが以下のエラーが出ます。
None of the following functions can be called with the arguments suplied
GlobalScope内ではArrayAdapterをセットする方法を教えてください。

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

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

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

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

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

kakajika

2020/01/26 08:32

いくつかツッコミどころがありそうなコードですが、何を参考にコードを書かれているのでしょうか?
negoto

2020/01/27 00:35

Roomに関しては、Android developerのRoomを用いてDB接続を行うと、個人サイトのRoomでDB管理をするを参考にしました。
kakajika

2020/01/27 10:18

なるほど。。ご質問のコードで気になったのは主にcoroutines関連のところだったのですが、参考にされた個人サイトをちらっと見た感じだとRoomの実装にも問題がありそうですね。そのサイトの情報はあまり参考にしない方が良いかもしれません。
guest

回答2

0

スマホからの操作でミス

投稿2020/01/28 05:04

編集2020/01/28 05:07
negoto

総合スコア13

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

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

0

ベストアンサー

  • まず、エラーの原因について

ArrayAdapterの第1引数に渡しているthisがCoroutineScopeを指してしまっているので、Activityを指すように修正してみてください。

kotlin

1val arrayAapter = ArrayAdapter(this@ResultActivity, ...)

おそらくこれでエラーは消えると思います。
ただし、他の箇所にいくつか問題があるので以下参考にしてください。


  • Roomの実行スレッドについて

ご提示のコードを拝見する限りでは、Daoの各メソッドをメインスレッド上で行うようになっていて、アプリを実行すると落ちるはずです。Roomはデフォルトではメインスレッド上での処理を許可しないので、非同期で実行する必要があります。coroutinesをお使いなら、Roomのcoroutinesサポート androidx.room:room-ktx を利用して各メソッドをsuspend関数にするのが一番シンプルで効率的な方法です。

もしくは、次の例のように自前で非同期処理を行ってその中で各メソッドを呼ぶようにします。

kotlin

1suspend fun create(): List<Result> { 2 return withContext(Dispatchers.IO) { 3 val dao = database.resultDao() 4 dao.insertAll(Result(0, "09:00", "17:30", 8, "2020/01/23", 1)) 5 dao.getAll() 6 } 7}

LiveDataを使う方法もありますが、ここでは割愛します。


  • CoroutineScopeとCoroutineContextについて

Activity内でコルーチンを立ち上げる場合、GlobalScopeは使うべきではありません。ドキュメントにも書かれている通り、Activityのライフサイクルに準じたスコープを利用するべきです。ご質問のコードでは、コルーチン内でActivityやViewを参照してしまっているので、最悪Activityがリークします。

また、CoroutineContextにDispatchers.Uncofinedを指定していますが、これは挙動が少しややこしいdispatcherなので、Dispatchers.Mainなどを指定した方が動作が明確になります。

MainScopeを利用するとこれら2つの問題を一緒に解決できるのでおすすめです。androidx.lifecycleを導入済みなら、LifecycleScopeを使うとさらにシンプルに書けます。

投稿2020/01/27 11:26

編集2020/01/28 01:46
kakajika

総合スコア3131

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

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

negoto

2020/01/28 05:05

拙いコードを読み取りアドバイスありがとうございます。 今__イタリックテキスト__出先で試せないので帰宅したら試してみます。 以下疑問点になります。 Roomはデフォルトではメインスレッドで行えないのはコルーチン内ならメインでも行えるということですか? そうでないなら、Dispatchers.MainもMainScopeもとちらもメインスレッド?で行うのでできないのではと思っています。 まだまだ始めたばかりでわからないことが多いので参考になるサイトなどを教えてもらえませんか?
negoto

2020/01/28 10:22

ArrayAdapterの引数のcontextをthis@ResultActivityにしたらエラーはなくなりました。動かしたら、データ取得する際に今度はUserRecoverableAuthIOExcaptなるエラーが生じエラー落ちしました。(今回の問題とは別なので置いておきます…) 今後はDAOの各メソッドをsuspend修飾子を付け、GlobalScopeをMainScopeに変えて試していきます。 最後にもう一つ質問なのですが、ArrayAdapterのcontext引数をthis@ResultActivityにしたのですか?Contextを渡すものだと認識しています。 回答ありがとうございました、とても助かりました。
kakajika

2020/01/28 11:31

> Roomはデフォルトではメインスレッドで行えないのはコルーチン内ならメインでも行えるということですか? いえ、コルーチン内でもメインスレッドからアクセスした場合は落ちます。Daoのメソッドをsuspend関数にした場合は、アクセス時に自動的にCoroutineContextが切り替わり別スレッドからのアクセスとなるので落ちません。回答に書いた方法のように自前でCoroutineContextを切り替えた場合も同様です。 > そうでないなら、Dispatchers.MainもMainScopeもとちらもメインスレッド?で行うのでできないのではと思っています。 Dispatchers.Mainを指定するのはコルーチンをlaunchする際のCoroutineContextです。Roomへアクセスする際に別のDispatcherを指定したCoroutineContextに切り替わっていれば問題ありません。 > 最後にもう一つ質問なのですが、ArrayAdapterのcontext引数をthis@ResultActivityにしたのですか?Contextを渡すものだと認識しています。 ActivityはContextを継承しています。 もちろん、Activityを直接参照せずにViewなどからContextを取得して渡すようにしてもOKです。
kakajika

2020/01/28 11:51 編集

> まだまだ始めたばかりでわからないことが多いので参考になるサイトなどを教えてもらえませんか? うーん、すみません。。入門者向けのサイトについてはあまり詳しくなくてわかりません。個人サイトよりは公式ドキュメントの方を参考にすべきと思います。 Androidアプリでのcoroutinesの利用についてはCodelabsの日本語訳を見つけたので参考にどうぞ。 https://droidkaigi.github.io/codelabs-kotlin-coroutines-ja/
negoto

2020/01/28 13:24

スレッドを変えているのではなくCoroutineContextを変えることが重要と理解しました。 参考サイトもありがとうございます。 大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問