logo
  • Home
  • Acerca
  • Autores
  • Faq
  • Rede
  Twitter   Feed-me! RSS!
Abr 16

Criando um componente de paginação – Parte 02

Escrito por Fabiel Prestes em 1, 4, 6, abas, action, Actionscript, Actionscript3, AR, arte, Artigo, Banco de Dados, bar, BI, Bindable, blog, boolean, catch, class, classe, classes, código, código fonte, collection, Componente, configuração, dados, DataProvider, demo, Design, Design Pattern, email, err, erro, error, eval, event, EventListener, finally, flash, flash builder, Flex, Flex Fast Code, fonte, for, function, game, gmail, ide, IE, if, image, int, Java, lista, loop, map, mapa, mg, MXML, mysql, Number, O, on, oop, override, pattern, Pessoal, print, Projetos, pt, rest, RIA, Ria’s Geral, RoR, SDK, server, serviço, servidor, state, string, TAT, Tema, try, Tutorial, UI, uint, update, UX, XML, zend @ 04 16th, 2010 | via http://www.fabielprestes.com.br | Sem comentários
Fabiel Prestes
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Salve salve pessoal,

Depois de um enorme jejum aqui no blog estou vontanto trazendo a segunda parte do componente de paginação. Recebi alguns email indagando o porque da demora da continuação do artigo. Então pessoal nestes ultimos meses fiquei meio ocupado com o trabalho peguei uns projetos e estes me tomaram grande parte do meu tempo.

Mas deixando o blá blá blá de lado vamos realmente no que interessa ;)

Na primeira parte do artigo desenvolvemos um componente de paginação estremamente estático, este apenas simulava uma paginação, ou seja, recebia uma lista completa do server-side e ficava então didindo a lista na memória. Todos sabemos que isto é realmente inviável em grande aplicações, pois imaginemos receber uma lista com mais de 1000 registros, com certeza o server-side ou o client iria lançar algum erro.

Nesta situação temos de fazer com que o server-side tenha toda a responsabilidade de paginar e retornar apenas os dados que informamos no filtro, é isso que irei abordar nesta segunda parte do artigo.

Requisitos:

* Ter Flex/Flash Builder ou outra IDE.
* Ter SDK 3 ou superior.
* Conhecimento em ActionScript e Mxml.
* Mysql Instalado e conhecimento básico
* Jdk 5 ou superior

Nível de dificuldade: 8.0

Passo 1:

Iremos criar um projeto Java e suas configurações básica para se conectar com o Flex, não irei demonstrar isso passo a passo já que este tema já foi abordado em um artigo anterior.

Passo 2:

Com o projeto criado e configurado iremos criar as seguintes classes de configuração e conexão com o banco de dados Mysql.
A única responsábilidade desta classe é de abrir e fechar uma conexao com o banco de dados.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package com.imaster;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
/**
 *
 * @author Fabiel Prestes
 *
 */
public class ConnectionManager {
 
	private static final String dburl = "jdbc:mysql://localhost:3306/imaster_paginacao";
    private static final String dbdriver = "com.mysql.jdbc.Driver";
    private static final String usuario = "root";
    private static final String senha = "root";
 
 
    public static Connection getConexao() throws Exception {
        try {
        	Connection conn = null;
            // carregamento do driver
            Class.forName(dbdriver);
            // Obtendo a conexao
            conn = DriverManager.getConnection(dburl, usuario, senha);
            System.out.println(" <<< Obtendo conexao >>>");
            return conn;
 
        } catch (ClassNotFoundException e) {
            String errorMsg = "Driver nao encontrado";
            throw new Excecoes(errorMsg, e);
        } catch (SQLException e) {
            String errorMsg = "Erro ao obter a conexao";
            throw new Excecoes(errorMsg, e);
        }
    }
 
    public static void closeAll(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            String errorMsg = "Nao foi possivel fechar a conexao com o banco";
            Excecoes.print(e, errorMsg);
        }
    }
 
    public static void closeAll(Connection conn, Statement stmt) {
        try {
            if (stmt != null) {
                stmt.close();
            }
        } catch (Exception e) {
            String errorMsg = "Nao foi possivel fechar o Statement";
            Excecoes.print(e, errorMsg);
        }
        closeAll(conn);
    }
 
    public static void closeAll(Connection conn, Statement stmt, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (Exception e) {
            String errorMsg = "Nao foi possivel fechar o Resultset";
            Excecoes.print(e, errorMsg);
        }
        closeAll(conn, stmt);
    }
 
}

