Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin 9 meses depois

Kotlin 9 meses depois

Kotlin é uma linguagem de programação criada pela JetBrains que traz mais clareza, segurança e simplicidade ao código. A relevância da linguagem no mundo Android deixou de ser dúvida depois que a Google anunciou suporte oficial no Google IO. Nos últimos 9 meses trabalhamos com essa linguagem no desenvolvimento de um aplicativo Android. Nesta palestra daremos nossa opinião apresentando pontos positivos e negativos dessa experiência.

André Luiz Cardoso

August 25, 2017
Tweet

More Decks by André Luiz Cardoso

Other Decks in Programming

Transcript

  1. Kotlin | O que é isso? - JetBrains - JVM

    - Concisa, Segura, Versátil, Interoperável
  2. 4 4

  3. Pontos fortes | Synthetic properties closeButton = (Button) findViewById(R.id.close_button);
 closeButton.setOnClickListener(new

    View.OnClickListener() {
 @Override
 public void onClick(View v) {
 presenter.close();
 }
 });
  4. Pontos fortes | Lambdas moviesApi.loadMovies(genre)
 .map { it.movies } .map

    { it.rating > 4 }
 .subscribe({ goodMovies ->
 goodMovies?.let { view.showMovies(it) }
 }, {
 Log.e(TAG, "Error loading movies from $genre", it)
 })
  5. Pontos fortes | Collections movies.filter { it.isFavorite } movies.sortedWith(compareBy( Movie::year,

    Movie::title, Movie::rating)) val movies = listOf("ET", "Tomates Assassinos") val rating = listOf(5, 1) print(movies.zip(rating)) //[(ET, 5), (Tomates Assassinos, 1)]
  6. Pontos fortes | Collections var horrorMoviesTitles = movies .asSequence() .filter

    { it.genre == "horror" } .map { it.title } .toList()
  7. Pontos fortes | Null safety public String getUrl(Movie movie) {


    if (movie == null || movie.getPosters() == null) {
 return fallbackUrl;
 }
 
 for (Poster poster : movie.getPosters()) {
 if (poster.type.equals("P") && poster.getUrl() != null) {
 return poster.getUrl();
 }
 }
 
 return fallbackUrl;
 }
  8. Pontos fortes | Extension functions val Context.isLandscape: Boolean get() =

    resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE fun View.fadeIn() {
 visibility = View.VISIBLE
 ViewCompat.animate(this)
 .alpha(1F)
 .start(
 } var View.visible: Boolean
 get() = visibility == View.VISIBLE
 set(value) {
 visibility = if (value) View.VISIBLE else View.GONE
 }
  9. Pontos fortes | Extension functions val Context.isLandscape: Boolean get() =

    resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE fun View.fadeIn() {
 visibility = View.VISIBLE
 ViewCompat.animate(this)
 .alpha(1F)
 .start(
 } var View.visible: Boolean
 get() = visibility == View.VISIBLE
 set(value) {
 visibility = if (value) View.VISIBLE else View.GONE
 }
  10. Pontos fortes | Extension functions val Context.isLandscape: Boolean get() =

    resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE fun View.fadeIn() {
 visibility = View.VISIBLE
 ViewCompat.animate(this)
 .alpha(1F)
 .start() } var View.visible: Boolean
 get() = visibility == View.VISIBLE
 set(value) {
 visibility = if (value) View.VISIBLE else View.GONE
 }
  11. Pontos fortes | Interoperability // MovieExtensions.kt
 fun Movie.isNew(currentDate: Date): Boolean

    {
 return launchDate?.let { it.daysBefore(currentDate) < 7 } ?: false
 } // SomeFile.java boolean isNew = MovieExtensions.isNew(movie);
  12. Pontos fortes | Data classes data class Movie( val title:

    String, 
 val year: Int, val rating: Float ) val et = Movie(title = "ET", year = 1982, rating = 5.0f) val (title, year) = et moviesSet.add(et)
  13. Pontos fortes | Imutabilidade val immutableMovies = listOf<Movie>() immutableMovies.add(et) val

    movies = mutableListOf<Movie>() movies.add(et) var movie = et movie = et.copy(title = "Alien")
  14. Pontos fortes | Sealed classes sealed class MovieViewState { data

    class Loaded(val movies: List<Movie>): MovieViewState() class Error: MovieViewState() class Loading: MovieViewState() }
  15. Pontos fortes | Sealed classes fun render(viewState: MovieViewState) { return

    when(viewState) { is MovieViewState.Loaded -> print(viewState.movies) } } //'when' expression must be exhaustive, add necessary 'is Error', 'is Loading' branches or 'else' branch instead
  16. Pontos fortes | Múltiplas classes por arquivo // MoviesInjection.kt @ActivityScope


    @Subcomponent(modules = arrayOf(MovieModule::class))
 interface MovieComponent {
 fun inject(activity: MovieActivity)
 }
 
 @Module
 class MovieModule(private val view: Movie.MovieView) {
 
 @Provides @ActivityScope
 fun provideMoviePresenter(movieLoader: MovieLoader): Movie.Presenter {
 return MoviePresenter(view, movieLoader)
 }
 }
  17. Pontos fortes | Múltiplas classes por arquivo // MoviesMvp.kt interface

    MoviesView { fun showMovies(movies: List<Movie>) } interface MoviesPresenter { fun loadMovies() }
  18. Dores | Mais métodos trouble writing output: Too many field

    references: 131000; max is 65536. You may try using --multi-dex option.
  19. Dicas | Evite escrever Kotlin como em Java if (movieTitle

    == "Guardians of the galaxy") {
 movie.setGenre(comedy)
 } else if (movieRating > 4) {
 movie.setGenre(good)
 } else {
 movie.setGenre(others)
 } if (movie != null) {
 presenter.list(movie.getGenre())
 }
  20. Dicas | Evite escrever Kotlin como em Java movie.genre =

    when {
 movieTitle == "Guardians of the galaxy" -> comedy movieRating > 4 -> good else -> others
 } movie?.let {
 presenter.list(it.genre)
 }
  21. Dicas | JVM annotations class MovieTextView @JvmOverloads constructor( context: Context,

    attrs: AttributeSet? = null, defStyleAttr: Int = 0): TextView(context, attrs, defStyleAttr) data class Movie(val title: String) : Parcelable { // ... companion object { @JvmField val CREATOR = object: Parcelable.Creator<Movie> { // ... } } }
  22. Dicas | JVM annotations @file:JvmName(“ExtensionsUtils") companion object {
 @JvmStatic fun

    newInstance(tourCode: String): Fragment {
 // ...
 }
 }
  23. Dicas | Adote um code standard class MoviesPresenter(
 movies: List<Movie>,


    private val moviesApi: MoviesApi,
 override val view: Movies.View,
 router: Router,
 private val user: User,
 override val shareManager: ShareManager
 ): BaseMoviesPresenter(movies, router, user), Movies.Presenter { … }
  24. Dicas | Adote um code standard @file:JvmName(“ImageFormatUtil”) … ImageFormatUtil.isGif(file); vs

    @file:JvmName(“ImageFormatUtil”) … ImageFormatUtilKt.isGif(file);
  25. Dicas | Utils vira extensions, private talvez fun Date?.format(pattern: String):

    String {
 return this?.let { SimpleDateFormat(pattern, Locale.US).format(it) } ?: ""
 } public class DateUtils {
 public public String format(Date date, String pattern) {
 if (date == null) {
 return "";
 }
 return new SimpleDateFormat(pattern, Locale.US).format(date);
 }
 }
  26. Dicas | Cuidado com nulls vindo do Java val movie

    = Movie() // Classe Java 
 movie.genre = null
 movie.genre.toString() // NPE
  27. Dicas | Null annotations // Java
 public static void prettyPrint(@NonNull

    String message) {
 System.out.print(message);
 }
 
 public @Nullable Rating getRating() { … } // Kotlin
 prettyPrint(null)
 val x: Rating = getRating()
  28. Dicas | Null annotations // Java
 public static void prettyPrint(@NonNull

    String message) {
 System.out.print(message);
 }
 
 public @Nullable Rating getRating() { … } // Kotlin
 prettyPrint("oi")
 val x: Rating? = getRating()
  29. Dicas | Builders e named parameters val movie = Movie(


    title = "Back to the Future 4",
 year = 2030,
 rating = 5f
 )
 
 val movie = Movie().apply {
 title = "Back to the Future 4"
 year = 2030
 rating = 5f
 }
  30. Dicas | Interface default implementations // Kotlin interface MovieHandler {

    fun handleMovie() { print("default handling") } } // Java class JavaMovieHandler implements MovieHandler { }
  31. Dicas | Annotation use-site target data class SomeDataClass(
 @field:SomeAnnotation
 @get:[Annotation1

    Annotation2]
 @set:YetAnotherAnnotation
 @param:LastAnnotation
 var someProperty: SomeType, …
  32. Dicas | Lambda do Java 8 val map = mapOf("Java"

    to "Kotlin") map.forEach { key, value -> print("Java 8") } map.forEach { (key, value) -> print("Kotlin") }
  33. Dicas | Kotlin Standard Library no Java goodMovies = CollectionsKt.minus(movies,

    badMovies); List<Movie> shortMovies = CollectionsKt.filter(movies, movie -> movie.length() > 100);
 shortMoviesTitles = CollectionsKt.map(shortMovies, Movie::getTitle);
  34. Dicas | Unit vazando para o Java // Kotlin
 val

    movieLoadedSubject: Subject<Unit> = PublishSubject.create<Unit>()
 
 movieLoadedSubject.subscribe {
 // no arg
 }
 // Java movieLoadedSubject.subscribe(unit -> {
 // can't ignore Unit arg :(
 });