Bug P3
Status Update
Comments
ae...@google.com <ae...@google.com> #2
Do you have a repro project that you could share with us?
There should be no need to excluding any dependencies: we automatically remove them from the test APK if they are in the main APK.
There should be no need to excluding any dependencies: we automatically remove them from the test APK if they are in the main APK.
Description
The getInstance() is a static method and it is being obfuscated by R8. However, Google is adding another APK(/data/app/androidx.test.tools.crawler) to the runtime classpath. If the crawler is before the app, that the IdlingRegistry classes get loaded from there instead of the app apk. and R8 modifies signature. Since the crawler apk has the original one, so the caller doesn't find the renamed method and cause the NoSuchMethodError exception.
import androidx.recyclerview.widget.AsyncDifferConfig
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.idling.concurrent.IdlingThreadPoolExecutor
import java.util.concurrent.Executor
import java.util.concurrent.SynchronousQueue
import java.util.concurrent.ThreadFactory
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
/**
* A [androidx.recyclerview.widget.ListAdapter] that uses [IdlingThreadPoolExecutor]
* as the background thread executor, which is synced with Espresso by default.
*
* Anyone needing a ListAdapter should use this [AsyncListAdapter] instead.
*
* Using explicitly qualified name for ListAdapter rather than using import to work around Detekt.
*/
abstract class AsyncListAdapter<Model, ViewHolder : RecyclerView.ViewHolder>(
diffCallback: DiffUtil.ItemCallback<Model>
) : androidx.recyclerview.widget.ListAdapter<Model, ViewHolder>(
AsyncDifferConfig.Builder(diffCallback)
.setBackgroundThreadExecutor(sharedIdlingExecutor)
.build()
) {
companion object {
private const val CORE_POOL_SIZE = 1
private const val MAXIMUM_POOL_SIZE = 20
private const val KEEP_ALIVE_SECONDS = 3L
private val threadFactory: ThreadFactory = object : ThreadFactory {
private val count = AtomicInteger(1)
override fun newThread(r: Runnable): Thread {
return Thread(r, "IdlingThread #" + count.getAndIncrement())
}
}
/**
* We are using androidx.test.espresso.idling.concurrent dependency here in the production code intentionally.
* Google says it is recommended approach.
*
*/
private val sharedIdlingExecutor: Executor = IdlingThreadPoolExecutor(
"AsyncListAdapter_IdlingThreadPoolExecutor",
CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE_SECONDS,
TimeUnit.SECONDS,
SynchronousQueue(),
threadFactory
)
}
}
The exception is as below
Fatal Exception: java.lang.NoSuchMethodError
No static method a()Landroidx/test/espresso/IdlingRegistry; in class Landroidx/test/espresso/IdlingRegistry; or its super classes (declaration of 'androidx.test.espresso.IdlingRegistry' appears in /data/app/androidx.test.tools.crawler-yW1gHKz27M9gGZ4XMDkIyw==/base.apk)
*****************************************************
Please use github issue tracker instead, unless this is an internal google specific issue
*****************************************************