Passo 3:

Iremos criar a classe AlunoDAO, está irá ter três métodos: Um para inserir alunos, um para listar os alunos e um outro para contar o total de alunos.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.imaster;
 
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
 
/**
 *
 * @author Fabiel Prestes
 *
 */
public class AlunoDAO {
 
	private Connection conn = null;
	private Statement stmt = null;
	private ResultSet rs = null;
 
	public void salvar(Aluno aluno) throws Exception {
		try {
			// criando Conexao
			conn = ConnectionManager.getConexao();
			stmt = conn.createStatement();
 
			// comando sql
			String sql = "insert into aluno (nome, email) values ('"+aluno.getNome()+"', '"+aluno.getEmail()+"')";
 
			stmt.executeUpdate(sql);
 
			System.out.println(" <<< aluno inserido com sucesso >>>");
		} catch (SQLException e) {
			Excecoes.print(e,"Nao foi possivel salvar o aluno na base de dados.");
		} finally {
			// Finalizar o statement e a conexao usando a classe ConnectionManager
			ConnectionManager.closeAll(conn, stmt);
		}
	}
 
	public int getTotalAlunos() throws Exception {
		int totalAlunos = 0;
 
		try{
			// comando sql
			String sql = "SELECT COUNT(*) FROM aluno";
 
			// criando Conexao
			conn = ConnectionManager.getConexao();
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);
 
			while(rs.next()){
				totalAlunos = rs.getInt(1);
			}
		} catch (SQLException e) {
			Excecoes.print(e,"Nao foi possivel recuperar o total de alunos na base de dados.");
		} finally {
			// Finalizar o statement e a conexao usando a classe ConnectionManager
			ConnectionManager.closeAll(conn, stmt);
		}
		return totalAlunos;
	}
 
	public List<Aluno> listarAlunos(int pagina, int totalRegistros) throws Exception {
		List<Aluno> alunos = new ArrayList<Aluno>();
 
		try{
			// comando sql
			String sql = "SELECT * FROM aluno LIMIT "+pagina+","+totalRegistros;
 
			// criando Conexao
			conn = ConnectionManager.getConexao();
			stmt = conn.createStatement();
			rs = stmt.executeQuery(sql);
 
			Aluno aluno = null;
 
			while(rs.next()){
				aluno = new Aluno();
				aluno.setId(rs.getInt("id"));
				aluno.setNome(rs.getString("nome"));
				aluno.setEmail(rs.getString("email"));
 
				alunos.add(aluno);
			}
		} catch (SQLException e) {
			Excecoes.print(e,"Nao foi possivel recuperar o total de alunos na base de dados.");
		} finally {
			// Finalizar o statement e a conexao usando a classe ConnectionManager
			ConnectionManager.closeAll(conn, stmt);
		}
		return alunos;
	}
}

Passo 4:

Com o DAO criado necessitamos de uma classe para acessar e chamar os metodos e devolve-los ao Client. Esta classe realmente simples apenas recebe uma requisição do Flex e retorna o resultado da paginação.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.imaster;
 
/**
 *
 * @author Fabiel Prestes
 *
 */
public class PaginacaoService {
 
	private AlunoDAO alunoDAO;
 
	public AlunoDAO getAlunoDAO(){
		if(alunoDAO == null){
			alunoDAO = new AlunoDAO();
		}
		return alunoDAO;
	}
 
	public Paginacao listarDadosPaginados(int pagina, int totalRegistros) throws Exception {
		try {
			Paginacao paginacao = new Paginacao();
			paginacao.setTotalDados(getAlunoDAO().getTotalAlunos());
			paginacao.setListaDados(getAlunoDAO().listarAlunos(pagina, totalRegistros));
			return paginacao;
		} catch (Exception e) {
			throw e;
		}
	}
 
