Android:我为何要封装DialogFragment?

我为何要封装DialogFragment

最近在重构项目代码,项目中创建对话框用的是Dialog,AlertDialog。但是官方推出了DialogFragment来代替Dialog。那我就去认真的了解下DialogFragment。

DialogFragment

DialogFragment是在Android3.0的时候被引入的,从其名字可以很直观的看出它是一种基于Fragment的Dialog,可以用来创建对话框,它是用来替代Dialog的。一个新事物的出现是为了解决旧事物存在的问题,那不建议使用的Dialog存在什么问题呢?下面简单的说下。

Dialog存在问题:

  • 在手机配置发生变化后(比如:旋屏后),变化之前显示的Dialog,变化之后不会显示,更别提Dialog状态的恢复了。
  • 管理自定义的Dialog和系统原生的Dialog麻烦

DialogFragment怎么解决Dialog存在的问题:

  • DialogFragment说到底还是一个Fragment,因此它继承了Fragment的所有特性。同理FragmentManager会管理DialogFragment。在手机配置发生变化的时候,FragmentManager可以负责现场的恢复工作。调用DialogFragment的setArguments(bundle)方法进行数据的设置,可以保证DialogFragment的数据也能恢复。
  • DialogFragment里的onCreateView和onCreateDIalog 2个方法,onCreateView可以用来创建自定义Dialog,onCreateDIalog 可以用Dialog来创建系统原生Dialog。可以在一个类中管理2种不同的dialog。

用DialogFragment替代Dialog

既然DialogFragment有这些好处,那我就毅然决然的对项目中的Dialog用DialogFragment来进行替代。
重构的思路是这样的:

  • 首先先创建一个ConfirmDialogFragment类(该类是用来创建确认对话框的),ConfirmDialogFragment类继承了DialogFragment。
  • 其次在创建一个ProgressDialogFragment类(该类是用来创建进度对话框),同时它也继承了DialogFragment。
  • 其他类型的Dialog就不举例了。
  • 最后在BaseActivity(项目中所有Activity的基类)添加显示Dialog的方法,供BaseActivity的子类、Fragment、还有非Activity和非Fragment的类来调用。

我们先看下关键代码片段:代码地址
ConfirmDialogFragment中的代码片段:代码地址

  /**
    *用来创建确认对话框
   * Created by niuxiaowei on 2015/10/16.
 */
 public class ConfirmDialogFragment extends DialogFragment{

        private ConfirmDialogListener mListener;

        //对外开放的接口
        public static interface ConfirmDialogListener extends DialogInterface.OnClickListener{
        }

        /**
         * @param title
        * @param message
         * @param cancelable
         * @return
         */
        public static ConfirmDialogFragment newInstance(String title, String message,boolean cancelable){
              ConfirmDialogFragment instance = new ConfirmDialogFragment();
              Bundle args = new Bundle();
              args.putString("title",title);
              args.putString("message",message);
              args.putBoolean("cancelable",cancelable);
              instance.setArguments(args);
              return instance;
        }

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            创建ConfirmDialog核心代码,可以下载源代码查看.....
        }

        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            if (getActivity() instanceof ConfirmDialogListener ) {
                  mListener= (ConfirmDialogListener ) getActivity();
            }
        }
        ......
  }

ConfirmDialogFragment很关键的一点,ConfirmDialogFragment中的mListener属性的值是通过

   @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            if (getActivity() instanceof ConfirmDialogListener ) {
                  mListener= (ConfirmDialogListener ) getActivity();
            }
        }

方式获取的。

BaseActivity中代码片段:代码地址

 public class BaseActivity extends FragmentActivity 
 {
           /*
            *显示确认对话框方法
           */
          public void showConfirmDialog(...){
                 ......
           }
          
           /*
            *显示进度条对话框方法
           */
          public void showProgressDialog(...){
                 ......
          }
 }

那我们就重构BaseActivity的子类显示Dialog的代码:
我拿MainActivity来举例子:
MainActivity的关键重构代码:

    /*
    *实现确认对话框的ConfirmDialogListener 接口
     *created by niuxiaowei
   */
   public class MainActivity extends BaseActivity implements ConfirmDialogListener {

           @Override
          public void onClick(DialogInterface dialogInterface, int i) {
              Toast.makeText(this,"点击了MainActivity 调起的确认对话框 i="+i,Toast.LENGTH_LONG).show();
          }
        
         //调用显示ConfirmDialog代码
         showConfirmDialog(...);

        //调用显示ProgressDialog代码
         showProgressDialog(...);
 }

