新技能get:Android应用优化技能之“延迟加载”术
世风日下,人心不古。
如今四海虽看似太平,其实却暗藏杀机。大到一架飞机一辆公交,小到一个app,都会让您抓狂。
越来越复杂的界面,越来越多的需求,对app来说本身来说就是一个噩耗,但在人类无穷的想象力,在功能模块无情的堆积之下,对于应用来说,要么瘦,要么死!
那么如何瘦,怎么瘦?对广大爱美的程序员和产品和用户来说,只有简约,按需才是王道。
旁白:写文章就写文章嘛,废话太多了!
【这是正题】上面一堆废话其实也是有两个有用的词汇的,简约和按需。简约是设计要想的,那么按需就是我们程序将要做的。
【按需:延迟加载】所谓的延迟加载就是不在初始化界面的时候加载部分view,在需要的时候才加载,在布局多控件的时候能有效的提升界面的加载和响应速度。
【我们普遍在使用的按需加载】稍微有些经验的android开发程序员都会懂得把一些复杂界面里的一些模块单独用一个xml写的layout独立写,然后在需要的时候把它们inflate()到程序中来,这样达到延迟加载的目的。这样做在界面不确定,需要多次实例化view或者根据数据遍历产生view的时候会很方便,完全由java代码实现。那么如果我们在界面元素确定并且需要延时加载的时候有没有更直观的做法呢?当然有:使用viewStub.
【一个轻量级的控件:viewStub】如名字的含义,只是一个view的存根,不占什么内存(区别于<include>),但却可以占个位置,在程序需要的时候把viewStub指向的view扩展到界面。依照惯例,在我要举例子的这个时候代码会悄悄袭来--》
1 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 tools:context=".MainActivity" > 6 7 <LinearLayout 8 android:id="@+id/main" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:orientation="vertical" 12 android:paddingBottom="@dimen/activity_vertical_margin" 13 android:paddingLeft="@dimen/activity_horizontal_margin" 14 android:paddingRight="@dimen/activity_horizontal_margin" 15 android:paddingTop="@dimen/activity_vertical_margin" > 16 17 <TextView 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:text="所谓的延时加载就是不在初始化界面的时候加载部分view,在需要的时候才加载,在布局多控件的时候能有效的提升界面的响应速度。"/> 21 22 <Button 23 android:id="@+id/btn_by_inflate" 24 android:layout_width="match_parent" 25 android:layout_height="wrap_content" 26 android:text="普通inflate方式" /> 27 28 <Button 29 android:id="@+id/btn_by_viewstub" 30 android:layout_width="match_parent" 31 android:layout_height="wrap_content" 32 android:text="viewStub方式" /> 33 34 <ViewStub 35 android:id="@+id/viewstub" 36 android:layout_width="match_parent" 37 android:layout_height="wrap_content" 38 android:inflatedId="@+id/inflate_view_id" 39 android:layout="@layout/delay_by_viewstub" /> 40 </LinearLayout> 41 42 </ScrollView>
这是我们主界面xml中定义的ViewStub,需要注意的有三点:id->stub的id,根据这个取stub对象;inflatedId->扩展出的视图id(即指向的视图的id,可以不定义);layout->将要inflate的layout。好的,太直观了,不用再解释什么了。
有了存根,那么我们怎么在程序需要的时候取得?寥寥几句,view轻松到手。
1 package com.change.delayloaddemo; 2 3 import android.app.Activity; 4 import android.graphics.Color; 5 import android.os.Bundle; 6 import android.view.Menu; 7 import android.view.View; 8 import android.view.View.OnClickListener; 9 import android.view.ViewStub; 10 import android.widget.Button; 11 import android.widget.LinearLayout; 12 import android.widget.TextView; 13 14 /** 15 * 两种延迟加载方式Demo android推荐采用viewStub方式。 16 * 17 * @author Change 18 * 19 */ 20 public class MainActivity extends Activity implements OnClickListener { 21 private LinearLayout main; 22 private TextView normalInflate, delayByViewStub; 23 private ViewStub mStub; 24 private Button byInflate, byViewStub; 25 26 @Override 27 protected void onCreate(Bundle savedInstanceState) { 28 super.onCreate(savedInstanceState); 29 setContentView(R.layout.activity_main); 30 initViews(); 31 } 32 33 private void initViews(){ 34 main = (LinearLayout) findViewById(R.id.main); 35 byInflate = (Button)findViewById(R.id.btn_by_inflate); 36 byViewStub = (Button)findViewById(R.id.btn_by_viewstub); 37 38 byInflate.setOnClickListener(this); 39 byViewStub.setOnClickListener(this); 40 } 41 42 @Override 43 public boolean onCreateOptionsMenu(Menu menu) { 44 // Inflate the menu; this adds items to the action bar if it is present. 45 getMenuInflater().inflate(R.menu.main, menu); 46 return true; 47 } 48 49 @Override 50 public void onClick(View arg0) { 51 switch (arg0.getId()) { 52 case R.id.btn_by_inflate: 53 normalInflate = (TextView) getLayoutInflater().inflate( 54 R.layout.delay_by_viewstub, null); 55 main.addView(normalInflate); 56 normalInflate.setText("我是通常的inflate方法加载的view"); 57 normalInflate.setBackgroundColor(Color.parseColor("#00ffff")); 58 break; 59 case R.id.btn_by_viewstub: 60 mStub = (ViewStub)findViewById(R.id.viewstub); 61 if(null!=mStub)//mStub执行了一次inflate()方法之后会被置空,所以此处判空 62 delayByViewStub = (TextView)mStub.inflate(); 63 // mStub.setVisibility(View.VISIBLE);//或者这样可以inflate出view. 64 break; 65 66 default: 67 break; 68 } 69 } 70 71 }
以上红色部分便是使用viewStub延迟加载的几句代码。
【需要注意的点】viewStub在执行完inflate()方法或者setVisibility(View.VISIBLE)方法之后会被置空,不能再使用该对象。
【完整代码】demo的github地址:https://github.com/ChangeWu/SomePoject/tree/master/DelayLoadDemo