提问人:Gabs 提问时间:5/2/2022 最后编辑:Gabs 更新时间:5/3/2022 访问量:796
使用 Kotlin 读取大型 (+- 50Mb) Json 文件
Read large (+- 50Mb) Json file using Kotlin
问:
我开始使用“openweathermap.org”API 开发天气应用程序,它们以 Json 格式为您提供可用城市列表。
在我继续这个项目之前,我希望能够处理这个 Json 文件中的数据。
问题是每当我尝试读取和解析该文件时,我都会得到 Null。
代码如下:
主要活动:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val jsonFileString = getJsonDataFromAsset(applicationContext, "citylist.json")
Log.i("gabs Data", jsonFileString ?: "Empty Data")
val gson = Gson()
val listOfCities = object : TypeToken<List<CityList>>() {}.type
var cities: List<CityList> = gson.fromJson(jsonFileString, listOfCities)
cities.forEachIndexed { idx, city -> Log.i("data", "> Item $idx:\n$city") }
}
}
Utils.kt:
fun getJsonDataFromAsset(context: Context, fileName: String): String? {
val jsonString: String
try {
jsonString = context.assets.open(fileName).bufferedReader().use { it.readText() }
} catch (ioException: IOException) {
ioException.printStackTrace()
return null
}
return jsonString
}
和数据类(城市数据数组):
class CityList : ArrayList<CityList.CityListItem>(){
data class CityListItem(
@SerializedName("coord")
val coord: Coord,
@SerializedName("country")
val country: String,
@SerializedName("id")
val id: Double,
@SerializedName("name")
val name: String,
@SerializedName("state")
val state: String
) {
data class Coord(
@SerializedName("lat")
val lat: Double,
@SerializedName("lon")
val lon: Double
)
}
}
和错误:
java.lang.RuntimeException:无法启动活动 ComponentInfo{com.example.weatherdisplay/com.example.weatherdisplay.ui.activities.MainActivity}:java.lang.NullPointerException:gson.fromJson(jsonFileString, listOfCities) 不得为空。
原因:java.lang.NullPointerException:gson.fromJson(jsonFileString, listOfCities) 不得为空 在 com.example.weatherdisplay.ui.activities.MainActivity.onCreate(MainActivity.kt:21)
答:
您的代码中存在一些问题:
- 您没有关闭
BufferedReader
- 您不应该在主线程上加载文件,因为它会阻止 UI
我创建了一些与您的数据结构相对应的示例数据:
[
{
"id": 1,
"country": "Germany",
"state": "Saxony",
"name": "Dresden",
"coord": {
"lat": 0.0,
"lon": 0.0
}
},
{
"id": 2,
"country": "Germany",
"state": "Berlin",
"name": "Berlin",
"coord": {
"lat": 0.0,
"lon": 0.0
}
},
{
"id": 3,
"country": "Germany",
"state": "Baden-Wuerttemberg",
"name": "Stuttgart",
"coord": {
"lat": 0.0,
"lon": 0.0
}
},
{
"id": 4,
"country": "Germany",
"state": "Hessen",
"name": "Frankfurth",
"coord": {
"lat": 0.0,
"lon": 0.0
}
},
{
"id": 5,
"country": "Germany",
"state": "Nordrhine-Westphalia",
"name": "Cologne",
"coord": {
"lat": 0.0,
"lon": 0.0
}
}
]
您的活动:
class MainActivity : AppCompatActivity() {
companion object {
const val TAG = "MyApplication"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launchWhenStarted {
launch(Dispatchers.IO) {
var reader: BufferedReader? = null
try {
// Create a reader and read the file contents
reader = assets.open("data.json").bufferedReader()
val rawData = reader.use { it.readText() }
// Create a Type token that Gson knows how to parse the raw data
val cityListType = object : TypeToken<List<City>>() {}.type
// Parse the raw data using Gson
val data: List<City> = Gson().fromJson(rawData, cityListType)
// TODO: Do something with the data
} catch (e: IOException) {
// Handle IOException: Gets thrown when the file wasn't found or something similar
Log.e(TAG, "An error occurred while reading in the data:", e)
} catch (e: JsonParseException) {
// Handle JsonParseException: Gets thrown when there is a problem with the contents of the file
Log.e(TAG, "An error occurred while reading in the data:", e)
}
finally {
// Close the reader to release system resources
reader?.close()
}
}
}
}
}
您的数据结构:
data class City(
@SerializedName("id")
val id: Int,
@SerializedName("country")
val country: String,
@SerializedName("state")
val state: String,
@SerializedName("name")
val name: String,
@SerializedName("coord")
val coordinate: Coordinate
) {
override fun toString(): String {
return "#$id[$name $state $country]@[${coordinate.lat}|${coordinate.lon}]"
}
}
data class Coordinate(
@SerializedName("lat")
val lat: Double,
@SerializedName("lon")
val lon: Double
)
在最好的情况下,您可以将获取文件内容并解析数据的代码放在 中,但这超出了此答案的范围。ViewModel
其他信息: https://developer.android.com/topic/libraries/architecture/viewmodelViewModels
评论
jsonFileString
gson.fromJson