一、什么是activity
activity类处于android.app包中,继承体系如下:
1.java.lang.Object
2.android.content.Context
3.android.app.ApplicationContext
4.android.app.Activity
activity是单独的,用于处理用户操作。几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上,
当 activity指向全屏窗口时,也可以用其他方式实现:作为漂浮窗口(通过windowIsFloating的主题集合),或者嵌入到其他的 activity(使用ActivityGroup)。
大部分的Activity子类都需要实现以下两个接口:
· onCreate(Bundle)接口是初始化activity的地方. 在这儿通常可以调用setContentView(int)设置在资源文件中定义的UI, 使用findViewById(int) 可以获得UI中定义的窗口.
· onPause()接口是使用者准备离开activity的地方,在这儿,任何的修改都应该被提交(通常用于ContentProvider保存数据).
另外,为了能够使用Context.startActivity(),所有的activity类都必须在AndroidManifest.xml文件中定义有相关的“activity”项。
二、activity的生命周期
在系统中的Activity被一个Activity栈所管理。当一个新的Activity启动时,将被放置到栈顶,成为运行中的Activity,前一个Activity保留在栈中,不再放到前台,直到新的Activity退出为止。
下面的图显示了Activity的重要状态转换,矩形框表明Activity在状态转换之间的回调接口,开发人员可以重载实现以便执行相关代码,带有颜色的椭圆形表明Activity所处的状态。
activity的内部实现:
【1】ActivityManagerService创建Activity线程,激活一个activity
【2】系统调用Instrumentation.newActivity创建一个activity
【3】Activity创建后,attach到一个新创建的phonewindow中。这样Activity获取一个唯一的WindowManager服务的实例
【4】Activity创建过程中使用setcontentView设置用用户UI,这些VIEW被加入到PhoneWindow的ContentParent中。
【5】Activity线程继续执行,当执行到Activity.makeVisible是将根view DecoView加入到WindowManger中,WindowManger实全会为每个DecoView创建对应的ViewRoot
【6】每个ViewRoot拥有一个Surface,每个Surface将会调用底层库创建图形绘制的内存空间。这个底层库就是SurfaceFlinger。SurfaceFlinger同时也负责将个View绘制的图形合到一块(按照Z轴)显示到用户屏幕。
【7】如果用户直接在Canvas上绘制,实际上它直接操作Surface。但对每个View的变更,它是要通知到ViewRoot,然后ViewRoot获取Canvas。如果绘制完成,surfaceFlinger得到通知,合并Surface成一个Surface到设备屏幕。
比较:
1. activity相当于控制部分,view相当于显示部分。两者之间是多对多的关系,所有东西必须用view来显示。
viewGroup继承自view,实现了ViewManager,ViewParent接口,主要用作layout方面。
2. Activity中加载相应的view才能显示出画面来,view是具体的画面布局(layout),由wegit控件组成。
好比view是jsp实现前台画面,activity是java程序,处理具体业务逻辑。
3. 基本上每个activity都有对应的view,
activity用于控制view中的响应,如button的点击事件等可以在activity中实现,但是你得把这个button给用户看到啊,所以就用view现实了~
4. activity就是一个容器,view只能在这个container里才能正常工作。
5. Activity主要是控制部分;View主要负责显示界面
public class TestCodeView extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //创建一个线性布局管理器 LinearLayout layout = new LinearLayout(this); //设置该Activity显示layout super.setContentView(layout); //设置为垂直(vertical)显示 layout.setOrientation(LinearLayout.VERTICAL); //创建一个按钮 Button btn = new Button(this); btn.setText(R.string.app_name); //viewGroup容器控制其子组件的分布依赖于 //ViewGroup.LayoutParams 、 ViewGroup.MarginLayoutParams 两个内部类 btn.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT )); //向layout容器中添加按钮 layout.addView(btn); btn.setOnClickListener(new OnClickListener() { public void onClick(View v) { Toast.makeText(TestCodeView.this,R.string.hello, Toast.LENGTH_LONG).show(); } }); } }
注:用java来控制UI界面,不仅繁琐,而且不利于解耦,XML控制UI方便,快捷,但有失灵活性。有些时候需要两者配合使用。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
LayoutInflater
通俗的说,inflate就相当于将一个xml中定义的布局找出来
因为在一个Activity里如果直接用findViewById()的话,对应的是setConentView()的那个layout里的组件.
因此如果你的Activity里如果用到别的layout,比如对话框上的layout,你还要设置对话框上的layout里的组件(像图片ImageView,文字TextView)上的内容,你就必须用inflate()先将对话框上的layout找出来,然后再用这个layout对象去找到它上面的组件,
具体作用:
1、对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;
2、对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素。
LayoutInflater 是一个抽象类,在文档中如下声明:
publicabstractclass LayoutInflater extends Object
获得 LayoutInflater 实例的三种方式
1.LayoutInflater inflater = getLayoutInflater(); //调用Activity的getLayoutInflater(),在Activity中可以使用,实际上是View子类下window的一个函数
2.LayoutInflater inflater = LayoutInflater.from(context); //该方法实质就是第三种方法,可参考源代码
3.LayoutInflater localinflater = (LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
inflate ()方法
public View inflate (int resource, ViewGroup root)
public View inflate (XmlPullParser parser, ViewGroup root)
/*
*1.ID for an XML layout resource to load (e.g.,R.layout.main_page
)--想要用的布局文件的id
*2.Optional view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams
* values for root of the returned hierarchy (if attachToRoot is false.)--持有选项卡的内容,获取FrameLayout
*3.Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams
* for the root view in the XML--true:将此处解析的xml文件做为根视图View*/
public View inflate (int resource, ViewGroup root, boolean attachToRoot)
注意:
·inflater方法与 findViewById 方法不同;
·inflater 是用来找 res/layout下的 xml 布局文件,并且实例化;
·findViewById() 是找具体 xml 布局文件中的具体 widget 控件(如:Button、TextView 等)。
public class TtlayoutActivity extends Activity { private Button btnContact;//通讯录按钮 private Button btnFind;//找好友按钮 private Button btnAdd;//添加按钮 private void init(){ btnContact = (Button) findViewById(R.id.b_friendlist_allcontacts); btnFind = (Button) findViewById(R.id.b_friendlist_find); btnAdd = (Button) findViewById(R.id.b_friendlist_invite); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //获得LayoutInflater对象 final LayoutInflater layout = LayoutInflater.from(this); //获得当前Context的RelativeLayout final RelativeLayout rmain = (RelativeLayout) findViewById(R.id.b_friendlist_mainlayout); init(); btnContact.setOnClickListener(new OnClickListener() { public void onClick(View v) { //获得通讯录的view RelativeLayout r = (RelativeLayout) layout.inflate(R.layout.listmain,null).findViewById(R.id.friend_list_main); //获得通讯录view中的listView ListView listv = (ListView) r.findViewById(R.id.b_friend_listview); //通过适配器填充listView的每一条数据 listv.setAdapter(new ListAdapter(TtlayoutActivity.this)); //删除当前主布局中的内容 rmain.removeAllViews(); //添加到当前主布局中 rmain.addView(r); } }); } }
public class ListAdapter extends BaseAdapter { List<Friend> friendList = new ArrayList<Friend>(); private LayoutInflater inflater; private Context context; public ListAdapter(Context context){ this.context = context; inflater = LayoutInflater.from(context); //封装测试数据 for(int i=0;i<6;i++){ Friend f = new Friend(); f.name="google"+i; f.phone=i+"9"+i+2+"99999"; f.pohto = "pic"+i; friendList.add(f); } } @Override public int getCount() { return friendList.size(); } @Override public Object getItem(int position) { return friendList.get(position); } @Override public long getItemId(int position) { return position; } @Override//绘制列表 public View getView(int position, View convertView, ViewGroup parent) { final Friend f = friendList.get(position); final int num = position; LoadFriend lfriend = null; if(convertView == null){ lfriend = new LoadFriend(); //获得列表布局文件并实例化 convertView = inflater.inflate(R.layout.listview,null); lfriend.mImageView = (ImageView) convertView.findViewById(R.id.img); lfriend.mPhoneText = (TextView) convertView.findViewById(R.id.phone); lfriend.mNameText = (TextView) convertView.findViewById(R.id.name); lfriend.add = (ImageView) convertView.findViewById(R.id.add_img); lfriend.add.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context,"第"+num+"行", Toast.LENGTH_LONG).show(); } }); lfriend.mPhoneText.setText(f.phone); lfriend.mNameText.setText(f.name); convertView.setTag(lfriend); } return convertView; } //列表一行的装载类 class LoadFriend{ private ImageView mImageView; private TextView mPhoneText; private TextView mNameText; private ImageView add; } //测试封装类 class Friend{ String name; String phone; String pohto; } }