getView () для ArrayAdapter работает медленно - PullRequest
1 голос
/ 30 сентября 2010

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

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;
        }
    }

ОБНОВЛЕНИЕ: Адаптер с шаблоном 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;
        }
    }

Ответы [ 2 ]

1 голос
/ 30 сентября 2010

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

0 голосов
/ 30 сентября 2010

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

<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

...