Making Android con Groovy(otra vez)

En las vísperas de la fecha en la que escribo este post, habíamos decidido entrar más de lleno con Android dentro del equipo de desarrollo, sin embargo, la convicción fue como siempre hacerlo de forma diferente, o por lo menos algo diferente con respecto a una industria que parecía siempre hacer lo mismo con lo mismo.

Es por ello que me gustaría escribirles al respecto de la experiencia que tuvimos usando Groovy en un proyecto Android, sé de antemano que la atención y los reflectores se encuentran en otros lenguajes, sin embargo, a nosotros nos ayudo muchísimo la la experiencia que teníamos con el lenguaje pero usándolo en otro contexto muy distinto, y aunque no escribiremos todo lo que hicimos en este post, si les comentaremos en algunos más que fue lo que hicimos y como nos beneficiamos.

Explicarles como agregamos el plugin de Groovy dentro de un proyecto Android está de más, pueden consultarlo directamente en su repositorio de GitHub. Lo que me gustaría mencionar es que ya está en una versión estable y confiable como para usarse.

La estructura de un proyecto

Al igual que un proyecto Android(Java), hay mucha similaridad integrando Groovy:

▾ app/
  ▾ src/
    ▾ main/
      ▾ groovy/com/makingdevs/mybarista/
        ▾ common/
            CamaraUtil.groovy
            ImageUtil.groovy
            LocationUtil.groovy
            SingleFragmentActivity.groovy
            WithFragment.groovy
        ▾ database/
        ▾ model/
          ▸ command/
          ▸ repository/
            Comment.groovy
            GPSLocation.groovy
            S3Asset.groovy
            User.groovy
        ▾ network/
          ▾ impl/
              RetrofitTemplate.groovy
            FoursquareRestOperations.groovy
            S3AssetRestOperations.groovy
            UserRestOperations.groovy
        ▾ service/
            CommentManager.groovy
            CommentManagerImpl.groovy
            FoursquareManager.groovy
            FoursquareManagerImpl.groovy
            S3assetManager.groovy
            S3assetManagerImpl.groovy
        ▾ ui/
          ▾ activity/
              PrincipalActivity.groovy
          ▾ adapter/
              CommentAdapter.groovy
              UserAdapter.groovy
          ▾ fragment/
              CameraFragment.groovy
              CommentsFragment.groovy
        ▾ view/
            CustomFontTextView.groovy
      ▸ res/
    app.iml
    proguard-rules.pro
▾ fastlane/
    Appfile
    Fastfile
  android_app.iml
  Gemfile
  Gemfile.lock
  gradle.properties
  gradlew*
  gradlew.bat
  local.properties
  README.md
  settings.gradle

Los modelos

La ventaja de los POGOS de Groovy se siente al declarar o instanciar algún objeto de dominio:

import groovy.transform.CompileStatic

@CompileStatic
class User {
    String id
    String username
    String token
}

Ahora instanciamos nuestra clase en cualquier parte:

User getUserSession(Context context) {
    SharedPreferences session = context.getSharedPreferences("UserSession",Context.MODE_PRIVATE)
    String username = session.getString("username",null);
    String token = session.getString("token",null)
    String id = session.getString("id",null)
    new User(username:username,token:token,id:id)
}

La nota importante aquí es la forma de la instanciación y que no hay palabra reservada return, al igual que la declaración del método como public no es necesaria. Además de que puedes llamar de forma abreviada a sus atributos.

@StaticCompile

Groovy es un lenguaje de tipado dinámico opcional, lo cuál significa que podemos beneficiarnos de ciertos elementos del lenguaje y estar seguros de que compilará correctamente; esta anotación hace al compilador mas estricto, con la ventaja de optimizar el código de byte dando como resultado una mejor ejecución. Los desarrolladores recomiendan el uso intenso de esta anotación en todas las clases dentro del proyecto Android:

import android.content.Context
import android.content.Intent
import android.support.v4.app.Fragment
import com.makingdevs.app.common.SingleFragmentActivity
import com.makingdevs.app.ui.fragment.RegistrationFragment
import groovy.transform.CompileStatic

@CompileStatic
class RegistrationActivity extends SingleFragmentActivity{

    static Intent newIntentWithContext(Context context){
        Intent intent = new Intent(context, RegistrationActivity)
        intent
    }

    @Override
    Fragment createFragment() {
        new RegistrationFragment()
    }
}

Realmente este es un tema que se puede extender un poco más, pero iniciando con esto es suficiente.

Los closures

Para quién ya ha programado en Groovy conocerá que los closures son un elemento fundamental, para quiénes no, podrán compararlos con las lambdas de Java 8 o simplemente como lo que son: closures.

La forma general del closure en Groovy es:

{ p1,p2,p3... -> body }

Y creo que es de las partes de las que más podemos comentar, incluso creo que cada beneficio particular que nos da Groovy con los closures lo podremos comentar en un post por separado.

Implementando interfaces con Closures

El evento más solicitado dentro de una app Android es el click de un componente, con un closure podemos tratarlo:

@CompileStatic
public class SomeFragment extends Fragment {

    FloatingActionButton mButtonGoChekin

    // ...more code...

    @Override
    View onCreateView(LayoutInflater inflater,
                      @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        mButtonGoChekin= (FloatingActionButton) root.findViewById(R.id.button_go_chekin)
        mButtonGoChekin.onClickListener = {
            Intent intent = AnotherActivity.newIntentWithContext(getContext())
            startActivity(intent)
        }
    }
}

Ahora aquí una de las que más me gusta en conjunto con otra anotación de Groovy @Singleton, de la cual hablaremos en otro post.

@Singleton
@CompileStatic
class RetrofitTemplate {

    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(BuildConfig.API_SERVER_URL)
            .build()

    def withRetrofit(Class operations, Closure onSuccess, Closure onError, Closure action){
        CustomRestOperations restOperations = retrofit.create(operations) as CustomRestOperations
        Call<Checkin> model = action(restOperations) as Call<Checkin>
        def callback = [
                onResponse :onSuccess,
                onFailure : onError
        ]
        model.enqueue(callback as Callback<Checkin>)
    }
}

Podemos hacer que un mapa se comporte como la implementación de una interfaz, es sólo cuestión de usar los closures correctamente. Y también podemos ejecutar closures para mandarles parámetros listos para usarse en otros contextos.

Conclusión

Si bien, Groovy agrega peso a las aplicaciones Android, creo que cada byte y cada línea vale todo lo que no tuvimos que codificar, la fluidez en el teclado y la productividad ganada.

comments powered by Disqus