title: getView() for ArrayAdapter is slow
body: <p>When a user selects a <code>ListViewItem</code>, I am changing that row's background image. This seems to happen very slowly. I'm not sure why?</p>
  
  <p><strong>OnItemClickListener</strong></p>
  
  <pre><code>listView.setOnItemClickListener(new OnItemClickListener() {
              @Override
              public void onItemClick(AdapterView&lt;?&gt; a, View v, int position, long id) {
                  //quotesAdapter.setSelectedPosition(position);
                  setupDetailView(position);
                  setupChartView(position);
                  setupARView(position);
                  emptyView.setVisibility(View.INVISIBLE);
  
                  ViewGroup vg = (ViewGroup)v;
  
                  TextView nameText = (TextView) vg.findViewById(R.id.nameText);
                  TextView priceText = (TextView) vg.findViewById(R.id.priceText);
                  TextView changeText = (TextView) vg.findViewById(R.id.changeText);
  
                  //change the old row back to normal
                  if(oldView != null){
                      oldView.setBackgroundResource(R.drawable.stocks_gradient);
                      nameText.setTextAppearance(getApplicationContext(), R.style.BlueText);
                      priceText.setTextAppearance(getApplicationContext(), R.style.BlueText);
                      changeText.setTextAppearance(getApplicationContext(), R.style.BlueText);
                  }
  
                  //change the selected row
                  v.setBackgroundResource(R.drawable.stocks_selected_gradient);
                  nameText.setTextColor(Color.WHITE);
                  priceText.setTextColor(Color.WHITE);
                  changeText.setTextColor(Color.WHITE);
  
                  //keep a reference to the old row, for the next time user clicks
                  oldView = v;
              }
          });
      }
  </code></pre>
  
  <p><strong>Original Code:</strong></p>
  
  <pre><code>private class QuoteAdapter extends ArrayAdapter&lt;Quote&gt; {
  
          private ArrayList&lt;Quote&gt; items;
          // used to keep selected position in ListView
          private int selectedPos = -1; // init value for not-selected
  
          public QuoteAdapter(Context context, int textViewResourceId, ArrayList&lt;Quote&gt; items) {
              super(context, textViewResourceId, items);
              this.items = items;
          }
  
          public void setSelectedPosition(int pos) {
              selectedPos = pos;
              // inform the view of this change
              notifyDataSetChanged();
          }
  
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
              View v = convertView;
              if (v == null) {
                  LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                  v = vi.inflate(R.layout.mainrow, null);
              }
  
              TextView nameText = (TextView) v.findViewById(R.id.nameText);
              TextView priceText = (TextView) v.findViewById(R.id.priceText);
              TextView changeText = (TextView) v.findViewById(R.id.changeText);
  
              // change the row color based on selected state
              if (selectedPos == position) {
                  v.setBackgroundResource(R.drawable.stocks_selected_gradient);
                  nameText.setTextColor(Color.WHITE);
                  priceText.setTextColor(Color.WHITE);
                  changeText.setTextColor(Color.WHITE);
              } else {
                  v.setBackgroundResource(R.drawable.stocks_gradient);
                  nameText.setTextAppearance(getApplicationContext(), R.style.BlueText);
                  priceText.setTextAppearance(getApplicationContext(), R.style.BlueText);
                  changeText.setTextAppearance(getApplicationContext(), R.style.BlueText);
              }
  
              Quote q = items.get(position);
              if (q != null) {
                  if (nameText != null) {
                      nameText.setText(q.getSymbol());
                  }
                  if (priceText != null) {
                      priceText.setText(q.getLastTradePriceOnly());
                  }
                  if (changeText != null) {
                      try {
                          float floatedChange = Float.valueOf(q.getChange());
                          if (floatedChange &lt; 0) {
                              if (selectedPos != position)
                                  changeText.setTextAppearance(getApplicationContext(), R.style.RedText); // red
                          } else {
                              if (selectedPos != position)
                                  changeText.setTextAppearance(getApplicationContext(), R.style.GreenText); // green
                          }
                      } catch (NumberFormatException e) {
                          System.out.println("not a number");
                      } catch (NullPointerException e) {
                          System.out.println("null number");
                      }
                      changeText.setText(q.getChange() + " (" + q.getPercentChange() + ")");
                  }
              }
              return v;
          }
      }
  </code></pre>
  
  <p><strong>UPDATE: Adapter with ViewHolder pattern</strong></p>
  
  <pre><code>   private class QuoteAdapter extends ArrayAdapter&lt;Quote&gt; {
  
          private ArrayList&lt;Quote&gt; items;
          // used to keep selected position in ListView
          private int selectedPos = -1; // init value for not-selected
  
          public QuoteAdapter(Context context, int textViewResourceId, ArrayList&lt;Quote&gt; items) {
              super(context, textViewResourceId, items);
              this.items = items;
          }
  
          public void setSelectedPosition(int pos) {
              selectedPos = pos;
              // inform the view of this change
              notifyDataSetChanged();
          }
  
          @Override
          public View getView(int position, View convertView, ViewGroup parent) {
              View v = convertView;
              ViewHolder holder; // to reference the child views for later actions
  
              if (v == null) {
                  LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                  v = vi.inflate(R.layout.mainrow, null);
  
                  // cache view fields into the holder
                  holder = new ViewHolder();
                  holder.nameText = (TextView) v.findViewById(R.id.nameText);
                  holder.priceText = (TextView) v.findViewById(R.id.priceText);
                  holder.changeText = (TextView) v.findViewById(R.id.changeText);
  
                  // associate the holder with the view for later lookup
                  v.setTag(holder);
              }
              else {
                  // view already exists, get the holder instance from the view
                  holder = (ViewHolder)v.getTag();
              }
  
              // change the row color based on selected state
              if (selectedPos == position) {
                  v.setBackgroundResource(R.drawable.stocks_selected_gradient);
                  holder.nameText.setTextColor(Color.WHITE);
                  holder.priceText.setTextColor(Color.WHITE);
                  holder.changeText.setTextColor(Color.WHITE);
              } else {
                  v.setBackgroundResource(R.drawable.stocks_gradient);
                  holder.nameText.setTextAppearance(getApplicationContext(), R.style.BlueText);
                  holder.priceText.setTextAppearance(getApplicationContext(), R.style.BlueText);
                  holder.changeText.setTextAppearance(getApplicationContext(), R.style.BlueText);
              }
  
              Quote q = items.get(position);
              if (q != null) {
                  if (holder.nameText != null) {
                      holder.nameText.setText(q.getSymbol());
                  }
                  if (holder.priceText != null) {
                      holder.priceText.setText(q.getLastTradePriceOnly());
                  }
                  if (holder.changeText != null) {
                      try {
                          float floatedChange = Float.valueOf(q.getChange());
                          if (floatedChange &lt; 0) {
                              if (selectedPos != position)
                                  holder.changeText.setTextAppearance(getApplicationContext(), R.style.RedText); // red
                          } else {
                              if (selectedPos != position)
                                  holder.changeText.setTextAppearance(getApplicationContext(), R.style.GreenText); // green
                          }
                      } catch (NumberFormatException e) {
                          System.out.println("not a number");
                      } catch (NullPointerException e) {
                          System.out.println("null number");
                      }
                      holder.changeText.setText(q.getChange() + " (" + q.getPercentChange() + ")");
                  }
              }
              return v;
          }
      }
  </code></pre>