Android how to optimize a large chain of ifs

Asked

Viewed 109 times

1

I would like to know how to optimize a large chain of ifs so that the code becomes more efficient and readable.

My Android application uses version 2.3.3 (API 10), in this application I have an Activity responsible for displaying user account information, where it can edit this information and update. This Activity contains 8 fields beside the field has 1 "Edit" button and a hidden "OK" button, if the "Edit" button is clicked then the application hides "Edit" and displays "OK" in the same place. So I have a total of 16 buttons, 8 "Edit" and 8 "OK". That left my onClick(View v) method with 16 ifs.

How can I improve this and make it more efficient and more readable? I know I can use the switch that would be almost the same.

The code below has the method with only 2 of the 16 buttons to simplify, since the other buttons follow the same logic.

public void onClick(View v) {
    // TODO Auto-generated method stub
    if(v.getId() == R.id.btneditar1) {
        camponome.setSelectAllOnFocus(true);
        camponome.setFocusable(true);
        camponome.setFocusableInTouchMode(true);            
        camponome.requestFocus();
        imm.showSoftInput(camponome, InputMethodManager.SHOW_FORCED);
        btneditar1.setVisibility(View.GONE);
        btnok1.setVisibility(View.VISIBLE);
    }

    if(v.getId() == R.id.btnok1) {
        CampoValido = ValidaCampo.validateNotNull(camponome, "Campos sem dados são inválidos!");
        if(CampoValido) {
            CampoValido = ValidaCampo.validateNotEqual(camponome, bnome);
            if(CampoValido) {
                final String nome = camponome.getText().toString().trim();
                atualizar.execute(usuario, nome, null, null, null, null, null, null);
                txtnomebd.setText(nome);
            }
            camponome.setFocusable(false);
            camponome.setFocusableInTouchMode(false);           
            camponome.requestFocus();
            btnok1.setVisibility(View.GONE);
            btneditar1.setVisibility(View.VISIBLE);
        }           
    }

    if(v.getId() == R.id.btneditar2) {
        camposobrenome.setSelectAllOnFocus(true);
        camposobrenome.setFocusable(true);
        camposobrenome.setFocusableInTouchMode(true);           
        camposobrenome.requestFocus();
        imm.showSoftInput(camposobrenome, InputMethodManager.SHOW_FORCED);
        btneditar2.setVisibility(View.GONE);
        btnok2.setVisibility(View.VISIBLE);
    }

    if(v.getId() == R.id.btnok2) {
        CampoValido = ValidaCampo.validateNotNull(camposobrenome, "Campos sem dados são inválidos!");
        if(CampoValido) {
            CampoValido = ValidaCampo.validateNotEqual(camposobrenome, bsobrenome);
            if(CampoValido) {
                final String sobrenome = camposobrenome.getText().toString().trim();
                atualizar.execute(usuario, null, sobrenome, null, null, null, null, null);
                txtsobrenomebd.setText(sobrenome);
            }
            camposobrenome.setFocusable(false);
            camposobrenome.setFocusableInTouchMode(false);          
            camposobrenome.requestFocus();
            btnok2.setVisibility(View.GONE);
            btneditar2.setVisibility(View.VISIBLE);
        }           
    }           

}
  • Try to use switch case... for all ifs of the code. Now there is a lot of content there that is repeated in various functions, optimizing this would create a new logic for you, and we don’t even know your program.

  • @Diego Felipe As said in the question the switch is almost the same thing will not optimize anything.

  • What do you mean by "optimize"? The big problem of the code is not even the ifs, but the number of repeated functions within some conditions. And as I said, optimizing this would be almost the same as recreating your logic. It seems that you can use Arraylist objects as well.

  • @Diego Felipe Yes I had to repeat the functions, because each one besides affecting a different field, it affects a different button. But it is a good idea to make a single method where I pass as parameter the field and button.

  • I have an idea how to solve this, but I do not know if it is optimized, I will post here in the comments and you take a look

  • @Diego Felipe ok.

  • 2

    @Gustavoalmeidacavalcante: Are you superimposing the onClick method of Activity? What I see most is something like findViewById(id).setOnClickListener(new View.OnClickListener() { ... seu código ...} ); , which I consider more readable. Anyway, it would be a great advance to separate these bodies from the ifs in their properly appointed private functions. As for performance, unless you’ve noticed some slowness in that part of the code, don’t worry about it hastily.

  • @Pablo If I were to put the Listener on each button in this way, it would increase the size of the code significantly. I don’t know if it would be more readable, but because it greatly increases the size of the code I prefer to centralize the listener of all buttons in one method.

  • 1

    @Gustavoalmeidacavalcante I prefer for debugging, but this point is really matter of taste. But the other two advices I suggest you consider.

  • 2

    @Gustavoalmeidacavalcante consider using switch or use if.... if Else. The way it is every time the user clicks a button the 16 ifs will be consumed.

  • @Arubu You’re right at this point, the way it consumes the 16 ifs. If I’m really going to use ifs I’ll do it.

  • @Pablo When you think about your idea of putting the Listener on each button with your method the way you said, it might even increase the size of the code, but I think this way it will consume less processing resources since it will not check which button was pressed but will directly execute what is in the button method. However my onCreate() will get bigger and when Activity is started it will consume more resources at that time. Good is just what I think, I’m not sure.

  • @Yes, it probably does. But the difference is probably so small that, for all intents and purposes, it is the same thing. I suggest you stop worrying about performance that way unless you actually measure some difference. There are tools called profilers that serve to find where are the "bottlenecks" of your application. Use them in these situations and, while it is not necessary, worry more about readability that thus you gain more time in the medium and long term.

  • 1

    Checking these 16 ifs is virtually nothing for current processors. Focus on what @Pablo said.

