Perda de Performance no ProgressBar ou ProgressDialog

Fazendo uns testes com meu amigo GilsonNunes percebemos que ao utilizar o código abaixo :


package viny.progress;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class AppTesteProgressActivity extends Activity {
	/** Called when the activity is first created. */

	private ProgressBar jProgressBar1,jProgressBar2;
	private int max = 100;
	private TextView lbl1, lbl2 ;
	private int iterations = 2000000;
	private int teste = 0 ;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		lbl1 = (TextView) findViewById(R.id.textView1);
		lbl2 = (TextView) findViewById(R.id.textView2);

		Button btn1 = (Button) findViewById(R.id.button1);
		btn1.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				setUp();

			}
		});
		Button btn2 = (Button) findViewById(R.id.button2);
		btn2.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				setUp2();

			}
		});
		jProgressBar1 = (ProgressBar) findViewById(R.id.progressBar1);
		jProgressBar2 = (ProgressBar) findViewById(R.id.progressBar2);

	}
	
	private void setUp(){
		jProgressBar1.setMax(max);
		final long l =  System.currentTimeMillis();
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < iterations; i++) {             
					jProgressBar1.setProgress(i *  100 / iterations);            
				}

				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						lbl1.setText(String.valueOf(System.currentTimeMillis() - l));				
					}
				});
			}
		}).start();

	}

	private void setUp2(){
		jProgressBar2.setMax(max);
		final long l =  System.currentTimeMillis();
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < iterations; i++) {
					if(teste != i){
						teste = i ;
						jProgressBar2.setProgress(i *  100 / iterations);            
					}
				}
				
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						lbl2.setText(String.valueOf(System.currentTimeMillis() - l));				
					}
				});
			}
		}).start();

	}
}



O button2 que executa o método setUp2() e sempre ganha no desempenho.
Vale ressaltar que, o método setUp() faz menos testes que o método setUp2().
Venho pedir ajuda aos colegas do guj ,uma explicação para esse comportamento.

O tempo de um teste é desprezível, mas o tempo de setar uma barra de progresso, mesmo que ela não saia do lugar, não é desprezível, e é isso que está pegando no seu programa.

A seguinte operação é bem lenta, e você deve fazer o possível para economizar chamadas a setProgress.

jProgressBar1.setProgress(i *  100 / iterations);     

Uma forma boba de fazer isso é calcular o valor de i * 100 / iterations, e salvar em uma variável auxiliar. Você somente deve chamar novamente jProgressBar1.setProgress quando o valor mudar.

[quote=entanglement]O tempo de um teste é desprezível, mas o tempo de setar uma barra de progresso, mesmo que ela não saia do lugar, não é desprezível, e é isso que está pegando no seu programa.

A seguinte operação é bem lenta, e você deve fazer o possível para economizar chamadas a setProgress.

jProgressBar1.setProgress(i *  100 / iterations);     

Uma forma boba de fazer isso é calcular o valor de i * 100 / iterations, e salvar em uma variável auxiliar. Você somente deve chamar novamente jProgressBar1.setProgress quando o valor mudar. [/quote]

foi o q fizemos.

apesar q achei q poderiam ter tratado melhor isso.

Pelo que imagino, além de atualizar a tela (ou seja, recalcular a posição da barra e outras coisas, e redesenhar o componente etc.) esse setProgress deve também chamar eventuais Listeners e outras coisas mais.

De modo geral, não é bom supor que a API “se vira” para otimizar certas coisas que você mesmo pode otimizar no seu código.
Por exemplo, você chamar repetidas vezes setProgress com o mesmo valor provavelmente irá ser mais lento que você testar antes e só chamar quando necessário.

Oi,

Eu não sei se vem ao caso, mas toda negação é motivo de atraso.

not in, not equals, != anything etc…

Tchauzin!

[quote=lina]Oi,

Eu não sei se vem ao caso, mas toda negação é motivo de atraso.

not in, not equals, != anything etc…

Tchauzin![/quote]

Lina-san, nesse caso eles estão afirmando que mesmo fazendo um teste a mais, a rotina está sendo mais rápida (eles estavam achando que só porque faziam um teste a mais a rotina seria mais lenta).

É mais ou menos como afirmar: se você estiver com o log no modo debug DESABILITADO, o que é mais rápido, testar para ver se o log está desabilitado e se não estiver, chamar a rotina de log, ou então chamar a rotina de log logo de cara, que ela se vira para checar se o debug está desabilitado? Embora você tenha de escrever mais código, normalmente

if (logger.isDebugEnabled()) {
     logger.debug ("a" + b() + c(d, "e", f()) + "g");
}

é mais rápido que

     logger.debug ("a" + b() + c(d, "e", f()) + "g");

embora seja feito um teste a mais. É que a avaliação dos parâmetros (no primeiro caso) é evitada e no segundo caso é obrigatória, e é essa avaliação dos parâmetros que pode ser demorada.

Oi,

Saquei! Tinha entendido completamente errado. Pensei que a 2 demorava e a 1 era a mais rápida. Mesmo assim, a minha explicação estaria furada.

Tchauzin!

na relidade esse techo ficou errado:

for (int i = 0; i < iterations; i++) { if(teste != i){ teste = i ; jProgressBar2.setProgress(i * 100 / iterations); } }

seria isso:

int p; for (int i = 0; i < iterations; i++) { p = i * 100 / iterations; if(teste != p){ teste = p ; jProgressBar2.setProgress(i); } }

Ou seja, você implementou o que eu chamei de forma “boba” de economizar processamento.
É boba mas é eficiente - como sabemos, código muito “esperto” (obscuro) pode dar problemas.
Se você precisa de um gênio para escrever uma linha de código, precisa de dois para consertá-la :slight_smile: