Problemas performance ListView carregado com cursor

Boa tarde pessoal.

Estou tendo problemas com a performance de um ListView, quando comecei o desenvolvimento encontrei um tutorial na internet que ensinava a carregá-lo desta maneira que implementei e havia ficado bem veloz pois eram poucos dados, mas após o aumento do número de dados começou a ficar muito lento para carregar.

Gostaria de saber como posso contornar este problema ou se há alguma outra maneira de modificar o carregamento do ListView.

Minha estrutura esta assim:

  • Estou executando este processo dentro do doInBackground de uma AsyncTask:

[code] cliente = new Cliente();
cursorClientes = cliente.CarregaTodos();

			if(cursorClientes!=null){
				
				if(cursorClientes.getCount() > 0){
					
					cursorClientes.moveToFirst();
			                while (!cursorClientes.isAfterLast()) {
			        	       cliente = new Cliente(cursorClientes.getInt(0));
			        	       arrClientes.add(cliente);
			        	       cursorClientes.moveToNext();
			                }
				}
			}[/code]

E no meu onPostExecute eu carrego o meu adapter:

@Override protected void onPostExecute(List<Cliente> result) { // TODO Auto-generated method stub super.onPostExecute(result); progressDialog.dismiss(); if(!(arrClientes.size()>0)){ Toast.makeText(getBaseContext(), "Você não possui Clientes Cadastrados!", Toast.LENGTH_LONG).show(); }else{ setListAdapter(new ClienteAdapter(Singleton.getContextoAplicacao(), result)); } }

Na minha classe Cliente eu tenho o meu método: CarregaTodos() que sobrescreve o método da minha classe de Persistência:

Classe Cliente:

[code] @Override
public Cursor CarregaTodos(){

	//this.Status = eStatus.CarregaTodos;
	this.setTabela(this.getClass().getSimpleName());
	this.setTabelaOrderBy("Identificacao");

	return super.CarregaTodos();
}[/code]

Classe Persistencia:

[code] public Cursor CarregaTodos(){

	DataBase = new DadosBD(this.getContexto());
	RsAtual = DataBase.ExecSelect(Tabela, TabelaColunaComposta, TabelaSelecao, TabelaSelecaoArgumentos, TabelaGroupBy, TabelaHaving, TabelaOrderBy);
	
	if(RsAtual.moveToNext()){
		
		if(DataBase!=null){
			DataBase.fecharBanco();
		}
		return RsAtual;
		
	} else{
		
		if(DataBase!=null){
			DataBase.fecharBanco();
		}
		if(RsAtual!=null){
			RsAtual.close();
		}
		return null;
	}
}[/code]

E no loop em cima do cursor com todos os clientes, a cada código do Cliente passado eu carrego o objeto e gravo em um ArrayList que depois será utilizado para inflar meu ListView.

Teria como eu fazer de alguma outra forma, mantendo mais ou menos a estrutura ou retornando algo diferente para meu ListView trabalhar? Li depois em alguns lugares que o ideal não era trabalhar com Cursores no ListView.

Obrigado desde já.

Olá aboult,

Acho que o problema seu está no Adapter do seu ListView…
Tem um jeito que faz um inflate somente… Veja o exemplo:

public class Adapter extends ArrayAdapter&lt;User&gt; {

	private Context context;

	private ListHolder holder;

	public Adapter(Context context, List&lt;User&gt; users) {
		super(context, R.layout.&lt;custom_listagem&gt;, users);
		this.context = context;
	}

	public View getView(int position, View view, ViewGroup parent) {

		if (view == null) {

			LayoutInflater inflater = (LayoutInflater) this.context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			view = inflater.inflate(R.layout.&lt;custom_listagem&gt;, parent, false);

			holder.avatar = (ImageView)view.findViewById(R.id.&lt;avatar&gt;);
			holder.profileName = (TextView)view.findViewById(R.id.&lt;profile&gt;);
			holder.name = (TextView)view.findViewById(R.id.&lt;name&gt;);
			view.setTag(this.holder);

		} else {
			this.holder = ((ListHolder) view.getTag());
		}
		
		User user = getItem(position);
		
		holder.avatar.setImageURI(user.getAvatar());
		holder.profileName.setText(user.getProfile());
		holder.name.setText(user.getName());
		return view;
	}

	// ///////////////////////////////////
	// /// Internal class
	// ///////////////////////////////////

	private static class ListHolder {
		ImageView avatar;
		TextView profileName, name;
	}
}

O grande lance está no ListHolder, ele guarda a instancia dos objetos view, dai uma vez instanciado nunca mais vai precisar montar novamente,
somente preencher o objeto com os valores.

if(....) {
    ....  
    view.setTag(this.holder);
} else {
     this.holder = ((ListHolder) view.getTag());
}

Creio que isso custe para o processador do mobile, inflar toda vez…

Espero ter ajudado,