106

我的问题是:

  1. LayoutInflater 的功能到底是什么?
  2. 为什么我读过的所有文章都首先检查 convertview 是否为空?当它为空时是什么意思,当它不是时又是什么意思?
  3. 这个方法接受的父参数是什么?
4

9 回答 9

119

1:LayoutInflater获取您的布局 XML 文件并根据其内容创建不同的视图对象。

2:适配器是为重用视图而构建的,当滚动视图以使其不再可见时,它可以用于出现的新视图之一。这个重用的 View 是convertView. 如果为null,则表示没有回收的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;
}

注意 的使用LayoutInflater,它parent可以用作它的参数,以及如何convertView重用。

于 2012-04-12T08:52:24.163 回答
72

getView()Adapter 中的方法用于生成项目的 a ListView, Gallery,...视图

  1. LayoutInflater用于获取您在布局 xml 中定义的 View 对象(根对象,通常为LinearLayoutFrameLayoutRelativeLayout

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

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

注意:你不直接调用这个方法,只需要实现它来告诉父视图如何生成项目的视图。

于 2012-04-12T08:56:56.683 回答
8

你可以看看这个关于列表视图的视频。它来自去年的 Google IO,并且仍然是我心目中关于列表视图的最佳演练。

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

  1. 它将布局(res/layout/ 文件夹中的 xml 文件)膨胀到 java 对象中,例如 LinearLayout 和其他视图。

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

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

于 2012-04-12T08:42:55.130 回答
5

LayoutInflater 的功能到底是什么?

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

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

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

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

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

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

希望这可以帮助 :)

于 2012-04-12T09:15:00.160 回答
4
  1. 布局充气器将外部 XML 膨胀/添加到当前视图。

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

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

于 2012-04-12T08:44:16.110 回答
2

LayoutInflater用于为ListView项目或onCreateView片段生成 XML 的动态视图。

ConvertView基本上是用来回收当前不在视图中的视图。假设您有一个可滚动的ListView. 在向下或向上滚动时,convertView给出被滚动的视图。这种重用可以节省内存。

getView()方法的 parent 参数给出了对具有 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;
    }

 }
于 2012-04-12T08:45:29.947 回答
1

getView()方法为or Spinner的每一行创建新的Viewor 。您可以定义它或在文件夹中的文件中定义它,并可以将其引用到类 Object。ViewGroupListviewViewViewGroupLayout XMLres/layoutAdapter

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

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

于 2012-04-12T08:50:14.343 回答
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);
于 2016-12-09T08:27:03.240 回答
0

如果您想将视图传递给函数(作为参数),您可以先定义一个元素,例如框架布局:

FrameLayout frameLayout = findViewById(R.id.frame_layout);

然后查看元素:

 frameLayout.getRootView();
于 2021-05-12T20:17:15.020 回答