日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ViewStub延迟加载

發(fā)布時間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ViewStub延迟加载 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在項目中,難免會遇到這種需求,在程序運行時需要動態(tài)根據(jù)條件來決定顯示哪個View或某個布局,最通常的想法就是把需要動態(tài)顯示的View都先寫在布局中,然后把它們的可見性設為View.GONE,最后在代碼中通過控制View.VISIABLE動態(tài)的更改它的可見性。這樣的做法的優(yōu)點是邏輯簡單而且控制起來比較靈活。但是它的缺點就是,耗費資源,雖然把View的初始可見View.GONE但是在Inflate布局的時候View仍然會被Inflate,也就是說仍然會創(chuàng)建對象,會被實例化,會被設置屬性。也就是說,會耗費內(nèi)存等資源。

推薦的做法是使用android.view.ViewStub,ViewStub是一個輕量級的View,使用非常簡單:

mViewStub = (ViewStub) this.findViewById(R.id.viewstub);

mViewStub.inflate();

它一個不可見的,不占布局位置,占用資源非常小的控件,相當于一個“占位控件”。使用時可以為ViewStub指定一個布局,在Inflate布局的時候,只有ViewStub會被初始化,然后當ViewStub被設置為可見的時或調(diào)用了ViewStub.inflate()的時候,ViewStub所指向的布局就會被inflate實例化,且此布局文件直接將當前ViewStub替換掉,然后ViewStub的布局屬性(layout_margin***、layout_width等)都會傳給它所指向的布局。這樣,就可以使用ViewStub在運行時動態(tài)顯示布局,節(jié)約內(nèi)存資源。

下面我們從ViewStub源碼來看下inflate()方法的實現(xiàn)原理:

