Flutter - Otimizando código - parâmetros opcionais


Hoje veremos como usar argumentos nomeados para poder otimizar código no Flutter.

O que é o Flutter ?

O Flutter é um SDK de aplicativo móvel do Google que ajuda a criar aplicativos móveis modernos para iOS e Android usando uma única (quase) base de código.

Se você não conhece o Flutter veja o meu artigo :  Flutter - Primeiros contatos e impressões

Otimizando código - Parâmetros Opcionais

A linguagem Dart possui duas formas de usar parâmetros opcionais:

  1. Parâmetros posicionais -  Usamos colchetes [] para especificar parâmetros posicionais opcionais. Se parâmetros posicionais opcionais forem definidos, as chamadas de função poderão especificar um número variável de argumentos. Ex:
     
    void main() {
      teste(1);
      teste(1, 2);
      teste(1, 2, 3);
    }
    void teste(a, [b, c]) { }

     

  2. Parâmetros nomeados - As chaves {} podem ser usadas para especificar parâmetros nomeados opcionais. Eles diferem dos parâmetros posicionais, pois seus nomes devem ser especificados para serem passados. Os nomes são especificados usando a sintaxe: parametro: value

Vejamos um exemplo prática da aplicação desta última opção.

Criando o projeto : Tela de Login

Vamos pegar como exemplo a definição do leiaute da uma tela de Login onde vamos usar um Form e dois Widgets TextFormField um para o nome e outro para a senha.

Para ver detalhes de como criar o projeto e como criar o leiaute passo a passo veja este meu artigo:  Login com WEB API

No arquivo onde definimos o código que define a tela de login vamos usamos um widget Form tendo como filho um widget ListView e neste widget usar um array de widgets para empilhar os dois widgets TextFormFields e RaisedButton.

Nota:  Para saber mais sobre o widget Form, veja meu artigo : Criando formulários com validação

 _body(BuildContext context) {
    return Form(
       child: ListView(
         children: <Widget>[
           textFormFieldLogin(),
           textFormFieldSenha(),
           containerButton(context)
         ],
        )
      );
  }

Para organizar o código e torná-lo mais legível definimos 3 métodos como filhos do ListView onde vamos implementar as funcionalidades e realizar a validação.

Assim o código da implementação para o TextFormField para o login ficou assim:

textFormFieldLogin() {
     return TextFormField(
           controller: _tedLogin,
           validator: _validaLogin,
           keyboardType: TextInputType.text,
           style: TextStyle(color: Colors.black),
           decoration: InputDecoration( 
             labelText: "Login",
             labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
             hintText: "Informe a senha"
         )
     );
 }

Aqui usamos o widget TextFormField definindo o tipo de teclado e usando um InputDecoration para criar uma Label com um estilo e uma dica de texto.(hintText).

Além disso estamos usando o controller e o validator do TextFormField para poder tratar os dados informados pelo usuário e realizar a validação.

Abaixo temos o código para o TextFormField para a senha:

 textFormFieldSenha() {
     return TextFormField( 
           controller: _tedSenha,
           validator: _validaSenha,
           obscureText: true,
           keyboardType: TextInputType.text,
           style: TextStyle(color: Colors.black),
            decoration: InputDecoration( 
             labelText: "Senha",
             labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
             hintText: "Informe a senha"
         )
     );
 }

Observe que temos código duplicado, o que não é bom. O que esta variando é o LabelText e o hintText que podemos então parametrizar. Podemos assim criar um método genérico.

Vamos criar um método chamado textFieldGenerico() que vai receber dois parâmetros: label e hint:

textFieldGenerico(String label, String hint) {
     return TextFormField(
           controller: _tedLogin,
           validator: _validaLogin,
           keyboardType: TextInputType.text,
           style: TextStyle(color: Colors.black),
           decoration: InputDecoration( 
             labelText: label,
             labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
             hintText: hint
            )
         );
   }
 

Agora para poder usar basta passar os parâmetros para cada caso:

 _body(BuildContext context) {
    return Form(
      key: _formKey,
       child: ListView(
         children: <Widget>[
           Icon(Icons.account_circle, size: 80.0,color: Colors.blue),
           textFieldGenerico("Login","Digite o login"),
           textFieldGenerico("Senha","Digite a Senha"),
           containerButton(context)
         ],
        )
      );
  }

Mas temos um problema. O campo senha possui a propriedade obscureText e o campo login não possui.

Para resolver esse problema vamos usar os parâmetros nomeados opcionais definindo o parâmetro relativo a essa propriedade como sendo opcional e atribuindo um nome obscure a ele:

 textFieldGenerico(String label, String hint, {bool obscure = false}) {
     return TextFormField(
           controller: _tedLogin,
           validator: _validaLogin,
           keyboardType: TextInputType.text,
           obscureText: obscure,
           style: TextStyle(color: Colors.black),
           decoration: InputDecoration( 
             labelText: label,
             labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
             hintText: hint
            )
         );
   }

Para chamar o método genérico basta definir o argumento como true para ativar a ocultação da senha:

_body(BuildContext context) {
    return Form(
      key: _formKey,
       child: ListView(
         children: <Widget>[
           Icon(Icons.account_circle, size: 80.0,color: Colors.blue),
           textFieldGenerico("Login","Digite o login"),
           textFieldGenerico("Senha","Digite a Senha", obscure : true),
           containerButton(context)
         ],
        )
      );
  }

E usamos esse mesmo recurso definindo dois parâmetros:

  1. controller : do tipo TextEditingController
  2. validacao : do tipo Validator:
 textFieldGenerico(String label, String hint, {bool obscure = false, controller, validacao}) {
     return TextFormField(
           controller: controller,
           validator: validacao,
           keyboardType: TextInputType.text,
           obscureText: obscure,
           style: TextStyle(color: Colors.black),
           decoration: InputDecoration( 
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(15)),
             labelText: label,
             labelStyle: TextStyle(fontSize:20.0, color: Colors.black),
             hintText: hint
            )
         );
   }

Com este método genérico podemos inclusive reaproveitar o código se precisarmos.

No código definimos a propriedade border do inpuDecoration para criar bordas arredondadas nas caixas de texto do formulário:

  border: OutlineInputBorder(borderRadius: BorderRadius.circular(15))

Incluimos também o widget Divider para dar um espaço entre os TextFormField.

Para usar o método genérico basta definir os argumentos para controller e validacao conforme abaixo:

 _body(BuildContext context) {
    return Form(
      key: _formKey,
       child: ListView(
         children: <Widget>[
           Icon(Icons.account_circle, size: 80.0,color: Colors.blue),
           textFieldGenerico("Login","Digite o login", controller : _tedLogin, validacao: _validaLogin),
           Divider(),
           textFieldGenerico("Senha","Digite a Senha", obscure : true, controller : _tedSenha, validacao: _validaSenha),
           containerButton(context)
         ],
        )
      );
  }

Aqui a ordem de passar os argumentos não importa visto que os parâmetros são nomeados.

Lembrando que já temos definidos os métodos _validaLogin e _validaSenha:

 String _validaLogin(String text){
      if(text.isEmpty){
        return "Informe o login";
      }
      return null;
  }
  String _validaSenha(String text){
      if(text.isEmpty){
        return "Informe a senha";
      }
      return null;
  }

 

O resultado final obtido é visto abaixo:

Essa não é a única forma de otimizar código mas é a mais básica e intuitiva, o importante é evitar a duplicação de código.

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti