android の Activity & View | LayoutInflate

一、什么是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主要负责显示界面

View Code
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 等)。

View Code
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);
            }
        });
    }
}
View Code
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;
    }
}
原文地址:https://www.cnblogs.com/zyoohoo/p/2516449.html