Iniciando uma atividade com resultado de maneira limpa

[AVISO IMPORTANTE] ESTA SOLUÇÃO NÃO FUNCIONA. Foi uma boa ideia, mas na verdade não foi: a atividade base A mantém um controle de todos os manipuladores, então, quando você inicia uma atividade B, e devido à pressão de memória, A é eliminada, então, quando B termina com Resultado, A é recriado, portanto, ele não tem nenhum manipulador e nada será chamado. NÃO use esta solução.


Não gostei da maneira como o Android lida com startActivityForResult e onActivityResult. Pareceu errado para mim, então criei uma pequena classe base permitindo uma maneira mais limpa (do meu ponto de vista) de fazer isso.

Em outras palavras :

Isso é péssimo:

private void onButtonClicked(){
Intent intent = new intent(this, Activity.class);
startActivityForResult
(intent, MY_REQUEST_CODE); //we have to keep the request code, who cares ?
}
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
case MY_REQUEST_CODE: //when did we asked for this ?
if(resultCode == Activity.RESULT_OK){
// use data
}
}
}

Isto é o que queremos :

private void onButtonClicked(){
Intent intent = new intent(this, Activity.class);
startActivityForResult
(intent, Activity.RESULT_OK, new SuccessResultHandler() {
@Override
public void onResult(Intent data) {
//here you have your results data. The resultCode has already been checked against Activity.RESULT_OK
}
});
}

Para ter esse recurso, basta criar uma classe base para todas as suas atividades ou fragmento contendo o seguinte:

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Created by philippeauriach on 18/10/2016.

*/

public class BaseActivity extends AppCompatActivity {

private Map<Integer, HandlerHolder> resultHandlers = new HashMap<>();
private AtomicInteger counter = new AtomicInteger(Integer.MIN_VALUE);

private int getNewRequestCode() {
return new AtomicInteger().incrementAndGet();
}

protected void startActivityForResult(Intent intent, int successResultCode, SuccessResultHandler handler) {
int requestCode = getNewRequestCode();
resultHandlers
.put(requestCode, new HandlerHolder(successResultCode, handler));
startActivityForResult
(intent, requestCode);
}

protected void startActivityForResult(Intent intent, ResultHandler handler) {
int requestCode = getNewRequestCode();
resultHandlers
.put(requestCode, new HandlerHolder(handler));
startActivityForResult
(intent, requestCode);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
HandlerHolder handler = resultHandlers.get(requestCode);
if (handler != null) {
if (handler.successHandler != null) {
if (resultCode == handler.successResultCode) {
handler
.successHandler.onResult(data);
}
return;
}
if (handler.resultHandler != null) {
handler
.resultHandler.onResult(resultCode, data);
return;
}
}
}

public interface SuccessResultHandler {
void onResult(Intent data);
}

public interface ResultHandler {
void onResult(int resultCode, Intent data);
}

protected class HandlerHolder {
private Integer successResultCode;
private SuccessResultHandler successHandler;
private ResultHandler resultHandler;

public HandlerHolder(Integer successResultCode, SuccessResultHandler successHandler) {
this.successResultCode = successResultCode;
this.successHandler = successHandler;
}

public HandlerHolder(ResultHandler resultHandler) {
this.resultHandler = resultHandler;
}
}
}