Listview too slow to load XML

Asked

Viewed 564 times

0

It’s taking too long to load a few items, it takes several seconds, and to load a lot of items, it never loads. I used the same XML reading algorithm, with a simple list and loaded very fast, but in my custom Listview it takes a long time, I tried using Viewholder, but it didn’t work. Check out my classes:

Adapter

public class AdapterSegmento extends BaseAdapter {


private ArrayList<Segmento> itens;
private Activity myContext;
private LayoutInflater mLayoutInflater;
public AdapterSegmento(Context context, ArrayList<Segmento> itens) {
    //Itens que preencheram o listview
    this.itens = itens;
    //responsavel por pegar o Layout do item.

}

/**
 * Retorna a quantidade de itens
 *
 * @return
 */
public int getCount() {
    return itens.size();
}

/**
 * Retorna o item de acordo com a posicao dele na tela.
 *
 * @param position
 * @return
 */
public Segmento getItem(int position) {
    return itens.get(position);
}

/**
 * Sem implementação
 *
 * @param position
 * @return
 */

public long getItemId(int position) {
    return position;
}


static class ViewHolder{
    TextView tvName;
    TextView tvDescription;
    ImageView imagem;
}
@Override
public View getView(int position, View view, ViewGroup parent) {

  View vi = view;             //trying to reuse a recycled view
  ViewHolder holder = null;

  if (vi == null) {
      //The view is not a recycled one: we have to inflate
      vi = mLayoutInflater.inflate(R.layout.empresa_item, parent, false);
      holder = new ViewHolder();

      holder.tvName = (TextView) vi.findViewById(R.id.nomeEmpresa);
      holder.tvDescription = (TextView) vi.findViewById(R.id.subtitulo);
     // holder.imagem = (ImageView) vi.findViewById(R.id.imagemSegmento);
      vi.setTag(holder);
  } else {
      // View recycled !
      // no need to inflate
      // no need to findViews by id
      holder = (ViewHolder) vi.getTag();
  }

 Segmento item = itens.get(position);

 holder.tvName.setText(item.getNome());
 holder.tvDescription.setText(item.getSubtitulo());
     return vi;
}
}

My View

public class SegmentoView extends Util implements OnItemClickListener {

private ListView listView;
private AdapterSegmento adapterEmpresa;
private ArrayList<Segmento> itensEmpresa;
XmlReader reader;
String URL;
ProgressDialog dialog;

@SuppressLint("NewApi") @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // carrega o layout onde contem o ListView
    setContentView(R.layout.empresa_lista);
    ActionBar bar = getActionBar();
    bar.hide();


    //Carregar XML
    reader = new XmlReader("http://www.itcuties.com/feed/");



    itensEmpresa = new ArrayList<Segmento>();
    try {
        for (int i = 0; i < reader.getItems().size(); ++i) {
            Segmento segmento = new Segmento();

            segmento.setNome(reader.getItems().get(i).getNome());
            segmento.setLink(reader.getItems().get(i).getLink());

            itensEmpresa.add(segmento);

        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    // Cria o adapter
    adapterEmpresa = new AdapterSegmento(this, itensEmpresa);

    // Define o Adapter
    listView.setAdapter(adapterEmpresa);
    // Cor quando a lista é selecionada para ralagem.
    listView.setCacheColorHint(Color.TRANSPARENT);

}
}

Can someone help me?

  • It would not be better to use a string array to make Listview options?

  • I did it now, switched to Adapter and view to Segment[] items; and gave anyway.

  • Any ideas? Someone?

  • It puts a bonus on the question. It is the lawful means of attracting attention.

  • I didn’t understand, how so?

  • Put a bonus/reward/bonus on your question. It will cost you reputation, but it’s worth more :D

  • Have you considered using Asynctask?

