Как работает метод getView () при создании собственного адаптера?

102

Мои вопросы:

  1. Какова именно функция LayoutInflater?
  2. Почему все статьи, которые я прочитал, сначала проверяют, имеет ли convertview значение null? Что это значит, когда он равен нулю, и что это значит, когда это не так?
  3. Какой родительский параметр принимает этот метод?
GrowinMan
источник

Ответы:

115

1: Программа LayoutInflaterберет ваши XML-файлы макета и создает из их содержимого различные View-объекты.

2: Адаптеры созданы для повторного использования представлений, когда представление прокручивается так, что оно больше не отображается, его можно использовать для одного из новых отображаемых представлений. Этот повторно используемый вид представляет собой файл convertView. Если это значение null, это означает, что переработанного представления нет и мы должны создать новый, в противном случае мы должны использовать его, чтобы избежать создания нового.

3: parentПредоставляется так, чтобы вы могли расширить свое представление для правильных параметров макета.

Все это вместе можно использовать для эффективного создания представления, которое появится в вашем списке (или другом представлении, требующем адаптера):

public View getView(int position, @Nullable View convertView, ViewGroup parent){
    if (convertView == null) {
        //We must create a View:
        convertView = inflater.inflate(R.layout.my_list_item, parent, false);
    }
    //Here we can do changes to the convertView, such as set a text on a TextView 
    //or an image on an ImageView.
    return convertView;
}

Обратите внимание на использование LayoutInflater, которое parentможет использоваться в качестве аргумента для него, и на то, как convertViewоно используется повторно.

Jave
источник
5
Convertview == null полезен, когда все ваши объекты следуют одному и тому же макету. Когда вам нужно проверить наличие переключателя или отмеченной кнопки, например, и изменить макет на основе каждого элемента, вам нужно повторно накачать, или он получит кешированное представление.
sagits
Нет необходимости повторно надувать воздух. Просто вам нужно написать переключатель или лестницу if-else в getview и раздувать представления в соответствии с вашим случаем, переопределить public int getItemViewType (int position) и public int getViewTypeCount (). @sagits
Прашант Деббадвар
Если операторы обычно работают, но при использовании переключателей, редактировании текстов и подобных вещах у меня возникли проблемы с использованием кешированных представлений, есть некоторые вопросы относительно этого материала при переполнении стека.
сагитс
71

getView()Способ адаптер для зрения генерирующего элемента из ListView, Gallery...

  1. LayoutInflaterиспользуется , чтобы получить вид объекта , который вы определяете в макет XML (корневой объект, обычно LinearLayout, FrameLayoutили RelativeLayout)

  2. convertViewподлежит переработке. Скажем, у вас есть представление списка, которое может отображать только 10 элементов за раз, и в настоящее время оно отображает элемент 1 -> элемент 10. Когда вы прокручиваете один элемент вниз, элемент 1 будет за пределами экрана, а элемент 11 будет отображаться. . Чтобы сгенерировать представление для элемента 11, будет вызван метод getView (), и convertViewвот вид элемента 1 (который больше не нужен). Поэтому вместо этого создайте новый объект View для элемента 11 (что дорого), почему бы не использовать повторно convertView? => мы просто проверяем, convertViewявляется ли null или нет, если null создает новое представление, иначе используется повторно convertView.

  3. parentView- это ListView или Gallery ... который содержит getView()созданное представление элемента .

Примечание : вы не вызываете этот метод напрямую, просто нужно реализовать его, чтобы сообщить родительскому представлению, как сгенерировать представление элемента.

Ань Туан
источник
2
ОТЛИЧНОЕ объяснение для parentView, лучшего объяснения не найти, +1
Ахмед Адель Исмаил
Прекрасное объяснение!
Габи
отличное объяснение +1
tpk
8

Вы можете посмотреть это видео о просмотре списка. Это с прошлых лет Google IO и до сих пор, на мой взгляд, лучший просмотр списков.

http://www.youtube.com/watch?v=wDBM6wVEO70

  1. Он раздувает макеты (файлы xml в папке res / layout /) в объекты Java, такие как LinearLayout и другие представления.

  2. Посмотрите видео, и вы узнаете, что такое преобразованное представление, в основном это переработанное представление, ожидающее повторного использования вами, чтобы избежать создания нового объекта и замедления прокрутки вашего списка.

  3. Позволяет ссылаться на представление списка из адаптера.

эрбсмен
источник
5

Какова именно функция LayoutInflater?

Когда вы проектируете с использованием XML, все ваши элементы пользовательского интерфейса - это просто теги и параметры. Прежде чем вы сможете использовать эти элементы пользовательского интерфейса (например, TextView или LinearLayout), вам необходимо создать фактические объекты, соответствующие этим элементам xml. Вот для чего нужен надувной насос. Inflater использует эти теги и соответствующие им параметры для создания фактических объектов и установки всех параметров. После этого вы можете получить ссылку на элемент пользовательского интерфейса с помощью findViewById ().