	public static void main(String[] args) throws Exception {
		PaginacaoService ps = new PaginacaoService();
		System.out.println(ps.getAlunoDAO().getTotalAlunos());
//		ps.getAlunoDAO().salvar(new Aluno("Fabiel Prestes", "fabiel.prestes@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Joao Prestes Neto", "joao.prestes@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Dom Pedro I", "domI@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Dom Pedro II", "donII@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Luiz Inacio", "luiz@inacio.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Ana Carolina", "ana@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Ana Beatriz", "anabeatriz@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Antonio Carlos", "antonio@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Aline B. R.", "aline@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Cecilia Duarte", "cecilia@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Maria Isabel", "mariaisabel@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Carlos Renato", "carlosrenato@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Susana", "susana@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Monica", "monmica@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Cebolinha", "cebolinha@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Chico Bento", "chicobento@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Magali", "magali@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Anginho", "anginho@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Cascao", "cascao@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("zeca Urubu", "eca@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Pica Pau", "picapau@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("zé Carioca", "cariona@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Tio Patinhas", "tiopatinhas@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Xuxa", "xuxa@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Sheila", "sh@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Hebe Camargo", "hebe@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Jonas", "jonas@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Igor", "@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Magnum", "@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Princila", "@gmail.com"));
//		ps.getAlunoDAO().salvar(new Aluno("Maria Cecilia", "@gmail.com"));
 
 
	}
}

Passo 5:

Com a nossa classe de serviço pronta precisamos criar um DTO/VO que represente a paginação em si. Neste DTO iremos ter apenas duas propriedades: totalDados e listaDados. O flex irá utilizar os dados contidos neste DTO para montar toda a estrutura de paginação.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.imaster;
 
import java.util.List;
 
/**
 *
 * @author Fabiel Prestes
 *
 */
public class Paginacao {
 
	private int totalDados;
	private List<? extends Object> listaDados;
 
	public Paginacao(){
 
	}
 
	/**
	 * @return the totalDados
	 */
	public int getTotalDados() {
		return totalDados;
	}
	/**
	 * @param totalDados the totalDados to set
	 */
	public void setTotalDados(int totalDados) {
		this.totalDados = totalDados;
	}
	/**
	 * @return the listaDados
	 */
	public List<? extends Object> getListaDados() {
		return listaDados;
	}
	/**
	 * @param listaDados the listaDados to set
	 */
	public void setListaDados(List<? extends Object> listaDados) {
		this.listaDados = listaDados;
	}
 
}

Passo 6:

Segue a classe Aluno que é simplesmente um DTO/Bean e a classe Excecoes que apenas realiza um tratamento nas Exceptions geradas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.imaster;
 
public class Aluno {
 
	private Integer id;
 
	private String nome;
 
	private String email;
 
	public Aluno(){
 
	}
 
	public Aluno(String nome, String email){
		this.nome = nome;
		this.email = email;
	}
 
	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}
 
	/**
	 * @param id the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}
 
	/**
	 * @return the nome
	 */
	public String getNome() {
		return nome;
	}
 
	/**
	 * @param nome the nome to set
	 */
	public void setNome(String nome) {
		this.nome = nome;
	}
 
	/**
	 * @return the email
	 */
	public String getEmail() {
		return email;
	}
 
	/**
	 * @param email the email to set
	 */
	public void setEmail(String email) {
		this.email = email;
	}
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
 *
 */
package com.imaster;
 
/**
 * @author Fabiel
 *
 */
public class Excecoes extends Exception{
 
	private static final long serialVersionUID = 1L;
 
	public Excecoes(String mensagem, Exception e) {
        super(mensagem, e);
    }
 
    public Excecoes(String mensagem) {
        super(mensagem);
    }
 
    public static void print(Exception e, String mensagem) {
        System.out.println("==============Exception===============");
        System.out.println(mensagem);
        System.out.println("PrintStackTrace: ");
        e.printStackTrace();
        System.out.println("============End Exception=============");
    }
 
    public void print() {
        System.out.println("==============Exception===============");
        System.out.println(getMessage());
        System.out.println("PrintStackTrace: ");
        getCause().printStackTrace();
        System.out.println("============End Exception=============");
    }
}

Chegamos ao final da configuração do servidor, neste não irei me apegar a nenhum design pattern e nem a bons modos de implentação já que o foco aqui é apenas mostrar como se faz para utilizar a paginação via sql.

