Android:我为什么要封装DialogFragment?

我为什么要封装DialogFragment

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

DialogFragment

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

Dialog存在问题:

  • 在手机配置发生变化后(好比:旋屏后),变化以前显示的Dialog,变化以后不会显示,更别提Dialog状态的恢复了。编程

  • 管理自定义的Dialog和系统原生的Dialog麻烦架构

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

  • DialogFragment说到底仍是一个Fragment,所以它继承了Fragment的全部特性。同理FragmentManager会管理DialogFragment。在手机配置发生变化的时候,FragmentManager能够负责现场的恢复工做。调用DialogFragment的setArguments(bundle)方法进行数据的设置,能够保证DialogFragment的数据也能恢复。app

  • DialogFragment里的onCreateView和onCreateDIalog 2个方法,onCreateView能够用来建立自定义Dialog,onCreateDIalog 能够用Dialog来建立系统原生Dialog。能够在一个类中管理2种不一样的dialog。ide

用DialogFragment替代Dialog

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

  • 首先先建立一个ConfirmDialogFragment类(该类是用来建立确认对话框的),ConfirmDialogFragment类继承了DialogFragment。学习

  • 其次在建立一个ProgressDialogFragment类(该类是用来建立进度对话框),同时它也继承了DialogFragment。网站

  • 其余类型的Dialog就不举例了。this

  • 最后在BaseActivity(项目中全部Activity的基类)添加显示Dialog的方法,供BaseActivity的子类、Fragment、还有非Activity和非Fragment的类来调用。

咱们先看下关键代码片断:代码地址
ConfirmDialogFragment中的代码片断:代码地址

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

  /**

    *用来建立确认对话框

   * 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属性的值是经过

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

   @Override

        public void onAttach(Activity activity) {

            super.onAttach(activity);

            if (getActivity() instanceof ConfirmDialogListener ) {

                  mListener= (ConfirmDialogListener ) getActivity();

            }

        }

方式获取的。

BaseActivity中代码片断:代码地址

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

public class BaseActivity extends FragmentActivity

{

           /*

            *显示确认对话框方法

           */

          public void showConfirmDialog(...){

                 ......

           }

 

           /*

            *显示进度条对话框方法

           */

          public void showProgressDialog(...){

                 ......

          }

}

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

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

    /*

    *实现确认对话框的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代码片断:

     

     

     

     

     

     

    Java

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    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的关键代码片断:

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

  @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里面的开放的接口做为参数致使的,假如能像下面的使用方式:

 

 

 

 

 

Java

 

1

2

3

4

5

6

    //某一个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属性,如下为代码:

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

      //直接把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的方法的关键代码:代码地址

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

   @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的方法。像下面同样:

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

     //某一个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 代码:代码地址

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

  /** * 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代码:代码地址

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

    /** * 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的关键代码

     

     

     

     

     

     

    Java

     

    1

    2

    3

    4

    5

    if (getParentFragment() instanceof BaseFragment) {    

               listener = ((BaseFragment) getParentFragment()).getDialogListener();

      }else if(getActivity() instanceof BaseActivity){

              listener = ((BaseActivity)getActivity()).getDialogListener();

      }


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

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

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

        //继承BaseDialogListener

        public static interface ConfirmDialogListener extends BaseDialogListener,DialogInterface.OnClickListener{

        }

 

        public void onReceiveDialogListener(BaseDialogListener listener){

              if(listener instanceof ConfirmDialogListener ){

                       mListener = (ConfirmDialogListener )listener;

              }

       }

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

修改BaseActivity和BaseFragment类关键代码:

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

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修改的代码片断:代码地址

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

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

代码有点复杂我先简单介绍下:
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修改代码片断:代码地址

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

private DialogListenerHolder mListenerHolder;

 

public DialogFactory(FragmentManager fragmentManager, Bundle savedInstanceState){

    this.mFragmentManager = fragmentManager;    

    mListenerHolder.getDialogListenerKey(savedInstanceState);

}

 

public void restoreDialogListener(Object o){    

    mListenerHolder.restoreDialogListener(o);

}

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

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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修改代码片断:代码地址

 

 

 

 

 

 

Java

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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的优势,能够在任何的类中使用。就像下面代码:

     

     

     

     

     

     

    Java

     

    1

    2

    3

    4

    5

    6

      //某一个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学习者提供帮助。代码地址

问啊-定制化IT教育平台,牛人一对一服务,有问必答,开发编程社交头条 官方网站:www.wenaaa.com 下载问啊APP,参与官方悬赏,赚百元现金。

QQ群290551701 汇集不少互联网精英,技术总监,架构师,项目经理!开源技术研究,欢迎业内人士,大牛及新手有志于从事IT行业人员进入!

相关文章
相关标签/搜索