添加工厂时出现 Moshi ArrayOutOfBoundsException
Moshi ArrayOutOfBoundsException when adding factory
我有时在打开应用程序时发现与 Moshi 相关的异常:
Caused by java.lang.ArrayIndexOutOfBoundsException: length=33; index=33
at java.util.ArrayList.add(ArrayList.java:468)
at com.squareup.moshi.Moshi$Builder.add(Moshi.java:231)
我们在 BaseApplication 中初始化一个存储库,这有时会导致初始化 Moshi 时提到的崩溃。我在应用程序报告中发现了这个错误,但我无法重现它。让我们跳转到我们拥有的内容,看看您是否有线索。
此工厂用于创建 Moshi 实例,添加 KotlinJsonAdapterFactory 时发生崩溃:
object MyMoshiConverterFactory {
fun create(setup: (Moshi.Builder.() -> Unit)? = null): Converter.Factory {
val moshi = MoshiUtil.createMoshi()
setup?.let { moshi.it() }
moshi.add(KotlinJsonAdapterFactory()) // Here is the crash!
return MoshiConverterFactory.create(moshi.build())
}
}
这里我们有一个 class ,其中有我们使用的所有转换器。它确实有更多的转换器,但为了简单起见,我删除了其中的一些:
object MoshiUtil {
private val lazyMoshi by lazy {
Moshi.Builder().apply {
add(DateAdapter())
add(DefaultOnDataMismatchAdapter.newFactory(FeedItem::class.java, null))
add(SkipListNullValuesAdapter.createFactory(Element::class.java))
add(SkipListNullValuesAdapter.createFactory(Post::class.java))
add(SkipListNullValuesAdapter.createFactory(MetadataItem::class.java))
add(GeoGeometry::class.java, GeometryAdapter())
}
}
fun createMoshi() = lazyMoshi
}
最后,在我们的 BaseApplication 中,我们有这样的东西:
class BaseApplication {
@Override
public void onCreate() {
super.onCreate();
val myService = getMyService(applicationContext)
}
private fun getMyService(appContext: Context): MyService {
val converterFactory = MyMoshiConverterFactory.create()
return Retrofit.Builder().baseUrl(baseUrl).apply {
addConverterFactory(converterFactory)
client(okHttpClientBuilder.build())
}.build().create(MyService::class.java)
}
}
}
那么,您是否看到任何可能导致它的原因?当应用程序中的多个位置同时创建 MoshiUtils 对象时,您认为这可能是在启动时发生的并发问题吗?期待收到你们的来信,谢谢!
Moshi.Builder
是可变的并且不是线程安全的,因此您有时遇到的这个错误是竞争条件的结果。您应该在该基础 MoshiUtil
实例上调用 .build()
以获得不可变的 Moshi
实例,然后使 MoshiUtil.createMoshi
的 return 值为 moshi.newBuilder()
(创建一个 Moshi.Builder
已经像现有的 Moshi
实例一样配置),像这样:
object MoshiUtil {
private val baseMoshi: Moshi = Moshi.Builder().apply {
// ...
}.build()
fun createMoshi(): Moshi.Builder = baseMoshi.newBuilder()
}
因为每个调用 createMoshi
的人现在都有自己的 Moshi.Builder
实例,所以应该不会再有任何并发问题了。
我有时在打开应用程序时发现与 Moshi 相关的异常:
Caused by java.lang.ArrayIndexOutOfBoundsException: length=33; index=33
at java.util.ArrayList.add(ArrayList.java:468)
at com.squareup.moshi.Moshi$Builder.add(Moshi.java:231)
我们在 BaseApplication 中初始化一个存储库,这有时会导致初始化 Moshi 时提到的崩溃。我在应用程序报告中发现了这个错误,但我无法重现它。让我们跳转到我们拥有的内容,看看您是否有线索。
此工厂用于创建 Moshi 实例,添加 KotlinJsonAdapterFactory 时发生崩溃:
object MyMoshiConverterFactory {
fun create(setup: (Moshi.Builder.() -> Unit)? = null): Converter.Factory {
val moshi = MoshiUtil.createMoshi()
setup?.let { moshi.it() }
moshi.add(KotlinJsonAdapterFactory()) // Here is the crash!
return MoshiConverterFactory.create(moshi.build())
}
}
这里我们有一个 class ,其中有我们使用的所有转换器。它确实有更多的转换器,但为了简单起见,我删除了其中的一些:
object MoshiUtil {
private val lazyMoshi by lazy {
Moshi.Builder().apply {
add(DateAdapter())
add(DefaultOnDataMismatchAdapter.newFactory(FeedItem::class.java, null))
add(SkipListNullValuesAdapter.createFactory(Element::class.java))
add(SkipListNullValuesAdapter.createFactory(Post::class.java))
add(SkipListNullValuesAdapter.createFactory(MetadataItem::class.java))
add(GeoGeometry::class.java, GeometryAdapter())
}
}
fun createMoshi() = lazyMoshi
}
最后,在我们的 BaseApplication 中,我们有这样的东西:
class BaseApplication {
@Override
public void onCreate() {
super.onCreate();
val myService = getMyService(applicationContext)
}
private fun getMyService(appContext: Context): MyService {
val converterFactory = MyMoshiConverterFactory.create()
return Retrofit.Builder().baseUrl(baseUrl).apply {
addConverterFactory(converterFactory)
client(okHttpClientBuilder.build())
}.build().create(MyService::class.java)
}
}
}
那么,您是否看到任何可能导致它的原因?当应用程序中的多个位置同时创建 MoshiUtils 对象时,您认为这可能是在启动时发生的并发问题吗?期待收到你们的来信,谢谢!
Moshi.Builder
是可变的并且不是线程安全的,因此您有时遇到的这个错误是竞争条件的结果。您应该在该基础 MoshiUtil
实例上调用 .build()
以获得不可变的 Moshi
实例,然后使 MoshiUtil.createMoshi
的 return 值为 moshi.newBuilder()
(创建一个 Moshi.Builder
已经像现有的 Moshi
实例一样配置),像这样:
object MoshiUtil {
private val baseMoshi: Moshi = Moshi.Builder().apply {
// ...
}.build()
fun createMoshi(): Moshi.Builder = baseMoshi.newBuilder()
}
因为每个调用 createMoshi
的人现在都有自己的 Moshi.Builder
实例,所以应该不会再有任何并发问题了。