Agora no projeto Flex que foi criado na parte I não iremos alterar muita coisa, iremos alterar apenas a classe Paginacao.as e criar uma classe chamada PaginacaoVO.as que é o espelho do nosso DTO Paginacao.java.

Na classe paginação inseri algumas anotations:

  • @Novo quando tive de criar metodos e variaveis
  • @Alterado quando apenas alterei um algoritimo de algum método
  • @Removido quando exlcui alguma variável ou método

Abaixo irei colocar alguns trechos que tive que modificar para a segunda parte do arqtigo. Mais já irei adiantando que apenas modifiquei uma ou outra coisa.

1
2
/** @Novo */
private var remotePaginacao:RemoteObject;
1
2
3
/* @Removido
[Bindable]
private var _listaBaseAux:ArrayCollection; */
1
2
/** @Novo */
private var _atualizarBarraBotoes:Boolean = true;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @Alterado
*
*/
public function Paginacao() {
super();
 
remotePaginacao = new RemoteObject();
remotePaginacao.destination = destination;
remotePaginacao.addEventListener(FaultEvent.FAULT, function (event:FaultEvent):void{
Alert.show(event.toString());
});
 
this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreate, false, 0, true);
}
1
2
3
4
5
6
7
8
/**
* @private
* @Novo
*
*/
private function onCreate(evt:FlexEvent):void{
this.remotePaginacao.listarDadosPaginados(0, totalPorPagina);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @private
* @Novo
* @param evt
*
*/
private function listarDadosPaginadosResult(evt:ResultEvent):void{
totalDados = PaginacaoVO(evt.result).totalDados;
listaBase = PaginacaoVO(evt.result).listaDados;
 
if(_atualizarBarraBotoes){
configurarBotoesPagina();
} else {
this.listaAlvo.dataProvider = listaBase;
}
}
1
2
3
4
5
6
7
8
9
10
/**
* @Removido
*
*/
override public function invalidateProperties():void{
super.invalidateProperties();
 
/* Inicializa a configuração da paginação */
configurarBotoesPagina();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @private
* @Alterado
* Fica escutando quando o usuario trocou o total de interva de dados a ser amostrado na lista
* @param evt
*/
private function trateTrocaIntervalo(evt:ListEvent):void{
totalPorPagina = cbIntevalo.selectedItem.value;
 
/* INICIO: @Novo*/
_atualizarBarraBotoes = true;
 
this.remotePaginacao.listarDadosPaginados(0, totalPorPagina);
/* FIM: @Novo*/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* @private
* @Alterado
* Configura e renderiza os dados Base para ser amostrado na tela levendo-se em consideração
* o intervalo passado.
* @param intervloIncial
*
*/
private function configurarListaNaPagina(bpAtual:BotaoPagina):void{
/* INICIO: @Removido
_listaBaseAux = new ArrayCollection();
 
//para cada Loop é copiado o objeto que se encontra no intervalo passado como parametro
 
for(var j:int = 0; j &lt; _totalPorPagina; j++){
if(bpAtual.intervaloInicial + j &lt; _totalDados)
_listaBaseAux.addItem(_listaBase.getItemAt(bpAtual.intervaloInicial + j));
}
FIM: @Removido */
 
/* Configurando os botoes de avançar e retornar */
if(bpAtual.pagina &gt; 1){
configBpPaginaAnterior();
} else {
configBpPaginaAnterior(false);
}
 
if(bpAtual.pagina == totalBotoes){
configBpProximaPagina(false);
} else {
configBpProximaPagina();
}
 
/* INICIO: @Removido
//Define o provider clonado e define na ListBase
this._listaAlvo.dataProvider = _listaBaseAux;
* FIM: @Removido */
 
/* INICIO: @Novo */
_atualizarBarraBotoes = false;
this.remotePaginacao.listarDadosPaginados((bpAtual.pagina - 1) * totalPorPagina, totalPorPagina);
/* FIM: @Novo */
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @Alterado
* Define a lista que será utilizada para exibir na paginacao
* @param value
*
*/
public function set listaBase(value:ArrayCollection):void{
_listaBase = value;
/*
_listaBase = value;
if(_listaBase){
_totalDados = _listaBase.length;
}
*/
}

É isso aí pessoal todas as alterações que tive que fazer para que o componente de paginação funciona-se junto ao server-side.

Estou disponibilizando o código fonte de ambos os projetos para vocês testarem.

Agora é só esperarem a terceira parte do tutorial, onde iremos refinar o componente, aplicar filtros e ordenação dos dados.

Código Fonte

Abraço pessoal e até a próxima.

Mai 7

Método construtor – Singleton

Escrito por Fabio da Silva em as3, Design Pattern @ 05 7th, 2009 | via http://fabiophx.blogspot.com | Sem comentários
Fabio da Silva
? X
  • Bookmarks

Blinkbits BlinkLists BlogLines Blogmarks Buddymarks CiteULike Co.mments Del.icio.us Digg Diigo

Fark Feed Me Links Furl Google Linkagogo ma.gnolia Mister Wong Newsvine Propeller Rawsugar

Reddit Rojo Simpy Sphinn Spurl Squidoo StumbleUpon Tailrank Technorati Yahoo

More »

Em AS não existe uma forma de criar um método construtor de uma classe como private para assim podermos usar o Design Pattern Singleton.

Métodos construtores só podem ser public sendo opcional a sua presença.

Se a sua classe herda de outra é uma boa prática fazer a chamada explícita ao método construtor da superclasse usando super(), mas caso você esqueça não tem problema, se o compilador não encontrar esta chamada, então ele irá colocar como primeiro comando do seu construtor.

Se você não criar um método construtor também não tem problema, pois o compilador cria um método construtor vazio colocando super() dentro.

Outra coisa interessante é que você pode usar o comando return no método construtor, desde que não retorne nenhum valor.

Mas se você precisar usar o Design Pattern Singleton você pode usar o seguinte código:

package mypackage {
   public class ClassSingleton {
      private static var instance:ClassSingleton;

      public function ClassSingleton(enforcer:SingletonEnforcer) {
         if (enforcer == null) {
            throw new ReferenceError(“Essa classe é Singleton. Utilize getInstance.”);
         }
      }

      public static function getInstance():ClassSingleton {
         if (ClassSingleton.instance == null) {
            ClassSingleton.instance = new ClassSingleton (new SingletonEnforcer());
         }

         return ClassSingleton.instance;
      }
   }
}


/** Classe utilitária para proibir o acesso ao construtor da classe Singleton. */
class SingletonEnforcer { }

| Entradas recentes »

ACERCA

O que é o RedeRIA ?

O redeRIA não é nada mais que um agregador de feed's que disponibiliza o conteudo de varios blogs e autores ao redor do mundo RIA, actualmente agregamos mais de 2791 entradas vindas de 53 blogs especializados em ria’s, pelo que só fica a ganhar em assinar o feed ou seguir a comunidade no twitter.

Se acha que o seu blog ou um blog de um amigo é interessante e util para os leitores o redeRIA, faça a sua submissão aqui.

Feed: assine já
Twitter: siga-nos

GOOGLE

Votação


Deveria o RedeRia agregar conteúdo em inglês?
Ver Resultados

AUTORES


Eduardo KrausAlexandre TadashiBindableCognitiva SoluçõesDaniel LopesDaniel SchmitzDanielPedrinhaDClick TeamEbercomEdgard DavidsonElvis FernandesErko BrideeFabiel PrestesFábio Batista da SilvaFabio da SilvaFabriccio BernardesFelipe BorellaFlavia MoreiraGabriel VersalliniGabriela T. PerryIgor MusardoJanderson CardosoJoão AugustoJose Carlos FielKelps SousaLeonardo FrançaLucas MarçalLuis MessiasLuiz TarabalMario JuniorMário SantosMauro MartinsPablo SouzaPedro ClaudioreneRia BrazilriaPTRicardo CerqueiraRobson FernandesRodrigo Pereira FragaSaintBrSamuelFacchinelloSergio SouzaSilva DeveloperStefan HorochovecTech CaffeTecinforThiago BuenoVedVinícius SandimWillian ManoXAML Cast

PUBLICIDADE








Powered by Wordpress & msdevstudio.com