Почему все статьи, которые я прочитал, сначала проверяют, имеет ли convertview значение null? Что это значит, когда он равен нулю, и что это значит, когда это не так?

Это интересно. Видите ли, getView () вызывается каждый раз, когда отрисовывается элемент в списке. Теперь, прежде чем элемент можно будет нарисовать, его нужно создать. Теперь convertView в основном является последним используемым представлением для рисования элемента. В getView () вы сначала раздуваете xml, а затем используете findByViewID () для получения различных элементов пользовательского интерфейса элемента списка. Когда мы проверяем (convertView == null), мы проверяем, что если представление имеет значение null (для первого элемента), то создаем его, иначе, если оно уже существует, повторно используем его, нет необходимости снова проходить процесс надувания . Делает это намного более эффективным.

Вы также должны были столкнуться с концепцией ViewHolder в getView (). Это делает список более эффективным. Что мы делаем, так это создаем зрителя и сохраняем ссылку на все элементы пользовательского интерфейса, которые мы получили после наполнения. Таким образом, мы можем избежать многочисленных вызовов findByViewId () и сэкономить много времени. Этот ViewHolder создается в условии (convertView == null) и сохраняется в convertView с помощью setTag (). В цикле else мы просто получаем его обратно с помощью getView () и повторно используем.

Какой родительский параметр принимает этот метод?

Родителем является ViewGroup, к которой окончательно прикрепляется ваше представление, созданное с помощью getView (). Теперь в вашем случае это будет ListView.

Надеюсь это поможет :)

Шубхаю
источник
4
  1. Инфлятор макета раздувает / добавляет внешний XML к вашему текущему представлению.

  2. getView () вызывается много раз, в том числе при прокрутке. Так что, если у него уже есть завышенное представление, мы не хотим делать это снова, так как раздутие - дорогостоящий процесс ... вот почему мы проверяем, является ли его значение null, а затем раздуваем его.

  3. Родительское представление - это отдельная ячейка вашего списка.

нгеш
источник
3
Родительский вид здесь объясняется неправильно. Это будет ListView, а не ListItem
Варун Джайн
2

LayoutInflaterиспользуется для создания динамических представлений XML для ListViewэлемента или onCreateViewфрагмента.

ConvertViewв основном используется для повторного использования представлений, которых сейчас нет в представлении. Скажем, у вас есть прокручиваемый ListView. При прокрутке вниз или вверх convertViewотображается вид, который был прокручен. Это повторное использование экономит память.

Параметр parent getView()метода дает ссылку на родительский макет, который имеет listView. Допустим, вы хотите получить идентификатор любого элемента родительского XML, который вы можете использовать:

ViewParent nv = parent.getParent();

while (nv != null) {

    if (View.class.isInstance(nv)) {
        final View button = ((View) nv).findViewById(R.id.remove);
        if (button != null) {
            // FOUND IT!
            // do something, then break;
            button.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Log.d("Remove", "Remove clicked");

                    ((Button) button).setText("Hi");
                }
            });
        }
        break;
    }

 }
user936414
источник
1

getView()метод создать новый Viewили ViewGroupдля каждой строки Listviewили Spinner. Вы можете определить это Viewили ViewGroupв Layout XMLфайле в res/layoutпапке и можете дать ссылку на негоAdapter класс Object.

если у вас есть 4 элемента в массиве, переданном адаптеру. getView()Метод создаст 4 View для 4 рядов Adaper.

Класс LayoutInflater имеет метод inflate (), который создает объект представления из макета ресурса XML.

Рави1187342
источник
0

Вы также можете найти полезную информацию о getView в интерфейсе адаптера в файле Adapter.java. Он говорит;

/**
 * Get a View that displays the data at the specified position in the data set. You can either
 * create a View manually or inflate it from an XML layout file. When the View is inflated, the
 * parent View (GridView, ListView...) will apply default layout parameters unless you use
 * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
 * to specify a root view and to prevent attachment to the root.
 * 
 * @param position The position of the item within the adapter's data set of the item whose view
 *        we want.
 * @param convertView The old view to reuse, if possible. Note: You should check that this view
 *        is non-null and of an appropriate type before using. If it is not possible to convert
 *        this view to display the correct data, this method can create a new view.
 *        Heterogeneous lists can specify their number of view types, so that this View is
 *        always of the right type (see {@link #getViewTypeCount()} and
 *        {@link #getItemViewType(int)}).
 * @param parent The parent that this view will eventually be attached to
 * @return A View corresponding to the data at the specified position.
 */
View getView(int position, View convertView, ViewGroup parent);
Хамза Полат
источник