现在MainActivity里的代码运行起来完全没问题,因为MainActivity里面包含了3个Fragment,每个Fragment里面都有显示ConfirmDialog和ProgressDialog的代码,所以开始重构这3个Fragment:
重构思路:

  • 每个Fragment里都可以获取到相对应的Activity的实例,只要获取到实例就可以调用显示对话框的方法来显示对话框了。

  • 对话框中的事件怎么传递给Fragment问题?Activity可以获取到Fragment的实例,对话框可以把事件传递给Activity,因此Activity顺理成章的可以把事件传递给对应的Fragment。

  • 一个Activity有多个Fragment调用显示对话框的方法,在Activity的实现了对话框接口的方法里怎样区分不同的Fragment调用者?可以在BaseActivity显示对话框的方法里加个id参数,用id来区分不同的Fragment调用者。
    那就上关键代码片段:
    MainActivity中的AFragment代码片段:

    public AFragment extends Fragment implements ConfirmDialogListener{
    
           @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Toast.makeText(this,"点击了AFragment 调起的确认对话框 i="+i,Toast.LENGTH_LONG).show();
            }
          
           //调用显示ConfirmDialog代码
           getActivity().showConfirmDialog(...);
    }
    

同理MainActivity的BFragment,CFragment的重构与AFragment类似。
MainActivity的关键代码片段:

  @Override
  public void onClick(DialogInterface dialogInterface, int i) {
             //伪代码
             if(mId == aFragment传递Id){
                    aFragment.onClick(dialogInterface,i);
             }else if(mId == bFragment传递Id){
             }else if(mId == cFragment传递Id){
             }else if(mId == mainActiviy传递Id){
                   调用自己的方法
             }
  }

产生的问题

看了MainActivity的onClick方法里面代码我都对自己无语了,onClick方法里面充斥着各种的if else 语句,并且当前的MainActivity里,若再有别的显示ConfirmDialog的调用者,onClick方法里少不了要增加对应的else if语句。MainActivity只是项目中所有Activity的一个缩影。其他的Activity也会遇到同样的问题(这不是我意淫的,提早预估到问题,提早入手进行解决总是好的)

我们拿MainActivity来代表所有的Activity总结下使用DialogFragment创建Dialog产生的问题:

  • MainActivity里的onClick方法维护、扩展性不好,充斥着各种if else if语句,可读性也不好。
  • MainActivity里的onClick方法除了把Dialog的事件转发给相对应的调用者之外,没有多任何其他操作,所以是多余的
  • 显示Dialog的方法不灵活

存在这些问题严重影响了我后面的重构工作,于是乎我就去国内国外网站上搜索对应的解决方法,但是也没有找到好的方法,最后我就想办法自己解决上面的问题,这也是我为何要封装DialogFragment的缘由

封装DialogFragment,让DialogFragment使用非常简单、灵活

我们仔细的分析下上文的问题的主要原因是显示Dialog的方法没有把Dialog里面的开放的接口作为参数导致的,假如能像下面的使用方式:

    //某一个Activity中显示ConfirmDialog
    showConfirmDialog(title,message,confirmDialogListener);
    //某一个Fragment中显示ConfirmDialog
    getActivity().showConfirmDialog(this,message,confirmDialogListener);
    //非Activity和非Fragment的类中显示ConfirmDialog
    mActivity.showConfirmDialog(this,message,confirmDialogListener);

上文中所有的问题都可以解决。

为什么不按下面的做法做

做法1:那我们直接把ConfirmDialogListener 的实例赋值给ConfirmDialogFragment 的实例的mListener属性,以下为代码:

      //直接把listener传递
       public static ConfirmDialogFragment newInstance(...,ConfirmDialogListener listener){
              ConfirmDialogFragment instance = new ConfirmDialogFragment();
              ......
              instance.mListener = listener;
              ......
        }

那我就详细的解释下为什么不这样做的具体原因:

  • 在创建Fragment的时候,最好是把传递给Fragment的数据存放在Bundle中,然后在调用fragment的setArguments(bundle)方法进行数据的设置,这种做法好处是:系统会保存Fragment的数据,在手机配置发生变化后(比如旋屏),系统会把保存的Fragment数据进行恢复。

