• 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;
        }
    }
  • 相关阅读:
    zabbix笔记之计算型监控项详解
    zabbix笔记之磁盘IO介绍
    zabbix笔记之Graphtree配置
    zabbix笔记之告警时远程执行命令
    zabbix笔记之异常优化
    zabbix笔记之IPMI配置
    基本的sql 语句
    socket 套接字
    调用父类的三种方法
    实例属性和类属性
  • 原文地址:https://www.cnblogs.com/zyoohoo/p/2516449.html
Copyright © 2020-2023  润新知