您的位置:首页 > 其它

View.inflate()和LayoutInflater.inflate()的区别

2018-03-01 11:42 253 查看
标签:【Android】UI

一、背景

昨天在写一个关于Viewpager的Demo时,碰到了一个OOM的问题,场景是这样的:

我要用Viewpager实现画廊效果,也就是一个屏幕显示多页

我将Viewpager所在的布局都加上了 android:clipChildren=”false”属性

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clipChildren="false"
tools:context="com.strivestay.viewpagerdemo.FourthActivity">

<include layout="@layout/layout_toolbar"/>

<android.support.v4.view.ViewPager
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="180dp"
android:layout_marginTop="100dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:clipChildren="false">
</android.support.v4.view.ViewPager>

</LinearLayout>


给page的布局,我直接在根布局使用Imageview,无父布局约束

<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/iv_banner"
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="#009999"
android:scaleType="centerCrop"/>


我使用View.inflate()加载布局

for (int i = 0; i < 4; i++) {
View view =  View.inflate(this,R.layout.item_banner,null);
ImageView iv = (ImageView) view.findViewById(R.id.iv_banner);
int resourceId = getResources().getIdentifier("img" + (i + 1), "drawable", getPackageName());
//            Glide.with(this).load(resourceId).into(iv);
iv.setImageResource(resourceId);
list.add(view);
}


效果



思考:

之所以出现这种效果,是因为加载page布局时,没有相关父布局的LayoutParams控制它,当它加载到Viewpager中后,又因为Viewpager的android:clipChildren=”false”,所以,page的内容显示到了viewpager外

解决:

View.inflate(this,R.layout.item_banner,vp);

第三个参数设置成了vp,是希望能够约束page布局(后来想想也没用,vp已经设置了clipChildren)

结果:

java.lang.OutOfMemoryError: Failed to allocate a 33341646 byte allocation with 16777216 free bytes and 18MB until OOM


我没有百度到,为什么这样会造成OOM,希望了解的能够给我留言,谢谢!

有效的两种解决办法:

1. 给page的布局外层套一个父布局

```
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<ImageView
android:id="@+id/iv_banner"
android:layout_width="match_parent"
android:layout_height="180dp"
android:background="#009999"
android:scaleType="centerCrop"/>
</LinearLayout>
```


2. 对图片进行裁切处理,或直接用glide

Glide.with(this).load(resourceId).into(iv);


效果:



具体实现在另一篇文章Viewpager

二、进入正题

由于上面的问题,我想仔细了解学习下View.inflate()和LayoutInflater.inflate()的区别,学习如下:

1. LayoutInflater.inflate()

该方法适用于所有布局填充的的场景,但使用前需要先实例化LayoutInflater对象

1. 获取LayoutInflater实例

getLayoutInflater();

这个方法可以在Activity和Fragment中使用,不过在Fragment中使用时,要传入一个bundle参数

// Activity中使用
LayoutInflater layoutInflater = getLayoutInflater();
// Fragment中使用
LayoutInflater layoutInflater = getLayoutInflater(savedInstanceState);


getSystemService();

这个为Context的方法,只要有上下文就能调用

LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);


LayoutInflater.from();

这个是LayoutInflater的静态方法,传入上下文即可

LayoutInflater inflater = LayoutInflater.from(this);


2. LayoutInflater.inflate()的重载

常用的是下面两种:

1. [b]inflate(int resource,ViewGroup root,boolean attachToRoot)[/b]

resource:布局资源

root:生成View对象的父控件。为null,则返回的view就是布局资源的根布局;否则,需要参照第三个参数

attachToRoot:是否将布局资源加载到root上,以root作为最终返回view的根布局。 false,root不为null,则提供root的LayoutParams约束resource生成的view;true,root不为null,以root作为最终返回view的根布局

2. [b]inflate(int resource,ViewGroup root)[/b]

resource:布局资源

root:生成View对象的父控件。为null,则返回的view就是布局资源的根布局;否则,返回的view以传入的root为根布局

该方法,实际还是调用了上一个方法

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}


2. View.inflate()

这个是View类的静态方法,可直接调用,实际上还是使用了LayoutInflater,所以,它没有直接使用LayoutInflater.inflate()强大

public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}


参数含义:

context:上下文

resource:布局资源

root:生成View对象的父控件。为null,则以布局资源的根布局为返回view的根布局,否则将view加载到root中,以root作为根布局返回

3. 总结

View.inflate()是封装了LayoutInflater的inflate()方法,由于是静态方法,比较简便;但LayoutInflater相当于比View多了一个三个参数的inflate()方法,功能更强大
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