以上做法,ConfirmDialogFragment 中mListener属性系统没有为之保存,所以手机配置发生变化后,ConfirmDialogFragment 中的mListener 是null。

做法2:那我们是否可以把ConfirmDialogListener实例(ConfirmDialogListener是ConfirmDialogFragment 对外开放的接口)存放在Bundle中?
答案是不可以,首先 Bundle对存放的数据是有限制的,把ConfirmDialogListener的实例存入Bundle中是比较复杂的操作。其次即使通过艰辛万苦把ConfirmDialogListener实例存入了Bundle中,保存ConfirmDialogListener实例是毫无意义的,只有保存数据对于Fragment来说才有意义,保存行为对Fragment是无意义的。

有思路

我们在回顾下ConfirmDialogFragment中onAttach的方法的关键代码:代码地址

   @Override
   public void onAttach(Activity activity) {
       if(getActivity() instanceof ConfirmDialogListener){ 
          //关键代码
           mListener= (ConfirmDialogListener)getActivity();
      }
    }

以上代码的关键之处在于mListener= (ConfirmDialogListener)getActivity()。同时痛点也在此处,这是一种类似于硬编码的方式,硬编码的一个不好的地方就是没有扩展性。解决思路:

  • 那我们就想办法让此处变的有弹性。我们可以把BaseActivity想象为一个ConfirmDialogListener的存取工具,调用者可以把自己实现的ConfirmDialogListener存入BaseActivity中, ConfirmDialogFragment可以从BaseActivity中取出ConfirmDialogListener实例,那我的问题就迎刃而解了。
  • 既然可以获取到BaseActivity的实例,那也可以获取到BaseFragment的实例(getParentFragment()可以获取到)。既然BaseFragment实例可以获取到,那解决ConfirmDialogFragment同时服务于BaseActivity和BaseFragment就不是问题了

同时我还想解决在任何的类中(不管Fragment、Activity、或其他类中)显示Dialog不需要依赖BaseActivity。而是有一个类(假如叫DialogFactory)定义显示各种Dialog的方法。像下面一样:

     //某一个Activity中显示ConfirmDialog
    mDialogFactory.showConfirmDialog(title,message,confirmDialogListener);
    //某一个Fragment中显示ConfirmDialog
    mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);
    //非Activity和非Fragment的类中显示ConfirmDialog
    mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);

那我就说下思路:

  • 新建DialogFactory类,该类封装了显示各种Dialog的方法
  • 新建BaseDialogFragment类,该类是各种类型Dialog的基类,里面封装了一些公用的方法
  • 修改BaseActivity和BaseFragment类,在各自的类中分别定义DialogFactory属性mDialogFactory,这样显示Dialog的任务就交给了mDialogFactory

DialogFactory 代码:代码地址

  /** * Created by niuxiaowei on 2016/2/3. * 对话框工厂 */
  public class DialogFactory {

        private FragmentManager mFragmentManager;
        private BaseActivity mBaseActivity;
        private BaseFragment mBaseFragment;

        public DialogFactory(BaseActivity baseActivity,FragmentManager fragmentManager){   
               this.mFragmentManager = fragmentManager;  
               this.mBaseActivity = baseActivity;  
        }

        public DialogFactory(BaseFragment baseFragment,FragmentManager fragmentManager){   
               this.mFragmentManager = fragmentManager;  
               this.mBaseFragment= baseFragment;  
        }

        /** * 进度条对话框 
        * @param message 进度条显示的信息
        * @param cancelable 点击空白处是否可以取消 */
       public void showProgressDialog(String message, boolean cancelable){   
              省略此处代码......
        }

        /**
        *  显示确认对话框,dialogId是用来区分不同对话框的
       * @param title 对话框title
       * @param message
       * @param cancelable
       * @param listener
       */
       public void showConfirmDialog(String title,String message,boolean cancelable,ConfirmDialogListener listener){ 
               省略此处代码......
               if(mBaseActivity != null){
                    mBaseActivity.setDialogListener(listener);
               }else if(mBaseFragment != null){
                    mBaseFragment.setDialogListener(listener);
                }
         }

        显示其他类型的dialog方法......
   }

DialogFactory关键代码介绍:

  • DialogFactory可以供任何的类来使用
  • mFragmentManager属性在现实Dialog时起作用,若调用者(显示Dialog)是Activity,则传递getFragmentManager();若调用者是Fragment,则传递getChildFragmentManager()。不过不需要担心这些,BaseActivity和BaseFragment都已经封装了这些参数
  • DialogFactory把调用者传递过来的BaseDialogListener传递给Activity或Fragment

