android - 添加工厂时出现Moshi ArrayOutOfBoundsException

标签 android kotlin moshi

打开应用程序时,有时会发现与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())
    }
}

在这里,我们有一个我们拥有所有使用的转换器的类。它确实有很多转换器,但是为了简单起见,我删除了其中的一些转换器:
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是可变的,并且不是线程安全的,因此,您有时会遇到的此错误是竞争情况。您应该在该基础.build()实例上调用MoshiUtil以获得不可变的Moshi实例,然后使MoshiUtil.createMoshi的返回值为moshi.newBuilder()(创建已经像现有Moshi.Builder实例一样配置的Moshi),如下所示:

object MoshiUtil {
    private val baseMoshi: Moshi = Moshi.Builder().apply {
        // ...
    }.build()

    fun createMoshi(): Moshi.Builder = baseMoshi.newBuilder()
}

由于现在每个调用createMoshi的人都拥有自己的Moshi.Builder实例,因此不再存在任何并发问题。

关于android - 添加工厂时出现Moshi ArrayOutOfBoundsException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60756382/

相关文章:

android - 找不到字段的 setter - 将 Kotlin 与 Room 数据库结合使用

android - 改造响应问题

generics - 具有 kotlin 泛型的 Moshi 为接口(interface)抛出 No JsonAdapter

java - Moshi 多个自定义名称

android - 如何从 json 数组中检索数据

Android GZIP解压结果被截断

android - 以编程方式在 framelayout 中的 imageview 上覆盖文本 - Android

android - 在EditText后隐藏提示不为null

java - Java+kotlin项目中moshi的正确使用方法

Android - 隐藏 API clientId 和 clientSecret 的最佳方式