  • I do not know how to use, if you can show me how to answer as I would be in my context I would very much appreciate

Show 4 more comments

2 answers

1


Cause

The slowness in your case is due to each iteration in the following section:

for (int i = 0; i < reader.getItems().size(); ++i) {
    // código omitido
}

For every iteration the method reader.getItems().size() is called to be compared with the i, and every call made to the method reader.getItems a web query is performed.

Solution

Instead of calling such a method use a variable to store the return of reader.getItems and so the size of this list can be used in for. Thus remaining:

items = reader.getItems();
itensEmpresa = new ArrayList<Segmento>();
try {
    for (int i = 0; i < items.size(); ++i) {
        Segmento segmento = new Segmento();

        segmento.setNome(items.get(i).getNome());
        segmento.setLink(items.get(i).getLink());

        itensEmpresa.add(segmento);
    }
} catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
  • You put the Asynctask to run inside the Adapter?

  • I asked you why you said "from Adapter to receive an asynctask", I guess I didn’t get it right then.

  • Strange happen a Nullpointerexception... the Arraylist is initialized when passing in the Adapter constructor.

  • You cannot run an Asynctask from an Adapter. You must run it from Mainthread, that is, an Activity that in your case is the Segmentoview class.

  • @War Lock can we talk through Hangout? Is that I am accessing by mobile because I only have internet in it at the moment.

  • Perfect, thank you!

Show 2 more comments

0

Place NULL where you are

BEFORE

 vi = mLayoutInflater.inflate(R.layout.empresa_item, parent, false);

AFTERWARD

 vi = mLayoutInflater.inflate(R.layout.empresa_item, null, false);

You can also exchange this line for:

 vi = LayoutInflater.from(getContext(), R.layout.empresa_item, null);

Then you can check the time you spend for that line:

//Carregar XML
    reader = new XmlReader("http://www.itcuties.com/feed/");

Using Log, for example:

 Log.d("teste",  new Date());
//Carregar XML
    reader = new XmlReader("http://www.itcuties.com/feed/");
Log.d("teste", new Date());

Obviously, you can get a better time in place of this new Date() I used, but it was just to illustrate. Maybe the bottleneck is there.

You can use Asynctask or Asynctaskloader to perform this load.

Here you check how to use Asynctask:

http://developer.android.com/reference/android/os/AsyncTask.html

Here you check how to use Asynctaskloader:

http://developer.android.com/reference/android/content/AsyncTaskLoader.html

Studies Androidannotations.

http://androidannotations.org/

It’s even better than the Viewholder pattern ;)

Using Annotations in your Activity there, to give you an idea, you wouldn’t even need Asynctask, because it would look like this:

ProgressDialog dialog;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // carrega o layout onde contem o ListView
    setContentView(R.layout.empresa_lista);
    ActionBar bar = getActionBar();
    bar.hide();

     // Cor quando a lista é selecionada para ralagem.
    listView.setCacheColorHint(Color.TRANSPARENT);


    dialog = new ProgressDialog(this);
    dialog.setMessage("Carregando dados...");
    dialog.show();

     //chamada para carregamento dos dados
     loadData();
}


@Background
void loadData(){

    //Carregar XML
    XmlReader reader = new XmlReader("http://www.itcuties.com/feed/");

    ArrayList itensEmpresa = new ArrayList<Segmento>();
    try {
        for (int i = 0; i < reader.getItems().size(); ++i) {
            Segmento segmento = new Segmento();

            segmento.setNome(reader.getItems().get(i).getNome());
            segmento.setLink(reader.getItems().get(i).getLink());

            itensEmpresa.add(segmento);

        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}


@UIThread
void createAdapter(ArrayList<Segmento> items){

    // Cria o adapter
    adapterEmpresa = new AdapterSegmento(this, items);
    // Define o Adapter
    listView.setAdapter(adapterEmpresa);

    dialog.dismiss();


}

(If there are any mistakes up there, give a discount, because I did not put this to compile XD)

  • I made the basic changes that you passed, and nothing, I used annotations and nothing, I showed with log the line of the Reader, and it was very fast, but inside the for, it takes 10 seconds.

  • Then you know the bottleneck is in this. To start optimizing, try assigning an object right at the beginning, to that line: Reader.getItems(). get(i), instead of doing it twice. The operation of . get(i) we know that complexity is O(1), but perhaps getItems() is not.

Browser other questions tagged

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