创建自己的自定义适配器时,getView()方法如何工作?


101

我的问题是:

  1. LayoutInflater的确切功能是什么?
  2. 为什么我阅读的所有文章都首先检查convertview是否为null?当它为null时,它是什么意思;当它不是null时,它是什么意思?
  3. 此方法接受的父参数是什么?

Answers:


115

1:LayoutInflater会使用您的布局XML文件,并根据其内容创建不同的View对象。

2:构建适配器是为了重用视图,当滚动视图以使其不再可见时,可以将其用于出现的新视图之一。此重用的View是convertView。如果为null,则意味着没有回收的View,我们必须创建一个新的View,否则我们应该使用它来避免创建一个新View。

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

注意LayoutInflaterparent可以使用用作参数,以及如何convertView重用。


5
当所有Iten都遵循相同的布局时,Convertview == null很有用。例如,当您需要检查单选按钮或选中按钮并根据每个项目更改布局时,您需要重新充气,否则它将获取缓存的视图。
sagits's

无需再充气。只是您需要在getview中编写switch或if-else阶梯并根据您的情况对视图进行充气,覆盖public int getItemViewType(int position)和public int getViewTypeCount()。@sagits
Prashanth Debbadwar 2015年

如果语句通常可以正常工作,但是在使用单选按钮,编辑文本以及使用缓存的视图时遇到麻烦的这类东西时,关于堆栈溢出的这些东西会有一些问题。
射手2015年

71

getView()在适配器的方法是对的生成项目的视图ListViewGallery...

  1. LayoutInflater用于获取您在布局中的XML定义视图对象(根对象,通常是一个LinearLayoutFrameLayoutRelativeLayout

  2. convertView用于回收。假设您有一个列表视图,一次只能显示10个项目,并且当前正在显示项目1->项目10。向下滚动一个项目时,项目1将不在屏幕上,并且项目11将显示。要为项目11生成视图,将调用getView()方法, convertView这是项目1的视图(现在不再需要)。因此,为项目11创建一个新的View对象(这很昂贵),为什么不重复使用convertView?=>我们只是检查是否convertView为null,如果为null则创建新视图,否则重新使用convertView

  3. parentView 是ListView或Gallery ...包含项目的视图,其中 getView()生成。

注意:您不必直接调用此方法,只需实现它即可告诉父视图如何生成项目的视图。


2
对于parentView优秀的解释,找不到更好的解释比这一个,+1
艾哈迈德·伊斯梅尔·阿德尔

惊人的解释!
gabi 2015年

很棒的解释+1
tpk 16/09/21

8

您可以看一下有关列表视图的视频。它来自去年的Google IO,在我看来仍然是最好的列表视图演练。

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

  1. 它将布局(res / layout /文件夹上的xml文件)扩展为java对象(如LinearLayout和其他视图)。

  2. 观看视频,将使您了解转换视图的用途,基本上是一个循环视图,等待您重用,以避免创建新对象并减慢列表滚动速度。

  3. 允许您从适配器引用列表视图。


5

LayoutInflater的确切功能是什么?

使用XML进行设计时,所有UI元素都只是标记和参数。在使用这些UI元素(例如TextView或LinearLayout)之前,需要创建与这些xml元素相对应的实际对象。这就是充气机的用途。充气机使用这些标签及其相应的参数来创建实际对象并设置所有参数。之后,您可以使用findViewById()获得对UI元素的引用。

为什么我阅读的所有文章都首先检查convertview是否为null?当它为null时,它是什么意思;当它不是null时,它是什么意思?

这是一个有趣的。您会看到,每次绘制列表中的项目时都会调用getView()。现在,必须先创建该项目,然后才能对其进行绘制。现在,convertView基本上是最后一个用于绘制项目的视图。在getView()中,您首先将xml膨胀,然后使用findByViewID()获得listitem的各种UI元素。当我们检查(convertView == null)时,我们要做的是检查视图是否为null(对于第一项),然后创建它;否则,如果该视图已经存在,则重新使用它,而无需再次执行膨胀过程。使效率更高。

您还必须在getView()中遇到ViewHolder的概念。这使列表更有效。我们要做的是创建一个Viewholder并存储对我们在膨胀后获得的所有UI元素的引用。这样,我们可以避免调用大量的findByViewId()并节省大量时间。该ViewHolder是在(convertView == null)条件下创建的,并使用setTag()存储在convertView中。在else循环中,我们只是使用getView()将其获取回来并重新使用它。

此方法接受的父参数是什么?

父级是一个ViewGroup,由getView()创建的视图最终附加到该ViewGroup。现在,在您的情况下,这将是ListView。

希望这可以帮助 :)


4
  1. 布局充气器将外部XML充气/添加到当前视图。

  2. getView()被多次调用,包括滚动时。因此,如果视图已经膨胀,我们就不想再做一次,因为膨胀是一个代价高昂的过程。这就是为什么我们先检查它是否为null然后对其进行膨胀。

  3. 父视图是列表的单个单元格。


3
此处对父视图的解释不正确。这将是ListView而不是ListItem
Varun Jain

2

LayoutInflater用于生成ListView商品或商品中XML的动态视图onCreateView片段中。

ConvertView基本上用于回收当前不在视图中的视图。假设您有一个可滚动的页面ListView。上下滚动时,convertView将显示已滚动的视图。重用可以节省内存。

方法的parent参数getView()提供对具有listView的父布局的引用。假设您想获取父XML中可以使用的任何项目的ID:

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

 }

1

getView()方法来创建新的ViewViewGroup为每行Listview或微调。您可以定义此ViewViewGroup在一个Layout XML文件res/layout夹,可以给它的参考Adapter类对象。

如果数组中有4个项目传递给适配器。getView()方法将为Adaper的4行创建4个视图。

LayoutInflater类具有一个方法inflate(),可以从XML资源布局创建视图对象。


0

您还可以在Adapter.java文件的Adapter接口上找到有关getView的有用信息。它说;

/**
 * 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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.