BaseDialogFragment代码:代码地址

    /** * Created by niuxiaowei on 2015/10/15. * 自定义dialog,是所有自定义dialog的基类 */
    public class BaseDialogFragment extends DialogFragment {

        /** * 基础的dialog listener,没有提供任何的方法,扩展的dialog,若该dialog有listener则必须继承本接口 */
        public static interface BaseDialogListener{}

        /** * 接收dialog listener对象,具体由子类进行实现 * @param listener */
        protected void onReceiveDialogListener(BaseDialogListener listener){}

         @Override
         public void onActivityCreated(Bundle savedInstanceState) {

              /*解析BaseDialogListener,fragment的级别要大于activity,若 
              *  (getParentFragment() instanceof BaseFragment)为true* ,
               * 表明是一个fragment调起的dialog,否则是一个activity调起的diaolog
              * */
              BaseDialogListener listener = null;
              if (getParentFragment() instanceof BaseFragment) {    
                    listener = ((BaseFragment) getParentFragment()).getDialogListener();
              }else if(getActivity() instanceof BaseActivity){ 
                   listener = ((BaseActivity)getActivity()).getDialogListener();
              }
              if(listener != null){
                  onReceiveDialogListener(listener);
              }
         }
    }

BaseDialogFragment关键代码介绍:

  • BaseDialogListener定义一个空方法接口,新增的Dialog(若该Dialog包含对外接口),则新增的Dialog提供的对外接口必须继承BaseDialogListener

  • onReceiveDialogListener方法是提供给子类来实现,让子类来接收调用者传递进来的BaseDialogListener实例

  • onActivityCreated方法很重要,该方法是使BaseDialogFragment可以兼容Activity和Fragment的关键代码

     if (getParentFragment() instanceof BaseFragment) {    
               listener = ((BaseFragment) getParentFragment()).getDialogListener();
      }else if(getActivity() instanceof BaseActivity){ 
              listener = ((BaseActivity)getActivity()).getDialogListener();
      }
    

上面代码的作用是假如当前调用者(显示Dialog)是一个Fragment,则会把Fragment中持有的BaseDialogListener赋给对应的Dialog,若当前调用者是一个Activity,则会做同样的事情

ConfirmDialogFragment 关键代码片段:代码地址

        //继承BaseDialogListener
        public static interface ConfirmDialogListener extends BaseDialogListener,DialogInterface.OnClickListener{
        }

        public void onReceiveDialogListener(BaseDialogListener listener){
              if(listener instanceof ConfirmDialogListener ){
                       mListener = (ConfirmDialogListener )listener;
              }
       }

ProgressDialogFragment基本没发生多大改变,我们就不贴具体代码了。

修改BaseActivity和BaseFragment类关键代码:

public class BaseActivity extends FragmentActivity{

        protected DialogFactory mDialogFactory ;
        private BaseDialogListener mListener;

        public void getDialogListener(){
               return mListener;
        }

        public void setDialogListener(BaseDialogListener listener){
                mListener = listener;
        }

        public void onCreate(Bundle savedInstanceState){
               super.onCreate(savedInstanceState);
               mDialogFactory = new DialogFactory(this,getFragmentManager();
        }
 }

  public class BaseFragment extends Fragment{

        protected DialogFactory mDialogFactory ;
        private BaseDialogListener mListener;

        public void getDialogListener(){
               return mListener;
        }

        public void setDialogListener(BaseDialogListener listener){
                mListener = listener;
        }
        public void onCreate(Bundle savedInstanceState){
               super.onCreate(savedInstanceState);
               mDialogFactory = new DialogFactory(this,getChildFragmentManager();
        }
 }

介绍下BaseActivity修改的代码:

  • mDialogFactory 是供Activity来显示各种Dialog的
  • mListener是Activity持有调用者传递的BaseDialogListener的实例,BaseDialogFragment会从getDialogListener()方法获取该实例

BaseFragment的修改和BaseActivity一样,就不介绍了。

那我们在理一下上面代码的思路:

