2010-09-30 3 views
1

Когда пользователь выбирает ListViewItem, я меняю фоновое изображение этой строки. Это происходит очень медленно. Я не уверен, почему?getView() для ArrayAdapter медленный

OnItemClickListener

listView.setOnItemClickListener(new OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> 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; 
      } 
     }); 
    } 

Оригинальный код:

private class QuoteAdapter extends ArrayAdapter<Quote> { 

     private ArrayList<Quote> items; 
     // used to keep selected position in ListView 
     private int selectedPos = -1; // init value for not-selected 

     public QuoteAdapter(Context context, int textViewResourceId, ArrayList<Quote> 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 < 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; 
     } 
    } 

UPDATE: Адаптер с ViewHolder рисунком

private class QuoteAdapter extends ArrayAdapter<Quote> { 

     private ArrayList<Quote> items; 
     // used to keep selected position in ListView 
     private int selectedPos = -1; // init value for not-selected 

     public QuoteAdapter(Context context, int textViewResourceId, ArrayList<Quote> 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 < 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; 
     } 
    } 

ответ

1

Ваш getView() - o.k. (хотя это можно сделать быстрее). Я думаю, проблема связана с setSelectedPosition(). Вы вызываете notifyDataSetChanged(), который вызывает слишком много просмотров для перерисовки. Вы должны обработать исходный фон с выдержкой из состояния.

+0

Я бы обрабатывать фон выбора с запоминанием состояния однако я хочу, чтобы фон представления оставался выбранным. Я не знаю другого способа сделать это, чем изменить фон представления. –

+0

Это имеет смысл. Но почему бы не назвать notifyDatasetChanged()? Я считаю, что должен быть способ изменить только один вид, не перекрасив их всех. –

+0

Да, кажется, что если я не вызываю notifyDatasetChanged(), несколько видов могут иметь фон выбора. Я хочу, чтобы только один вид имел фоновый фон выбора за раз. Вы знаете какой-либо другой способ, который я могу обновить, без необходимости перекрашивать их все? –

0

Хорошо, я признаю, что не знаю, насколько велик ваш набор данных, и я не знаю, сколько видимых элементов отображается на экране за раз, но если вы можете гарантировать, что ваш список находится в режиме единого выбора, с правильным состоянием другого цвета

<selector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:dither="true" > 
    <item 
     android:state_pressed="true" 
     android:state_enabled="true" 
     android:drawable="@color/my_color" /> 

    <item 
     android:state_selected="true" 
     android:drawable="@color/my_color" /> 
    </item> 

    <item 
     android:state_focused="true" 
     android:state_enabled="true" 
     android:drawable="@android:drawable/list_selector_background" /> 
</selector> 

Это должно работать автоматически.

Если вы хотите, чтобы выбранное состояние отображалось так, как будто оно липкое, вы также можете сделать многозадачность listView и перехватить вызов, чтобы установить выделение для отмены предыдущих.

Если вы все еще намерены установить фон вручную, я бы оптимизировал ваш метод getView, используя шаблон ViewHolder, который используется другими пользователями. Это позволит вашему перекрашивать быть дешевле и выглядят, как будто это на самом деле не происходит (опять же в зависимости от количества элементов на экране в то время)

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List14.html

+0

Ознакомьтесь с моим последним обновлением. Я реализовал шаблон ViewHolder, но не уверен, правильно ли настроен фоновый ресурс? –

Смежные вопросы