Show 9 more comments

1 answer

1


By reflecting on the comments and do some research. For this specific case, the only way to optimize ifs would be to place a Listener on each button in the onCreate() method thus:

findViewById(id).setOnClickListener(new View.OnClickListener() { ... seu código ...} );

But in doing so I overload the onCreate() method, that is, by optimizing one thing I overload another. I don’t know if this would be better, but with the help of the comments I came to the conclusion that ifs in this case were not the problem but the fact of repeating functions. I was worried about ifs and forgot to use object orientation. So the only optimization done was to make a single method for the action of all the buttons that use this method, passing as parameter what differentiates in the action of each button was like this:

public void onClick(View v) {
    // TODO Auto-generated method stub
    ControlaBanco bd = new ControlaBanco(getBaseContext());
    Cursor dados = bd.pegaUsuario();
    bnome = dados.getString(2);
    bsobrenome = dados.getString(3);
    busuario= dados.getString(4);
    bpaisregiao = dados.getString(6);
    bdatanasc = dados.getString(7);
    bsexo = dados.getString(8);
    bemail = dados.getString(9);

    boolean CampoValido = false;
    TarefaAtualizar atualizar = new TarefaAtualizar(this);
    final String usuario = busuario;

    if(v.getId() == R.id.btneditar1) {
        AcaoEditarCampo(camponome, btneditar2, btnok2);
    }

    if(v.getId() == R.id.btnok1) {
        CampoValido = AcaoOkCampo(camponome, bnome, btnok2, btneditar2);
        if(CampoValido) {
            final String nome = camponome.getText().toString().trim();
            atualizar.execute(usuario, nome, null, null, null, null, null, null);
            txtnomebd.setText(nome);
        }
    }

    if(v.getId() == R.id.btneditar2) {
        AcaoEditarCampo(camposobrenome, btneditar3, btnok3);
    }

    if(v.getId() == R.id.btnok2) {
        CampoValido = AcaoOkCampo(camposobrenome, bsobrenome, btnok3, btneditar3);
        if(CampoValido) {
            final String sobrenome = camposobrenome.getText().toString().trim();
            atualizar.execute(usuario, null, sobrenome, null, null, null, null, null);
            txtsobrenomebd.setText(sobrenome);
        }
    }   

}

private void AcaoEditarCampo(EditText Campo, Button BotaoEditar, Button BotaoOk) {
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    Campo.setSelectAllOnFocus(true);
    Campo.setFocusable(true);
    Campo.setFocusableInTouchMode(true);            
    Campo.requestFocus();
    imm.showSoftInput(Campo, InputMethodManager.SHOW_FORCED);
    BotaoEditar.setVisibility(View.GONE);
    BotaoOk.setVisibility(View.VISIBLE);
}

private boolean AcaoOkCampo(EditText Campo, String bcampo, Button BotaoOk, Button BotaoEditar) {
    boolean CampoValido = ValidaCampo.validateNotNull(Campo, "Campos sem dados são inválidos!");
    if(CampoValido) {
        if(Campo.getInputType() == (InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + 1)) {
            CampoValido = ValidaCampo.validateEmail(Campo);
            if(!CampoValido) {
                return CampoValido;
            }
        }           
        if(CampoValido) {
            CampoValido = ValidaCampo.validateNotEqual(Campo, bcampo);
        }
        Campo.setFocusable(false);
        Campo.setFocusableInTouchMode(false);           
        Campo.requestFocus();
        BotaoOk.setVisibility(View.GONE);
        BotaoEditar.setVisibility(View.VISIBLE);
    }

    return CampoValido;
}

Thank you to everyone who commented and helped in my reply, I will leave without marking this answer as right for 2 days in case someone has a better answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.