¿Cómo tratar adecuadamente las dependencias de clase para utilizar la compilación incremental en Java / Android con Gradle?

Me mejoré nuestro sistema de compilación y activé compilaciones incrementales y compilación como se describe enest pregunta. Para mi decepción, la compilación incremental no mejoró los tiempos de compilación tanto como esperaba de leerGradles publicación de blog.

Después de algunas investigaciones, me di cuenta de que el problema es que, aunque solo agrego un comentario a una clase pequeña en algún lugar profundo de la aplicación, aparentemente se reconstruye casi toda la base de código. De hecho, en realidad no importa qué clase toco, Gradles--debug output revela que básicamente siempre recompila 476 clases.

ompilación incremental de 476 clases completadas en 12.51 segundos.

Mientras entiendo quepublic static constantes en el archivo modificado desencadenan una recompilación completa (que es solo un poco más lenta), no entiendo cómo dividir adecuadamente las dependencias de clase para que la compilación incremental realmente funcione. ¿Cuáles son las reglas exactas para determinar las dependencias de clase que afectan la compilación incremental? Podría leer sobre algunos ejemplosaqu, pero no parece aplicarse en absoluto a nuestro proyecto (bastante estándar).

Algunas de mis propias pruebas arrojaron lo siguiente:

// One of my main classes that has lots of class dependencies
public class A{
   public void foo() {
       // This line produces a dependency between A and B. So changing just
       // a comment in B triggers recompilation of all classes attached to A
       B b1 = new B(); 


   }
}

// A small helper class that I want to change
public class B {
   public void bar() {
       // This line does not create a dependency, so B can still be compiled by
       // itself. But usually, that's not the "common" direction you have.
       A a1 = new A();
       // I make the change here and then trigger a new build
   }
}

¿Por qué A necesita recompilación cuando se detalla una implementación, pero no cambia la interfaz de B?

Traté también de "esconderme" B detrás de una interfaz C. Pensé que esa sería la forma correcta (aunque a menudo muy engorrosa) de romper las dependencias. Pero resulta que no ayudó en absoluto.


public class A{
   public void foo() {
       C c1 = C.cFactory();
   }
}

public class B implements C {
   public void bar() {
       // I make the change here and then trigger a new build
   }
}

public interface C {
   void bar();

   public static C cFactory() {
       return new B();
   }
}

Me parece que tenemos este gran blob de dependencia y no estoy seguro de que esto pueda cambiarse razonablemente, aunque diría que tenemos una base de código razonablemente diseñada. ¿Existen mejores prácticas, pautas o patrones de diseño comunes entre los desarrolladores de Android que mejorarían efectivamente las compilaciones incrementales?

Me pregunto si otros tienen el mismo problema que nosotros y, si no, ¿qué hiciste?

Respuestas a la pregunta(1)

Su respuesta a la pregunta