public View inflate() {final ViewParent viewParent = getParent();if (viewParent != null && viewParent instanceof ViewGroup) {if (mLayoutResource != 0) {final ViewGroup parent = (ViewGroup) viewParent;final LayoutInflater factory;if (mInflater != null) {factory = mInflater;} else {factory = LayoutInflater.from(mContext);}final View view = factory.inflate(mLayoutResource, parent,false);if (mInflatedId != NO_ID) {view.setId(mInflatedId);}final int index = parent.indexOfChild(this);parent.removeViewInLayout(this);final ViewGroup.LayoutParams layoutParams = getLayoutParams();if (layoutParams != null) {parent.addView(view, index, layoutParams);} else {parent.addView(view, index);}mInflatedViewRef = new WeakReference<View>(view);if (mInflateListener != null) {mInflateListener.onInflate(this, view);}return view;} else {throw new IllegalArgumentException("ViewStub must have a valid layoutResource");}} else {throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");}}

我們先從方法的入口開始看:
1、在第2行,首先是得到ViewStub它的父視圖對象。

2、然后在第4行一開始肯定是能進入判斷的,mLayoutResource就是需要inflate的布局資源,然后在第13行填充這個布局資源。

3、然后在第21行,重要的來了,parent.removeViewInLayout(this);這段代碼是什么意思呢?看方法名字就知道了,this是代表ViewStub對象,意思就是把當前ViewStub對象從父視圖中移除了。

4、然后第23~28行,就是得到ViewStub的LayoutParams布局參數(shù)對象,如果存在就把它賦給被inflate的布局對象,然后把inflate的布局對象添加到父視圖中。
5、最后返回inflate的布局對象。

好了,源碼解析完畢!!!

從上述可知,當我們第二次調(diào)用ViewStub.inflate()方法的時候,因為已經(jīng)移除了ViewStub對象,在第2、4行,得到的viewParent就為null,此時判斷時候就會走else拋出一個IllegalStateException異常:ViewStub must have a non-null ViewGroup viewParent。

需要注意的幾點:
1.ViewStub之所以常稱之為“延遲化加載”,是因為在教多數(shù)情況下,程序無需顯示ViewStub所指向的布局文件,只有在特定的某些較少條件下,此時ViewStub所指向的布局文件才需要被inflate,且此布局文件直接將當前ViewStub替換掉,具體是通過viewStub.infalte()或viewStub.setVisibility(View.VISIBLE)來完成。

2.正確把握住ViewStub的應用場景非常重要,因為使用ViewStub可以優(yōu)化布局,一般應用在當前布局或控件在用戶使用較少情況下,這樣可以提高性能,節(jié)約內(nèi)存,加快界面渲染。

3.對ViewStub的inflate操作只能進行一次,因為inflate的時候是將它指向的布局實例化并替換掉當前ViewStub本身(由此體現(xiàn)出了ViewStub“占位”性質(zhì)),一旦替換后,此時原來的布局文件中就沒有ViewStub控件了,因此,如果多次對ViewStub進行infalte,會出現(xiàn)錯誤信息:ViewStub must have a non-null ViewGroup viewParent。

4.3中所講到的ViewStub指向的布局文件解析inflate并替換掉當前ViewStub本身,并不是完全意義上的替換(與include標簽不太一樣),替換時,布局文件的layout params是以ViewStub為準,其他布局屬性是以布局文件自身為準。

5.ViewStub本身是不可見的,對ViewStub.setVisibility(int visibility)與其他View控件不一樣,我們可以從源碼角度來看一下ViewStub.setVisibility()方法的作用:

這個方法意思就是ViewStub的setVisibility()設置成View.VISIBLE或INVISIBLE如果是首次使用,都會自動inflate其指向的布局文件,并替換ViewStub本身,再次使用則是相當于對其指向的布局文件設置可見性。

好了,原理講了那么多,來看看代碼怎么實現(xiàn)吧:
使用了ViewStub的activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.viewstub.MainActivity" ><Switchandroid:id="@+id/switch1"android:layout_width="wrap_content"android:layout_height="wrap_content" /><ViewStubandroid:id="@+id/viewstub"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginBottom="10dp"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:layout_marginTop="10dp"android:layout="@layout/hide_layout" /></LinearLayout>

hide_layout.xml

<?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="match_parent"android:background="#00ffff"android:orientation="vertical" ><Buttonandroid:id="@+id/hide_layout_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="Click me" /> </LinearLayout>

代碼文件:

public class MainActivity extends ActionBarActivity {private ViewStub mViewStub;private Switch mSwitch;private boolean flag = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mViewStub = (ViewStub) this.findViewById(R.id.viewstub);//實例化ViewStubmSwitch = (Switch) findViewById(R.id.switch1);mSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {if (isChecked) {if(!flag){mViewStub.inflate();//ViewStub只能被inflate一次,會返回一個填充資源的View對象//mViewStub.setVisibility(View.VISIBLE);)flag = true;}else{mViewStub.setVisibility(View.VISIBLE);}Button mBtn = (Button) findViewById(R.id.hide_layout_btn);//ViewStub被替換的布局內(nèi)的控件mBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(getApplicationContext(), "Click me!",Toast.LENGTH_SHORT).show();}});} else {mViewStub.setVisibility(View.GONE);}}});} }

注:使用ViewStub被替換的布局中的控件,直接findViewById即可。

減少視圖層級merge

<merge />標簽在UI的結(jié)構(gòu)優(yōu)化中起著非常重要的作用,它可以刪減多余的層級,優(yōu)化UI。<merge />多用于替換FrameLayout(因為所有的 Activity視圖的根結(jié)點都是FrameLayout,如果當前的布局根結(jié)點是Framelayout,那么可以用merge替代,減少多余的層級)或者當一個布局 包含另一個時,<merge />標簽消除視圖層次結(jié)構(gòu)中多余的視圖組。例如你的主布局文件是垂直布局,又include引入了一個垂直布局,這是 如果include布局使用的LinearLayout就沒意義了,使用的話反而減慢你的UI渲染。這時可以使用<merge />標簽進行優(yōu)化。<merge xmlns:android="http://schemas.android.com/apk/res/android"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text=""/> </merge>

總結(jié)

以上是生活随笔為你收集整理的ViewStub延迟加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: www.国产精品.com | 一区二区内射 | 热99在线 | 内射后入在线观看一区 | 国产精品国产馆在线真实露脸 | 中文字幕av影视 | 国产成人无码一区二区在线观看 | 国产成人精品一区二区在线小狼 | 国产精品jizz在线观看老狼 | 中字幕视频在线永久在线观看免费 | 午夜剧场91 | cao国产| 日韩激情视频网站 | 免费的毛片视频 | 午夜爱爱毛片xxxx视频免费看 | 少妇高潮21p | 91最新地址| 怡春院一区二区 | 超碰视屏 | 日本精品国产 | 美女扒开内裤让男人捅 | 免费看一级视频 | 国产精品一区二区三区高潮 | 老头av| 丝袜人妻一区 | 亚洲23p| 黄视频在线播放 | 欧美黄色大片网站 | av导航网站 | 不卡中文字幕在线 | 午夜国产 | 成人涩涩网站 | 久久偷看各类wc女厕嘘嘘偷窃 | 黄色录像片子 | 国产精品自拍偷拍视频 | 清纯唯美亚洲综合 | 亚洲天堂网视频 | 日韩有码专区 | 亚洲精品a区 | 日韩欧美在线视频免费观看 | 色天天干 | 国产精欧美一区二区三区蓝颜男同 | 成人小视频在线免费观看 | 欧美激情在线免费 | 日本少妇一区二区 | 娇妻玩4p被三个男人伺候电影 | 亚洲国产精品一区二区久久hs | 亚洲大成色| 中文文字幕一区二区三三 | 亚洲制服另类 | 久久人人爽人人爽人人片av免费 | 开心激情综合 | 蜜桃网站 | 99久久久无码国产精品性色戒 | 影音先锋中文字幕在线视频 | 91精品国产综合久久精品图片 | 色噜噜狠狠一区二区 | 亚洲一区人妻 | 亚洲天堂av电影 | 九久久 | 91呦呦 | 久久网免费视频 | 日本午夜在线 | 国产99久久久 | 九九精品视频免费 | 午夜视频在线免费播放 | 午夜网页| 免费精品视频在线观看 | 毛片99 | 国产 日韩 欧美 综合 | 日本一区二区三区在线播放 | 日韩专区一区 | 天天色天天射综合网 | 青青插 | 亚洲www在线 | 少妇野外性xx老女人野外性xx | 国产中文字幕在线观看 | av影院在线观看 | 狠狠躁日日躁夜夜躁2022麻豆 | 制服.丝袜.亚洲.中文.综合懂色 | 一区二区精品国产 | 麻豆一区二区在线 | www.桃色av嫩草.com | 美女黄色一级 | 葵司ssni-879在线播放 | 国产视频综合 | 亚洲天堂网络 | 综合激情在线 | 国产免费91 | 国产又爽又黄游戏 | 中文字幕久久网 | 亚洲最大免费视频 | 欧美少妇性生活 | 欧美xxxx免费虐 | 不卡二区 | 午夜精品999 | 特级西西www444人体聚色 | 黄色av小说在线观看 | 午夜精品一区二区三区在线播放 |