Bloqueo de la aplicación en la creación de ViewModel sólo cuando minifyEnabled y con el ciclo de vida v 2.1.0

Mi aplicación se bloquea en el lanzamiento con un LinkageError a la hora de crear un modelo de vista el uso de lazy{}. El bloqueo sólo ocurre cuando:

  1. minifyEnabled se establece a true en construir.gradle, Y
  2. Yo uso la versión. 2.1.0 de ciclo de vida de los componentes. Funciona bien con lifecycle-2.0.0 minifyEnabled
    def lifecycle_version = '2.1.0'
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

También, el bloqueo es sólo pasando por uno de los modelos de vista. Otra vista de los modelos en la misma actividad que se tocan antes de esto, no estrellarse la aplicación.


El accidente ocurre en la segunda línea aquí:

    private val searchStackViewModel by lazy {
        ViewModelProviders.of(this)[SearchStateViewModel::class.java]
    }

El SearchStateViewModel es:

class SearchStateViewModel : ViewModel() {

    // Live data that initialises to empty stack with SearchStack.init
    private val privateStack = MutableLiveData<SearchStack>().apply {
        value = SearchStack()
    }

    // Observable view of search stack so it can't be directly modified
    internal val stateStack : LiveData<SearchStack> = privateStack

    /**
     * Add state to stack
     */
    fun add(searchState: SearchState) {
        val current = privateStack.value ?: SearchStack()
        current.add(searchState)
        privateStack.value = current
    }

    /**
     * Clear stack
     */
    fun clear() {
        val current = privateStack.value ?: SearchStack()
        current.clear()
        privateStack.value = current
    }

    /**
     * Clear stack, then add current state as the only state
     */
    fun clearThenAdd(searchState: SearchState) {
        val current = privateStack.value ?: SearchStack()
        current.clear()
        current.add(searchState)
        privateStack.value = current
    }

    /**
     * Get currentState search state, without changing the stack
     */
    fun currentState(): SearchState {
        return privateStack.value?.last() ?: SearchState()
    }

    /**
     * Return currentState search state, and remove it from the stack
     */
    fun pop(): SearchState {
        val current = privateStack.value ?: SearchStack()
        val poppedState = current.pop()
        privateStack.value = current
        return poppedState
    }
}

SearchStack es sólo un ArrayList:

class SearchStack : ArrayList<SearchState>() {

    init {
        add(SearchState())
    }


    fun pop(): SearchState = if (lastIndex > 0) removeAt(lastIndex) else last()


    override fun clear() {
        super.clear()
        add(SearchState())
    }


    override fun add(element: SearchState): Boolean {
        if (element == lastOrNull())
            return false
        return super.add(element)
    }
}

Y SearchState es una clase de datos:

@Parcelize
data class SearchState(
        val searchTerm: String = "",
        val isComplete: Boolean? = null,
        val dueOnly: Boolean = false,
        val aliveOnly: Boolean = true,
        val priority: Char? = null,
        val project: String? = null,
        val priorityMatchType: PriorityMatchType? = null,
        val name: String = "",
        val hideThresholdTasks: Boolean = true,
        val sortOrder: Int = -1,
        val sortOrderString: String? = null
                      ) : Parcelable {

    enum class PriorityMatchType {
        GREATOR,
        LESSOR,
        EXACT
    }

    enum class TaskState {
        DUE,
        PENDING,
        COMPLETED,
        ALL
    }

Stacktrace:

FATAL EXCEPTION: main
    Process: net.c306.ttsuper, PID: 7380
    java.lang.LinkageError: i.a.a.o.b
1 >>    at net.c306.ttsuper.view.ui.MainActivity$v.b(SourceFile:182)
        at net.c306.ttsuper.view.ui.MainActivity$v.b(SourceFile:159)
        at g.j.a(SourceFile:74)
        at net.c306.ttsuper.view.ui.MainActivity.F(SourceFile)
2 >>    at net.c306.ttsuper.view.ui.MainActivity.c(SourceFile:1839)
        at net.c306.ttsuper.view.ui.MainActivity.a(SourceFile:1993)
        at net.c306.ttsuper.view.ui.MainActivity.a(SourceFile:1967)
        at net.c306.ttsuper.view.ui.MainActivity.onCreate(SourceFile:386)
        at android.app.Activity.performCreate(Activity.java:6251)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
        at android.app.ActivityThread.-wrap11(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

La línea de la etiqueta (1) es el perezoso crear de ViewModel donde el accidente ocurre.
La línea de la etiqueta (2) es el primer acceso de ViewModel que inicia la creación perezosa:

val lastState = searchStackViewModel.currentState()
+1
2019-09-18 16:44:38
fuente
1 respuestas

Hay tres cuestiones a considerar.

Lo más significativo es que mysqldump no funcionan bien cuando se ejecuta a una distancia de la base de datos, debido a las limitaciones en la tradicional MySQL cliente/servidor de protocolo de cable, lo que hace que no hay margen para la canalización de una serie de comandos.

El mysqldump de la utilidad no utiliza la magia para generar los archivos de volcado -- emite instrucciones SQL para el servidor, y toma los resultados de esas consultas para generar su salida.

Como resultado, cada objeto individual (esquema, tabla, vista, almacenados función/procedimiento de evento) en la base de datos se requiere al menos un viaje ida y vuelta y a veces más de uno.

Para cada tabla, mysqldump primero las cuestiones de SHOW CREATE TABLE t1; seguido por SELECT * FROM t1; ... así que un viaje de ida y de tiempo de 100 ms significaría que la extracción de un archivo de volcado de 150 tablas significaría 150 × 2 × 0.100 = 30 segundos se desperdiciaron por la distancia entre el funcionamiento de la máquina de mysqldump y el servidor, y esto es cierto incluso si las tablas están vacías.

Esto es no una recomendación, pero usted puede tomar un vistazo a mydumper, que dice tener la capacidad de crear la copia de seguridad a través de múltiples conexiones de base de datos, en paralelo, y esto podría ayudar a mediar en los ciclos desperdiciado como los comandos de pasar al servidor y volver a el cliente, al paralelizar el proceso de volcado. No sé la calidad de esta base de código, pero algo como esto podría ayudar.


A continuación, casi siempre utilizar el --compress por mysqldump. Contrariamente a lo que se podría suponer, esto no comprimir el archivo de copia de seguridad. Generar el archivo de copia de seguridad es idéntica cuando se usa esta opción, pero cuando se activa esta función, el servidor comprime los datos que envía a mysqldump en el cable, y mysqldump descomprime los datos antes de escribir un vistazo -- por lo que esta opción casi siempre va a hacer para un proceso más rápido, a menos que el funcionamiento de la máquina de mysqldump y el servidor de base de datos están conectados por una baja latencia y alto ancho de banda de la red. Debido a que el archivo generado es idéntica, no hay problemas de compatibilidad cuando se utiliza esta opción.


Por último, hay un problema con el recién creado RDS servidores que usted necesita para tener en cuenta, de manera que no distorsione sus puntos de referencia. Cuando se crea un RDS de la réplica, es originalmente sembradas con datos a partir de una instantánea de la parte de arriba de maestro. Esto es, detrás de las escenas, una de instantáneas de EBS de la maestría en la unidad de disco duro, y la nueva instancia de base de datos está respaldado por un volumen de EBS restaurado a partir de la instantánea. Los volúmenes de EBS se perezosamente-cargado de la instantánea, por lo que se tiene documentado el primer toque de la pena. Este problema podría tener un impacto sustancial en el rendimiento de la primera copia de seguridad completa, pero no debería tener impacto significativo después de eso.

+0
2019-09-19 07:52:16