
Eu tenho perguntas sobre expressões lambda e RxJava. Essas perguntas dizem respeito principalmente a um entendimento incompleto de expressões lambda ou RxJava. Vou tentar explicar as expressões lambda da maneira mais simples possível. RxJava vou descrever separadamente.
Expressões Lambda e RxJava
O que são expressões lambda? As expressões lambda são “apenas” uma nova maneira de fazer a mesma coisa que sempre poderíamos fazer, mas de uma maneira mais limpa e menos detalhada de usar classes internas anônimas.
Uma classe interna anônima em Java é uma classe sem nome; deve ser usada se você precisar substituir os métodos de classe ou interface. Uma classe interna anônima pode ser criada a partir de uma classe ou interface.
Por exemplo:
abstract class Animal { abstract void speak(); } Animal a = new Animal() { void speak() { System.out.println("Woff"); } };
No Android, geralmente usamos uma classe interna anônima como ouvinte, por exemplo, para botões desse tipo:
Button btn = findViewById(R.id.button); btn.setOnClickListener( new View.OnClickListener() { @Override public void onClick(final View view) {
Vamos voltar às expressões lambda. Esta é a próxima parte, que faz parte do código anterior, considerado uma classe interna anônima.
new View.OnClickListener() { @Override public void onClick(final View view) {
Expressões lambda só podem ser usadas se você precisar substituir no máximo um método. Felizmente para nós, o View.OnClickListener contém apenas um. Dê uma olhada no código abaixo. Que parte você acha que precisamos remover?
new View.OnClickListener() { @Override public void onClick(final View view) {
Depois de remover quase todo o código, precisamos adicionar ->, como no código abaixo. A visualização do parâmetro de entrada pode ser usada dentro da função da mesma maneira que antes.
(view) -> {
Em alguns casos, pode ser necessário adicionar um tipo a um parâmetro; se o compilador não conseguir adivinhar, você poderá fazer isso adicionando-o antes do parâmetro:
(View view) -> {
Você também pode usar o código de várias linhas:
(view) -> { Intent intent = new Intent(context, AuthActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); view.getContext().startActivity(intent); }
Se você possui uma interface com um método que aceita dois parâmetros ...
interface MyInterface { abstract void onMethod(int a, int b); }
... a expressão lambda ficará assim:
(a, b) -> {
Se o método tiver um tipo de retorno ...
interface MySecondInterface { abstract int onSecondMethod(int a, int b); }
... a expressão lambda ficará assim:
(a, b) -> { return a + b; }
Mas isso não é tudo, existem alguns casos especiais que tornam o código ainda menor. Se o corpo do método contiver apenas uma linha de código, você poderá remover os chavetas {} . Se você remover chaves, também precisará remover o ponto-e-vírgula, deixando o seguinte:
(a, b) -> return a + b
Há mais uma coisa que podemos fazer. Se tivermos apenas uma linha de código, o compilador poderá entender se a parte retornada é necessária ou não, para que possamos deixar assim:
(a, b) -> a + b
Se tivéssemos código com várias linhas, ele se resumiria ao seguinte:
(a, b) -> { a+=1; return a + b; }
Então o que fizemos? Tomamos isso:
new MySecondInterface() { @Override public int onSecondMethod(final int a, final int b) { return a + b; } };
e transformou-o neste:
(a, b) -> a + b
Resta apenas uma coisa: referências de método. Suponha que tenhamos uma interface, como antes, e um método que aceite essa interface como parâmetro:
public interface Callback { public void onEvent(int event); } public void myMethod(Callback callback){ }
Sem uma expressão lambda, ficaria assim:
myMethod(new Callback() { @Override public void onEvent(final int state) { System.out.println(state); } });
Adicionando uma expressão lambda, como fizemos anteriormente, obtemos o seguinte:
myMethod(state -> System.out.println(state));
Mas isso não é tudo. Se o código usado for de linha única e a função chamada tiver um parâmetro, podemos passar a referência do método neste formato:
myMethod(System.out::println);
O parâmetro será passado automaticamente, sem a necessidade de outro código! Incrível né? Espero que você tenha aprendido algo novo!