zoukankan      html  css  js  c++  java
  • (转)深入分析Android中Dialog

    在Android中,Dialog是一个非常重要的UI,它可以方便的给用户提示,用最简洁的方式向用户展示信息,以下的图片是Dialog的一个整体架构,通过它,可以总体对Dialog有一个很清晰的认识。

     

    从这张图中可以看到,Dialog为父类,其下有最重要的,我们最常用的AlertDilog,而AlertDialog的子类,则是由DatPicker, ProgressDialog,TimePick来组成。
    这几个子类都是我们在程序开发中最常用的,因此要重点理解,我们可以试着想像一下,如下几个问题的答案 
    <1> 怎么产生一个Dialog? 
    <2> Dialog与Activity是什么关系? 为什么显示Dialog的时候,Activity就失去了焦点,不能被点击,在系统内部到底是怎么管理他们的关系的? 

    我们以ProgressDialog为例,通过分析其源码,让我们彻底理解它的内部运行机制 

    <1> 怎么产生一个ProgressDialog?
        通过打开ProgressDialog的源码,可以看到它有2个构造方法, 
        

    ProgressDialog(Context context) 
    
    ProgressDialog(Context context,int theme) 

      参数解释:context:说明它是依靠Context,必须通过一个Context来创建它,第二个参数theme:此dialog的主题. 

        另外我们还可以发现有四个静态的show方法,他们只是参数不同, 

         show(Context context,CharSequence title,CharSequence message); 
    
         show(Context context,CharSequence title,CharSequence message,boolean indeterminate); 

    其实,我们只看最后一个静态方法就行了,因为三个静态方法,最终会调用最后一个参数最多的show静态方法来完成功能。


    它所实现的功能是: 
         

    1 ProgressDialog dialog=new ProgressDiaog(context); 
    2      ... 
    3      ... 
    4      ... 
    5 dialog.show(); 

    这其实跟我们调用构造方法是一样的。

    到这一步,仅仅是知道了,怎么调用产生的ProgressDialog的,但具体内部的细节呢。还要看onCreate()方法,此方法才是真正能产生progressDialog的地方,它跟Activity中的onCreate()方法是一样的,就是初始化的时候调用,我们看其源码如下:

    首先看到的是一个名叫 mViewUpdatehandler的 Handler,这个Handler主要用来更新progress的值,(百分比),接着往下看... 
    有这么一句: View view=inflater.inflate(R.layout.alert_dialog_press,null); 
    很明显,这就是我们看到的,显示在dialog中转圈的那个东东。然而,这个alert_dialog_pross文件是在com.android.internal.R 包中,属于系统定义的ui配置文件。 

    最后调用 setView(view)方法来把view显示在Dialog上。 

    因此,我们同样也可以实现自定义一个dialog.xml文件,来调用setView()方法显示上来。 

    这个setView()方法是AlertDialog类中定义的,等会再解释!

    这就是我们平时所见到的 ProgressDialog。分析完毕。 


    AlertDialog 

    接下来,我们开始分析ProgressDialog的父类  AlertDialog。

    打开源码,首先映入眼帘的是三个构造方法,但这三个构造方法都是protected类型的,可见,不允许我们直接实例化AlertDialog。因此,我们再看有没有别的方法可以实例化。

    再仔细一看,发现一个变量,

       AlertController mAlert; 这个才是我们今天的主角,重点研究它。 

       mAlert的定义是在上面我们提到的AlertDialog的构造函数, 

    此外,我们还发现,AlertDialog中几乎所有的方法都是通过这个mAlert变量来操作的, 

    也就是说,AlertDialog是一个空壳,并没有实际的作用,它的实质是AlertController类。 
    就是我刚才说的  "主角" 。Alertcontroller的源码,是Android系统自带的,我们需要花费一番力气去查找。 

    再往下看,AlertDialog 类中,发现一个静态类 Builder,通过这个类,我们也可以直接创建一个Dialog, 
    Builder静态类中也同样有一个AlertController.Alertparams的类的对象 P,我们再看Builder的源码,它里面可以设置所有Dialog的的方法,包括 

    setTitle(CharSequence title) 
    setMessage(int messageId); 
    setIcon(int iconId); 
    setPositiveButton() 
      ... 
      ... 
      .... 

    等,我们看这些方法的的内部实现,全部是针对它的内置对象P 来实现的,也就是我们所调用的这些方法,最终结果实际上是用在了AlertController.AlertParams 类的对象P 身上, 


    ,而别外还有一个有趣的现象,这些方法的返回值都是Builder对象, 也就是说,我们可以连级调用此方法来显示一个Dialog。仅仅调用这些set 方法还不够,最后还差一步,就是调用create()方法,这个方法是最后调用的,也就是创建对话框,我们看,create方法中都做了那些动作 

    1 public AlertDialog create() { 
    2    final AlertDialog dialog =new AlertDialog(p.mContext); 
    3    p.apply(dialog.mAlert) 
    4    dialog.setCancelable(P.mCancelable); 
    5    
    6    return dialog; 
    7 } 

    这个是create()的实现,我们可以很直观地看出是它帮我们创建了一个AlertDialog对象, 

    这里的p,就是我们创建的AlertController.Alertparams的对象,而在AlertDialog  dialog=new AlertDialog(p.mContext); 这句代码中,定义Dialog的同时也定义了 一个AlertController 的对象 mAlert;

    在第二句代码中,p.apply(dialog.mAlert),我们跟踪过去,看下,哈哈,原来是我们刚才调用的set方法的值,又还原给新定义的dialog中的mAlert对象了。这下明白了,原来 P只不过是一个 "屁"   ,暂时的存放数据的对象,只要我们调用create方法,P就会乖乖的把数据交给dialog对象。

    除了create方法以外, 还有一个show() 方法,实现如下 

    1 public AlertDialog show() { 
    2     AlertDialog dialog=create(); 
    3     dialog.show(); 
    4     return dialog; 
    5 } 

    我们可以看出,show() 也是调用的 create方法。 

    由以上的分析,我们就可能轻松理解如下我们常用的语句了:

    1 return new AlertDialog.Builder(context). 
    2             setIcon(R.drawable.alert_icon). 
    3             setTitle(R.string.alert_str) 
    4             .create() ; 

    这就是我们平时用到的产生的Dialog了。

  • 相关阅读:
    Civil 3D 二次开发 创建Civil 3D 对象—— 01 —— 创建几何空间点
    Civil 3D 二次开发 创建Civil 3D 对象—— 00 ——
    Civil 3D 二次开发 创建AutoCAD对象—— 01 —— 创建直线
    Civil 3D 二次开发 新建CLR项目出现错误C2143
    Civil 3D 二次开发 创建AutoCAD对象—— 00 ——
    了解AutoCAD对象层次结构 —— 6 ——块表记录
    datepicker97使用
    使用angular 外接 templateUrl,使用ng-include
    angularJs 遮罩
    网上找的有关css兼容问题
  • 原文地址:https://www.cnblogs.com/chenbin7/p/2621181.html
Copyright © 2011-2022 走看看