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

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

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

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

Kotlin

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

Q&A

解決済

1回答

1667閲覧

Gildeライブラリーを利用したアイコンの表示

yu9718s

総合スコア9

Android

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

Kotlin

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

0グッド

0クリップ

投稿2020/06/01 03:05

前提・実現したいこと

APIを利用して取得したデータをRecyclerViewで表示したいのですが、
アイコンの表示がうまくできません。
アイコンを表示させるためにGlideライブラリーを利用して表示させようとしておりましたが、エラーが発生してしまいました。

発生している問題・エラーメッセージ

E/AndroidRuntime: FATAL EXCEPTION: main
Process: jp.co.stv_tech.kotlin232, PID: 28616
java.lang.NullPointerException: Argument must not be null
at com.bumptech.glide.util.Preconditions.checkNotNull(Preconditions.java:29)
at com.bumptech.glide.util.Preconditions.checkNotNull(Preconditions.java:23)
at com.bumptech.glide.RequestBuilder.into(RequestBuilder.java:669)
at jp.co.stv_tech.kotlin232.MainActivity$WeatherInfoReceiver.onPostExecute(MainActivity.kt:155)
at jp.co.stv_tech.kotlin232.MainActivity$WeatherInfoReceiver.onPostExecute(MainActivity.kt:113)
at android.os.AsyncTask.finish(AsyncTask.java:695)
at android.os.AsyncTask.access$600(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

import android.annotation.SuppressLint import android.graphics.Color import android.os.AsyncTask import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.google.android.material.appbar.CollapsingToolbarLayout import kotlinx.android.synthetic.main.row.* import org.json.JSONObject import java.io.BufferedReader import java.io.InputStream import java.io.InputStreamReader import java.net.HttpURLConnection import java.net.URL class MainActivity : AppCompatActivity() { val weatherList: MutableList<MutableMap<String, String>> = mutableListOf() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Log.i("MainActivity", "onCreate") val toolbar = findViewById<Toolbar>(R.id.toolbar) toolbar.setLogo(R.mipmap.ic_launcher) setSupportActionBar(toolbar) val toolbarLayout = findViewById<CollapsingToolbarLayout>(R.id.toolbarLayout) toolbarLayout.title = getString(R.string.toolbar_title) toolbarLayout.setExpandedTitleColor(Color.WHITE) toolbarLayout.setCollapsedTitleTextColor(Color.LTGRAY) val lvWeatherList = findViewById<RecyclerView>(R.id.lvWeatherList) val layout = LinearLayoutManager(applicationContext) lvWeatherList.layoutManager = layout val weatherList = createWeatherList() val adapter = RecyclerListAdapter(weatherList) lvWeatherList.adapter = adapter val decorator = DividerItemDecoration(applicationContext, layout.orientation) lvWeatherList.addItemDecoration(decorator) //val url = "https://i.picsum.photos/id/777/400/500.jpg" //Glide.with(this).load(url).into(lvImage) } public override fun onStart() { Log.i("MainActivity", "onStart") val receiver = WeatherInfoReceiver() receiver.execute("130010") super.onStart() } private fun createWeatherList():MutableList<MutableMap<String,String>> { Log.i("MainActivity", "createWeatherList") return weatherList } private inner class RecyclerListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){ var tvWeatherDesc: TextView = itemView.findViewById(R.id.tvWeatherDesc) var tvWeatherDate: TextView = itemView.findViewById(R.id.tvWeatherDate) var tvWeather: TextView = itemView.findViewById(R.id.tvWeather) var lvImage: ImageView = itemView.findViewById(R.id.lvImage) } private inner class RecyclerListAdapter(private val _listData: MutableList<MutableMap<String, String>>): RecyclerView.Adapter<RecyclerListViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerListViewHolder { Log.i("MainActivity", "onCreateViewHolder") val inflater = LayoutInflater.from(applicationContext) val view = inflater.inflate(R.layout.row, parent, false) return RecyclerListViewHolder(view) } override fun onBindViewHolder(holder: RecyclerListViewHolder, position: Int) { Log.i("MainActivity", "onBindViewHolder") val item = _listData[position] Log.i("MainActivity", "$position") val description = item["description"] as? String val date = item["date"] as? String val telop = item["telop"] as? String val image = item["image"] as? String holder.tvWeatherDesc.text = description holder.tvWeatherDate.text = date holder.tvWeather.text = telop // holder.lvImage.imageview = image } override fun getItemCount(): Int { Log.i("MainActivity", "getItemCount") return _listData.size } } @SuppressLint("StaticFieldLeak") private inner class WeatherInfoReceiver(): AsyncTask<String, String, String>() { override fun doInBackground(vararg params: String): String { Log.i("MainActivity", "doInBackground") val id = params[0] val urlStr = "http://weather.livedoor.com/forecast/webservice/json/v1?city=${id}" val url = URL(urlStr) val con = url.openConnection() as HttpURLConnection con.requestMethod = "GET" con.connect() val stream = con.inputStream val result = is2String(stream) con.disconnect() stream.close() return result } override fun onPostExecute(result: String) { Log.i("MainActivity", "onPostExecute") val rootJSON = JSONObject(result) val forecasts = rootJSON.getJSONArray("forecasts") val description = rootJSON.getJSONObject("description") Log.i("MainActivity", "description:$description") for (i in 0..1) { val forecastsNow = forecasts.getJSONObject(i) Log.i("MainActivity", "${i}") val telop = forecastsNow.getString("telop") Log.i("MainActivity", "telop:$telop") val date = forecastsNow.getString("date") Log.i("MainActivity", "date:$date") val image = forecastsNow.getJSONObject("image") Log.i("MainActivity", "image:$image") val url = image.getString("url") Log.i("MainActivity", "url:$url") Glide.with(this@MainActivity).load(url).into(lvImage) val weather = mutableMapOf("telop" to telop, "date" to date, "url" to url) weatherList.add(weather) } } } private fun is2String(stream: InputStream): String { Log.i("MainActivity", "is2String") val sb = StringBuilder() val reader = BufferedReader(InputStreamReader(stream, "UTF-8")) var line = reader.readLine() while (line != null) { sb.append(line) line = reader.readLine() } reader.close() return sb.toString() } }

該当のソースコード

kotlin

試したこと

上記にも記載しましたが、Glideライブラリーを試しました。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

hoshi-takanori

2020/06/01 07:57 編集

エラーメッセージを見ると into の引数、つまり lvImage が null だと言ってますね。 import kotlinx.android.synthetic.main.row.* がどういう意味がご存知ですか?
yu9718s

2020/06/01 08:23

ご返信ありがとうございます。 先ほど調べてみたのですが、ソースコード中で直接書き換えができるとありました。しかし、あまりイメージができず、理解できておりません。
yu9718s

2020/06/02 08:22 編集

@hoshi-takanoriさん さらに調べてみて、findViewByIdを使わずにコードから要素を参照できると認識しました。 そのためlvImage.load(url)やlvImage.setImageResource(url)を試 してみましたが、上手くいきませんでした。 nullの対応策がまだよく理解できていないため解決にはいたりませんでした。 findViewByIdを使っていないのにどうしてエラーが発生しているのかが理解できていないので、その点についてご教示いただけますでしょうか。
guest

回答1

0

ベストアンサー

エラーの直接の原因は、inner class WeatherInfoReceiver の onPostExecute で呼んでいる Glide の into メソッドの引数 lvImage が null ってことです。この lvImage ですが、WeatherInfoReceiver では特に変数として定義してないので、import を確認すると

Kotlin

1import kotlinx.android.synthetic.main.row.*

とあるので、おそらく Kotlin の synthetic import 機能で自動生成されているものと思われます。
参考: Android + Kotlin で findViewById が不要だった | なんや書くところ

これは、import 文を書くことによって findVieById しなくても layout xml で指定した id を変数名としてそのまま使えるという便利なものですが、基本的には Activity の中で使うことを前提としているため、RecyclerView 用と思われる layout/row.xml に対して使うと目的のビューが取得できずに null になってしまいます。

とりあえず、以下の修正で動くのでは。

diff

1 // synthetic import を削除 2-import kotlinx.android.synthetic.main.row.* 3 4 class MainActivity : AppCompatActivity() { 5 val weatherList: MutableList<MutableMap<String, String>> = mutableListOf() 6 // adapter のメソッドを呼びたいので、プロパティにしておく。 7+ private val adapter = RecyclerListAdapter(weatherList) 8 9 override fun onCreate(savedInstanceState: Bundle?) { 10 // 略 11 12 val layout = LinearLayoutManager(applicationContext) 13 lvWeatherList.layoutManager = layout 14 // adapter をプロパティに変更したので、これは不要。 15- val weatherList = createWeatherList() 16- val adapter = RecyclerListAdapter(weatherList) 17 lvWeatherList.adapter = adapter 18 19 // 略 20 } 21 22 // 略 23 24 private inner class RecyclerListAdapter(private val _listData: MutableList<MutableMap<String, String>>): 25 RecyclerView.Adapter<RecyclerListViewHolder>() { 26 27 override fun onBindViewHolder(holder: RecyclerListViewHolder, position: Int) { 28 // 略 29 30 // 前回の設定内容があれば、それをクリア。 31+ Glide.with(this@MainActivity).clear(holder.lvImage) 32 33 // 画像の読み込みはここで行う。 34+ val url = item["url"] as? String 35+ Glide.with(this@MainActivity).load(url).into(holder.lvImage) 36 } 37 38 // 略 39 40 @SuppressLint("StaticFieldLeak") 41 private inner class WeatherInfoReceiver(): AsyncTask<String, String, String>() { 42 override fun doInBackground(vararg params: String): String { 43 44 // 略 45 46 override fun onPostExecute(result: String) { 47 // 略 48 49 // この時点では lvImage は存在しないので、削除。 50- Glide.with(this@MainActivity).load(url).into(lvImage) 51 52 // ここで item["url"] に値を設定しているので、onBindViewHolder でそれを利用。 53 val weather = mutableMapOf("telop" to telop, "date" to date, "url" to url) 54 weatherList.add(weather) 55 } 56 57 // weatherList が更新されたので、lvWeatherList の表示を更新する。 58+ adapter.notifyDataSetChanged() 59 } 60 }

投稿2020/06/02 15:50

hoshi-takanori

総合スコア7895

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

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

yu9718s

2020/06/03 00:47

import kotlinx.android.synthetic.main.row.*に対するご説明ありがとうございます。xmlで指定したIDを使えるという点はなんとなく理解していたつもりになっていました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問