  • DialogFactory封装了显示各种Dialog的方法,使用者使用它来显示Dialog。它会把使用者传递的BaseDialogListener传递给BaseActivity或BaseFragment
  • BaseActivity和BaseFragment在传递BaseDialogListener起了一个桥梁的作用。当Dialog即将被显示时,BaseDialogFragment会从BaseActivity或BaseFragment获取BaseDialogListener

解决最棘手的问题

当我还沉浸在happy中时,突然一个问题出现了,旋屏后重新弹出的ConfirmDialog的点击事件却没传递给调用者,我就细细的想原来是旋屏后BaseActivity或BaseFragment里的mListener为空了。那我就继续解决这棘手问题,为什么棘手呢?因为我们一直都是在围绕着怎样解决旋屏后Dialog中的mListener属性的值(BaseDialogListener的实例)怎么重新获取的问题,但是经过一番努力还是没成功,不行我还得继续想办法。

上文中也提到过对于Fragment存放行为是毫无意义的,那我们就换个角度考虑问题,我们先用BaseFragment来举例子(BaseActivity类似):

  • 在BaseFragment用一个属性mDialogListenerKey去存mListener(类型是BaseDialogListener)属性的类名,当手机配置发生变化的时候在BaseFragment的onSaveInstance(bundle)方法中把mDialogListenerKey存入Bundle中(前提条件Dialog没消失)
  • 当BaseFragment重新被创建的时候,在onCreate(savedInstanceState)方法中从Bundle中把mDialogListenerKey值读出来
  • 根据mDialogListenerKey去找到对应的BaseDialogListener子类的实例
  • 把上步中找到的实例通过调用BaseFragment的setDialogListener()方法进行设置

那我们就开始写代码:
新建DialogListenerHolder,该类用来持有调用者传递的BaseDialogListener实例,即把原来BaseActivity或BaseFragment里的mListener属性放到该类中
DialogListenerHolder修改的代码片段:代码地址

public class DialogListenerHolder{

      private BaseDialogListener mDialogListener;
      /** * 对话框的listener的key值,用类名作为key值,
      *主要用来在手机配置发生变化时(横屏换为竖屏),
       *当现场恢复时,能正确的找到对话框的listener */
      private String mDialogListenerKey;

      public void setDialogListener(BaseDialogFragment.BaseDialogListener listener){        
          mDialogListener = listener;    
          mDialogListenerKey = listener == null ?null:listener.getClass().getName();
      }

      /** * 把listener的key值保存在bundle中,配置发生变化的情况下(横屏换为竖屏),在从bundle中取listener的key值
     * @param outState */
    public void saveDialogListenerKey(Bundle outState){      
          if(outState != null){        
              outState.putString("key",mDialogListenerKey);
          }
    }

    /** * 从bundle中尝试取出dialog listener key
   * @param savedInstanceState */
    public void getDialogListenerKey(Bundle savedInstanceState){    
          if(savedInstanceState != null){ 
               mDialogListenerKey = savedInstanceState.getString("key");
          }
    }

    /** * 这个方法很重要,是恢复dialog listener的一个关键点,
    *在初始化DialogFactory或把DialogFactory赋值后,调用该方法,把调用该方法所在
   * 的类的实例作为参数。 该方法会把param中的属性依次遍历,尝试找属性是BaseDialogFragment.BaseDialogListener的实例,
   * 并且该属性就是保存在bundle中的dialog listener key对应的dialog listener 
  * @param o */
  public void restoreDialogListener(Object o){
        if(o == null){
              return; 
         } 
         if(!isNeedRestoreDialogListener()){
              return;
         } 
       //先尝试找传进来的实例
        if(o instanceof BaseDialogFragment.BaseDialogListener && o.getClass().getName().equals(mDialogListenerKey))
        {        
       setDialogListener((BaseDialogFragment.BaseDialogListener)o); 
           return; 
       } 

      Class c = o.getClass();
      Field[] fs = c.getDeclaredFields();
      for (int i = 0; i < fs.length; i++) {
          Field f = fs[i]; 
           try {
                Object instance = f.get(o);
                if((instance instanceof BaseDialogFragment.BaseDialogListener) && instance.getClass().getName().equals(mDialogListenerKey)){ 
           setDialogListener((BaseDialogFragment.BaseDialogListener) f.get(o));
                }  
          } catch (IllegalAccessException e) {  
                e.printStackTrace(); 
          } 
      }
  }

  private boolean isNeedRestoreDialogListener(){
      return mDialogListenerKey == null? false:mDialogListener== null;
  }

}

代码有点复杂我先简单介绍下:
DialogListenerHolder中的mDialogListenerKey是存BaseDialogListener的子类的类名。

DialogListenerHolder中的saveDialogListenerKey(Bundle outState)方法是把mDialogListenerKey存到Bundle中,这样系统就可以存储下该值。供BaseActivity或BaseFragment的onSaveInstanceState(Bundle outState)方法调用。

DialogListenerHolder中的getDialogListenerKey(Bundle savedInstanceState)方法是从Bundle中取出mDialogListenerKey,供BaseActivity或BaseFragment的onCreate(Bundle savedInstanceState)调用。

DialogListenerHolder中的restoreDialogListener(Object o)方法很重要,作用是从参数o中去查找mDialogListenerKey对应的BaseDialogListener(查找范围是参数o和o中的属性),若找到并调用setDialogListener()方法。
所以这里对于调用者(调起Dialog)传递的BaseDialogListener有个要求:调用者实现了BaseDialogListener的子类或者调用者包含BaseDialogListener的子类的一个public属性

DialogFactory修改代码片段:代码地址

private DialogListenerHolder mListenerHolder;

public DialogFactory(FragmentManager fragmentManager, Bundle savedInstanceState){
    this.mFragmentManager = fragmentManager;    
    mListenerHolder.getDialogListenerKey(savedInstanceState);
}

public void restoreDialogListener(Object o){    
    mListenerHolder.restoreDialogListener(o);
}

BaseActivity修改代码片段:代码地址

public BaseDialogFragment.BaseDialogListener getDialogListener()  {
    return mDialogFactory.mListenerHolder.getDialogListener();
}

@Override
public void onSaveInstanceState(Bundle outState) {             
   super.onSaveInstanceState(outState);    
 mDialogFactory.mListenerHolder.saveDialogListenerKey(outState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mDialogFactory = new DialogFactory(getSupportFragmentManager(),savedInstanceState);  
    mDialogFactory.restoreDialogListener(this);
}

BaseFragment修改代码片段:代码地址

public BaseDialogFragment.BaseDialogListener getDialogListener()  {
    return mDialogFactory.mListenerHolder.getDialogListener();
}
 @Override
 public void onSaveInstanceState(Bundle outState) {    
    super.onSaveInstanceState(outState);    
   mDialogFactory.mListenerHolder.saveDialogListenerKey(outState);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {    
   super.onActivityCreated(savedInstanceState);
   mDialogFactory = new DialogFactory(getChildFragmentManager(),savedInstanceState); 
   mDialogFactory.restoreDialogListener(this);
}

到此为止我们的封装就一切ok了,高兴下。

总结

经过一步步艰辛的路程,封装DialogFragment的工作终于结束了,封装好的Dialog架构可以给您带来以下好处:

  • 可以让DialogFragment的使用像Dialog一样的简单、灵活,同时也保持了DialogFragment的优点,可以在任何的类中使用。就像下面代码:

      //某一个Activity中显示ConfirmDialog
      mDialogFactory.showConfirmDialog(title,message,confirmDialogListener);
      //某一个Fragment中显示ConfirmDialog
      mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);
      //非Activity和非Fragment的类中显示ConfirmDialog
      mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);
    
  • 很简单的新增新类型的Dialog

同时在使用的时候需要注意以下几点:

1 . 在既不是Activity也不是Fragment的类(下面我们简称该类)中调起Dialog要求:

  • 该类拥有DialogFactory 属性(DialogFactory 的值是从继承了BaseActivity的Activity或继承了BaseFragment的Fragment传递进来的)
  • 在给DialogFactory 属性赋值后,紧接着需要调用DialogFactory 的restoreDialogListener(Object)方法
  • 该类实现了XXDialogListener或者该类包含XXDialogListener这样的一个属性(该属性权限必须是public)

2 .在继承了BaseActivity的Activity(简称activity)中或者继承了BaseFragment的Fragment(简称fragment)中调起Dialog的要求:

  • activity或fragment实现了XXDialogListener或者是activity或fragment包含XXDialogListener这样的一个public类型的属性。

3 .若需要创建新的类型的Dialog,需要注意的是:

  • 继承BaseDialogFragment
  • 若该Dialog对外提供接口(接口需要继承BaseDialogListener,需要实现onReceiveDialogListener()方法)

以上是我个人的总结,希望对给Android学习者提供帮助。代码地址

本人微信:704451290

本人公众账号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容