国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Android:我為何要封裝DialogFragment?

bang590 / 1920人閱讀

摘要:我為何要封裝最近在重構(gòu)項(xiàng)目代碼,項(xiàng)目中創(chuàng)建對話框用的是,。在手機(jī)配置發(fā)生變化的時(shí)候,可以負(fù)責(zé)現(xiàn)場的恢復(fù)工作。以上做法,中屬性系統(tǒng)沒有為之保存,所以手機(jī)配置發(fā)生變化后,中的是。

我為何要封裝DialogFragment

最近在重構(gòu)項(xiàng)目代碼,項(xiàng)目中創(chuàng)建對話框用的是Dialog,AlertDialog。但是官方推出了DialogFragment來代替Dialog。那我就去認(rèn)真的了解下DialogFragment。

DialogFragment

DialogFragment是在Android3.0的時(shí)候被引入的,從其名字可以很直觀的看出它是一種基于Fragment的Dialog,可以用來創(chuàng)建對話框,它是用來替代Dialog的。一個(gè)新事物的出現(xiàn)是為了解決舊事物存在的問題,那不建議使用的Dialog存在什么問題呢?下面簡單的說下。

Dialog存在問題:

在手機(jī)配置發(fā)生變化后(比如:旋屏后),變化之前顯示的Dialog,變化之后不會(huì)顯示,更別提Dialog狀態(tài)的恢復(fù)了。

管理自定義的Dialog和系統(tǒng)原生的Dialog麻煩

DialogFragment怎么解決Dialog存在的問題:

DialogFragment說到底還是一個(gè)Fragment,因此它繼承了Fragment的所有特性。同理FragmentManager會(huì)管理DialogFragment。在手機(jī)配置發(fā)生變化的時(shí)候,F(xiàn)ragmentManager可以負(fù)責(zé)現(xiàn)場的恢復(fù)工作。調(diào)用DialogFragment的setArguments(bundle)方法進(jìn)行數(shù)據(jù)的設(shè)置,可以保證DialogFragment的數(shù)據(jù)也能恢復(fù)。

DialogFragment里的onCreateView和onCreateDIalog 2個(gè)方法,onCreateView可以用來創(chuàng)建自定義Dialog,onCreateDIalog 可以用Dialog來創(chuàng)建系統(tǒng)原生Dialog。可以在一個(gè)類中管理2種不同的dialog。

用DialogFragment替代Dialog

既然DialogFragment有這些好處,那我就毅然決然的對項(xiàng)目中的Dialog用DialogFragment來進(jìn)行替代。
重構(gòu)的思路是這樣的:

首先先創(chuàng)建一個(gè)ConfirmDialogFragment類(該類是用來創(chuàng)建確認(rèn)對話框的),ConfirmDialogFragment類繼承了DialogFragment。

其次在創(chuàng)建一個(gè)ProgressDialogFragment類(該類是用來創(chuàng)建進(jìn)度對話框),同時(shí)它也繼承了DialogFragment。

其他類型的Dialog就不舉例了。

最后在BaseActivity(項(xiàng)目中所有Activity的基類)添加顯示Dialog的方法,供BaseActivity的子類、Fragment、還有非Activity和非Fragment的類來調(diào)用。

我們先看下關(guān)鍵代碼片段:[代碼地址] [0]
ConfirmDialogFragment中的代碼片段:[代碼地址] [0]

  
  /**
    *用來創(chuàng)建確認(rèn)對話框

Created by niuxiaowei on 2015/10/16.

*/

class ConfirmDialogFragment extends DialogFragment{

       private ConfirmDialogListener mListener;

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

       /**

@param title

@param message

@param cancelable

@return
*/

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

Dialog onCreateDialog(Bundle savedInstanceState) {

          創(chuàng)建ConfirmDialog核心代碼,可以下載源代碼查看.....
      }

      @Override

void onAttach(Activity activity) {

          super.onAttach(activity);
          if (getActivity() instanceof ConfirmDialogListener ) {
                mListener= (ConfirmDialogListener ) getActivity();
          }
      }
      ......
}

ConfirmDialogFragment很關(guān)鍵的一點(diǎn),ConfirmDialogFragment中的mListener屬性的值是通過

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

方式獲取的。

BaseActivity中代碼片段:[代碼地址] [0]

 public class BaseActivity extends FragmentActivity 
 {
           /*
            *顯示確認(rèn)對話框方法
           */
          public void showConfirmDialog(...){
                 ......
           }
          
           /*
            *顯示進(jìn)度條對話框方法
           */
          public void showProgressDialog(...){
                 ......
          }
 }

那我們就重構(gòu)BaseActivity的子類顯示Dialog的代碼:
我拿MainActivity來舉例子:
MainActivity的關(guān)鍵重構(gòu)代碼:

    /*
    *實(shí)現(xiàn)確認(rèn)對話框的ConfirmDialogListener 接口
     *created by niuxiaowei
   */
   public class MainActivity extends BaseActivity implements ConfirmDialogListener {

           @Override
          public void onClick(DialogInterface dialogInterface, int i) {
              Toast.makeText(this,"點(diǎn)擊了MainActivity 調(diào)起的確認(rèn)對話框 i="+i,Toast.LENGTH_LONG).show();
          }
        
         //調(diào)用顯示ConfirmDialog代碼
         showConfirmDialog(...);

        //調(diào)用顯示ProgressDialog代碼
         showProgressDialog(...);
 }

現(xiàn)在MainActivity里的代碼運(yùn)行起來完全沒問題,因?yàn)镸ainActivity里面包含了3個(gè)Fragment,每個(gè)Fragment里面都有顯示ConfirmDialog和ProgressDialog的代碼,所以開始重構(gòu)這3個(gè)Fragment:
重構(gòu)思路:

每個(gè)Fragment里都可以獲取到相對應(yīng)的Activity的實(shí)例,只要獲取到實(shí)例就可以調(diào)用顯示對話框的方法來顯示對話框了。

對話框中的事件怎么傳遞給Fragment問題?Activity可以獲取到Fragment的實(shí)例,對話框可以把事件傳遞給Activity,因此Activity順理成章的可以把事件傳遞給對應(yīng)的Fragment。

一個(gè)Activity有多個(gè)Fragment調(diào)用顯示對話框的方法,在Activity的實(shí)現(xiàn)了對話框接口的方法里怎樣區(qū)分不同的Fragment調(diào)用者?可以在BaseActivity顯示對話框的方法里加個(gè)id參數(shù),用id來區(qū)分不同的Fragment調(diào)用者。
那就上關(guān)鍵代碼片段:

MainActivity中的AFragment代碼片段:

  public AFragment extends Fragment implements ConfirmDialogListener{

         @Override
          public void onClick(DialogInterface dialogInterface, int i) {
              Toast.makeText(this,"點(diǎn)擊了AFragment 調(diào)起的確認(rèn)對話框 i="+i,Toast.LENGTH_LONG).show();
          }
        
         //調(diào)用顯示ConfirmDialog代碼
         getActivity().showConfirmDialog(...);
  }

同理MainActivity的BFragment,CFragment的重構(gòu)與AFragment類似。
MainActivity的關(guān)鍵代碼片段:

 
  @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){
                   調(diào)用自己的方法
             }
  }
產(chǎn)生的問題

看了MainActivity的onClick方法里面代碼我都對自己無語了,onClick方法里面充斥著各種的if else 語句,并且當(dāng)前的MainActivity里,若再有別的顯示ConfirmDialog的調(diào)用者,onClick方法里少不了要增加對應(yīng)的else if語句。MainActivity只是項(xiàng)目中所有Activity的一個(gè)縮影。其他的Activity也會(huì)遇到同樣的問題(這不是我意淫的,提早預(yù)估到問題,提早入手進(jìn)行解決總是好的)

我們拿MainActivity來代表所有的Activity總結(jié)下使用DialogFragment創(chuàng)建Dialog產(chǎn)生的問題:

MainActivity里的onClick方法維護(hù)、擴(kuò)展性不好,充斥著各種if else if語句,可讀性也不好。

MainActivity里的onClick方法除了把Dialog的事件轉(zhuǎn)發(fā)給相對應(yīng)的調(diào)用者之外,沒有多任何其他操作,所以是多余的

顯示Dialog的方法不靈活

存在這些問題嚴(yán)重影響了我后面的重構(gòu)工作,于是乎我就去國內(nèi)國外網(wǎng)站上搜索對應(yīng)的解決方法,但是也沒有找到好的方法,最后我就想辦法自己解決上面的問題,這也是我為何要封裝DialogFragment的緣由

封裝DialogFragment,讓DialogFragment使用非常簡單、靈活

我們仔細(xì)的分析下上文的問題的主要原因是顯示Dialog的方法沒有把Dialog里面的開放的接口作為參數(shù)導(dǎo)致的,假如能像下面的使用方式:

    //某一個(gè)Activity中顯示ConfirmDialog
    showConfirmDialog(title,message,confirmDialogListener);
    //某一個(gè)Fragment中顯示ConfirmDialog
    getActivity().showConfirmDialog(this,message,confirmDialogListener);
    //非Activity和非Fragment的類中顯示ConfirmDialog
    mActivity.showConfirmDialog(this,message,confirmDialogListener);

上文中所有的問題都可以解決。

為什么不按下面的做法做

做法1:那我們直接把ConfirmDialogListener 的實(shí)例賦值給ConfirmDialogFragment 的實(shí)例的mListener屬性,以下為代碼:

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

那我就詳細(xì)的解釋下為什么不這樣做的具體原因:

在創(chuàng)建Fragment的時(shí)候,最好是把傳遞給Fragment的數(shù)據(jù)存放在Bundle中,然后在調(diào)用fragment的setArguments(bundle)方法進(jìn)行數(shù)據(jù)的設(shè)置,這種做法好處是:系統(tǒng)會(huì)保存Fragment的數(shù)據(jù),在手機(jī)配置發(fā)生變化后(比如旋屏),系統(tǒng)會(huì)把保存的Fragment數(shù)據(jù)進(jìn)行恢復(fù)。

以上做法,ConfirmDialogFragment 中mListener屬性系統(tǒng)沒有為之保存,所以手機(jī)配置發(fā)生變化后,ConfirmDialogFragment 中的mListener 是null。

做法2:那我們是否可以把ConfirmDialogListener實(shí)例(ConfirmDialogListener是ConfirmDialogFragment 對外開放的接口)存放在Bundle中?
答案是不可以,首先 Bundle對存放的數(shù)據(jù)是有限制的,把ConfirmDialogListener的實(shí)例存入Bundle中是比較復(fù)雜的操作。其次即使通過艱辛萬苦把ConfirmDialogListener實(shí)例存入了Bundle中,保存ConfirmDialogListener實(shí)例是毫無意義的,只有保存數(shù)據(jù)對于Fragment來說才有意義,保存行為對Fragment是無意義的。

有思路

我們在回顧下ConfirmDialogFragment中onAttach的方法的關(guān)鍵代碼:[代碼地址] [0]

   @Override
   public void onAttach(Activity activity) {
       if(getActivity() instanceof ConfirmDialogListener){ 
          //關(guān)鍵代碼
           mListener= (ConfirmDialogListener)getActivity();
      }
    }

以上代碼的關(guān)鍵之處在于mListener= (ConfirmDialogListener)getActivity()。同時(shí)痛點(diǎn)也在此處,這是一種類似于硬編碼的方式,硬編碼的一個(gè)不好的地方就是沒有擴(kuò)展性。解決思路:

那我們就想辦法讓此處變的有彈性。我們可以把BaseActivity想象為一個(gè)ConfirmDialogListener的存取工具,調(diào)用者可以把自己實(shí)現(xiàn)的ConfirmDialogListener存入BaseActivity中, ConfirmDialogFragment可以從BaseActivity中取出ConfirmDialogListener實(shí)例,那我的問題就迎刃而解了。

既然可以獲取到BaseActivity的實(shí)例,那也可以獲取到BaseFragment的實(shí)例(getParentFragment()可以獲取到)。既然BaseFragment實(shí)例可以獲取到,那解決ConfirmDialogFragment同時(shí)服務(wù)于BaseActivity和BaseFragment就不是問題了

同時(shí)我還想解決在任何的類中(不管Fragment、Activity、或其他類中)顯示Dialog不需要依賴BaseActivity。而是有一個(gè)類(假如叫DialogFactory)定義顯示各種Dialog的方法。像下面一樣:

     //某一個(gè)Activity中顯示ConfirmDialog
    mDialogFactory.showConfirmDialog(title,message,confirmDialogListener);
    //某一個(gè)Fragment中顯示ConfirmDialog
    mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);
    //非Activity和非Fragment的類中顯示ConfirmDialog
    mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);

那我就說下思路:

新建DialogFactory類,該類封裝了顯示各種Dialog的方法

新建BaseDialogFragment類,該類是各種類型Dialog的基類,里面封裝了一些公用的方法

修改BaseActivity和BaseFragment類,在各自的類中分別定義DialogFactory屬性mDialogFactory,這樣顯示Dialog的任務(wù)就交給了mDialogFactory

DialogFactory 代碼:[代碼地址] [0]

  /** * 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;  
        }

        /** * 進(jìn)度條對話框 

@param message 進(jìn)度條顯示的信息

@param cancelable 點(diǎn)擊空白處是否可以取消 */

void showProgressDialog(String message, boolean cancelable){

             省略此處代碼......
       }

       /**

顯示確認(rèn)對話框,dialogId是用來區(qū)分不同對話框的

@param title 對話框title

@param message

@param cancelable

@param listener

      */

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關(guān)鍵代碼介紹:

DialogFactory可以供任何的類來使用

mFragmentManager屬性在現(xiàn)實(shí)Dialog時(shí)起作用,若調(diào)用者(顯示Dialog)是Activity,則傳遞getFragmentManager();若調(diào)用者是Fragment,則傳遞getChildFragmentManager()。不過不需要擔(dān)心這些,BaseActivity和BaseFragment都已經(jīng)封裝了這些參數(shù)

DialogFactory把調(diào)用者傳遞過來的BaseDialogListener傳遞給Activity或Fragment

BaseDialogFragment代碼:[代碼地址] [0]

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

        /** * 基礎(chǔ)的dialog listener,沒有提供任何的方法,擴(kuò)展的dialog,若該dialog有l(wèi)istener則必須繼承本接口 */
        public static interface BaseDialogListener{}

        /** * 接收dialog listener對象,具體由子類進(jìn)行實(shí)現(xiàn) * @param listener */
        protected void onReceiveDialogListener(BaseDialogListener listener){}

         @Override
         public void onActivityCreated(Bundle savedInstanceState) {

              /*解析BaseDialogListener,fragment的級別要大于activity,若 

(getParentFragment() instanceof BaseFragment)為true* ,

表明是一個(gè)fragment調(diào)起的dialog,否則是一個(gè)activity調(diào)起的diaolog

*/

             BaseDialogListener listener = null;

(getParentFragment() instanceof BaseFragment) {

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

BaseDialogFragment關(guān)鍵代碼介紹:

BaseDialogListener定義一個(gè)空方法接口,新增的Dialog(若該Dialog包含對外接口),則新增的Dialog提供的對外接口必須繼承BaseDialogListener

onReceiveDialogListener方法是提供給子類來實(shí)現(xiàn),讓子類來接收調(diào)用者傳遞進(jìn)來的BaseDialogListener實(shí)例

onActivityCreated方法很重要,該方法是使BaseDialogFragment可以兼容Activity和Fragment的關(guān)鍵代碼

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

上面代碼的作用是假如當(dāng)前調(diào)用者(顯示Dialog)是一個(gè)Fragment,則會(huì)把Fragment中持有的BaseDialogListener賦給對應(yīng)的Dialog,若當(dāng)前調(diào)用者是一個(gè)Activity,則會(huì)做同樣的事情

ConfirmDialogFragment 關(guān)鍵代碼片段:[代碼地址] [0]

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

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

ProgressDialogFragment基本沒發(fā)生多大改變,我們就不貼具體代碼了。

修改BaseActivity和BaseFragment類關(guān)鍵代碼:

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持有調(diào)用者傳遞的BaseDialogListener的實(shí)例,BaseDialogFragment會(huì)從getDialogListener()方法獲取該實(shí)例

BaseFragment的修改和BaseActivity一樣,就不介紹了。

那我們在理一下上面代碼的思路:

DialogFactory封裝了顯示各種Dialog的方法,使用者使用它來顯示Dialog。它會(huì)把使用者傳遞的BaseDialogListener傳遞給BaseActivity或BaseFragment

BaseActivity和BaseFragment在傳遞BaseDialogListener起了一個(gè)橋梁的作用。當(dāng)Dialog即將被顯示時(shí),BaseDialogFragment會(huì)從BaseActivity或BaseFragment獲取BaseDialogListener

解決最棘手的問題

當(dāng)我還沉浸在happy中時(shí),突然一個(gè)問題出現(xiàn)了,旋屏后重新彈出的ConfirmDialog的點(diǎn)擊事件卻沒傳遞給調(diào)用者,我就細(xì)細(xì)的想原來是旋屏后BaseActivity或BaseFragment里的mListener為空了。那我就繼續(xù)解決這棘手問題,為什么棘手呢?因?yàn)槲覀円恢倍际窃趪@著怎樣解決旋屏后Dialog中的mListener屬性的值(BaseDialogListener的實(shí)例)怎么重新獲取的問題,但是經(jīng)過一番努力還是沒成功,不行我還得繼續(xù)想辦法。

上文中也提到過對于Fragment存放行為是毫無意義的,那我們就換個(gè)角度考慮問題,我們先用BaseFragment來舉例子(BaseActivity類似):

在BaseFragment用一個(gè)屬性mDialogListenerKey去存mListener(類型是BaseDialogListener)屬性的類名,當(dāng)手機(jī)配置發(fā)生變化的時(shí)候在BaseFragment的onSaveInstance(bundle)方法中把mDialogListenerKey存入Bundle中(前提條件Dialog沒消失)

當(dāng)BaseFragment重新被創(chuàng)建的時(shí)候,在onCreate(savedInstanceState)方法中從Bundle中把mDialogListenerKey值讀出來

根據(jù)mDialogListenerKey去找到對應(yīng)的BaseDialogListener子類的實(shí)例

把上步中找到的實(shí)例通過調(diào)用BaseFragment的setDialogListener()方法進(jìn)行設(shè)置

那我們就開始寫代碼:
新建DialogListenerHolder,該類用來持有調(diào)用者傳遞的BaseDialogListener實(shí)例,即把原來BaseActivity或BaseFragment里的mListener屬性放到該類中
DialogListenerHolder修改的代碼片段:[代碼地址] [0]

public class DialogListenerHolder{

      private BaseDialogListener mDialogListener;
      /** * 對話框的listener的key值,用類名作為key值,
      *主要用來在手機(jī)配置發(fā)生變化時(shí)(橫屏換為豎屏),
       *當(dāng)現(xiàn)場恢復(fù)時(shí),能正確的找到對話框的listener */
      private String mDialogListenerKey;

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

      /** * 把listener的key值保存在bundle中,配置發(fā)生變化的情況下(橫屏換為豎屏),在從bundle中取listener的key值

@param outState */

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");
        }
  }

  /** * 這個(gè)方法很重要,是恢復(fù)dialog listener的一個(gè)關(guān)鍵點(diǎn),
  *在初始化DialogFactory或把DialogFactory賦值后,調(diào)用該方法,把調(diào)用該方法所在

的類的實(shí)例作為參數(shù)。 該方法會(huì)把param中的屬性依次遍歷,嘗試找屬性是BaseDialogFragment.BaseDialogListener的實(shí)例,

并且該屬性就是保存在bundle中的dialog listener key對應(yīng)的dialog listener

@param o */

void restoreDialogListener(Object o){

       if(o == null){
             return; 
        } 
        if(!isNeedRestoreDialogListener()){
             return;
        } 
      //先嘗試找傳進(jìn)來的實(shí)例
       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(); 
         } 
     }
 }

boolean isNeedRestoreDialogListener(){

     return mDialogListenerKey == null? false:mDialogListener== null;
 }

}

代碼有點(diǎn)復(fù)雜我先簡單介紹下:

DialogListenerHolder中的mDialogListenerKey是存BaseDialogListener的子類的類名。

DialogListenerHolder中的saveDialogListenerKey(Bundle outState)方法是把mDialogListenerKey存到Bundle中,這樣系統(tǒng)就可以存儲(chǔ)下該值。供BaseActivity或BaseFragment的onSaveInstanceState(Bundle outState)方法調(diào)用。

DialogListenerHolder中的getDialogListenerKey(Bundle savedInstanceState)方法是從Bundle中取出mDialogListenerKey,供BaseActivity或BaseFragment的onCreate(Bundle savedInstanceState)調(diào)用。

DialogListenerHolder中的restoreDialogListener(Object o)方法很重要,作用是從參數(shù)o中去查找mDialogListenerKey對應(yīng)的BaseDialogListener(查找范圍是參數(shù)o和o中的屬性),若找到并調(diào)用setDialogListener()方法。
所以這里對于調(diào)用者(調(diào)起Dialog)傳遞的BaseDialogListener有個(gè)要求:調(diào)用者實(shí)現(xiàn)了BaseDialogListener的子類或者調(diào)用者包含BaseDialogListener的子類的一個(gè)public屬性

DialogFactory修改代碼片段:[代碼地址] [0]

private DialogListenerHolder mListenerHolder;

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

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

BaseActivity修改代碼片段:[代碼地址] [0]

 
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修改代碼片段:[代碼地址] [0]

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了,高興下。

總結(jié)

經(jīng)過一步步艱辛的路程,封裝DialogFragment的工作終于結(jié)束了,封裝好的Dialog架構(gòu)可以給您帶來以下好處:

可以讓DialogFragment的使用像Dialog一樣的簡單、靈活,同時(shí)也保持了DialogFragment的優(yōu)點(diǎn),可以在任何的類中使用。就像下面代碼:

    //某一個(gè)Activity中顯示ConfirmDialog
    mDialogFactory.showConfirmDialog(title,message,confirmDialogListener);
    //某一個(gè)Fragment中顯示ConfirmDialog
    mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);
    //非Activity和非Fragment的類中顯示ConfirmDialog
    mDialogFactory.showConfirmDialog(this,message,confirmDialogListener);

很簡單的新增新類型的Dialog

同時(shí)在使用的時(shí)候需要注意以下幾點(diǎn):

1 . 在既不是Activity也不是Fragment的類(下面我們簡稱該類)中調(diào)起Dialog要求:

該類擁有DialogFactory 屬性(DialogFactory 的值是從繼承了BaseActivity的Activity或繼承了BaseFragment的Fragment傳遞進(jìn)來的)

在給DialogFactory 屬性賦值后,緊接著需要調(diào)用DialogFactory 的restoreDialogListener(Object)方法

該類實(shí)現(xiàn)了XXDialogListener或者該類包含XXDialogListener這樣的一個(gè)屬性(該屬性權(quán)限必須是public)

.在繼承了BaseActivity的Activity(簡稱activity)中或者繼承了BaseFragment的Fragment(簡稱fragment)中調(diào)起Dialog的要求:

activity或fragment實(shí)現(xiàn)了XXDialogListener或者是activity或fragment包含XXDialogListener這樣的一個(gè)public類型的屬性。

3 .若需要?jiǎng)?chuàng)建新的類型的Dialog,需要注意的是:

繼承BaseDialogFragment

若該Dialog對外提供接口(接口需要繼承BaseDialogListener,需要實(shí)現(xiàn)onReceiveDialogListener()方法)

以上是我個(gè)人的總結(jié),希望對給Android學(xué)習(xí)者提供幫助。[代碼地址] [0]

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/65532.html

相關(guān)文章

  • Android之Window和彈窗問題

    摘要:指向的主要是實(shí)現(xiàn)和通信的。子不能單獨(dú)存在,需附屬特定的父。系統(tǒng)需申明權(quán)限才能創(chuàng)建。和類似,同樣是通過來實(shí)現(xiàn)。將添加到中顯示。方法完成的顯示。執(zhí)行的檢查參數(shù)等設(shè)置檢查將保存到中將保存到中。因?yàn)橥ㄟ^和的將無法獲取到從而導(dǎo)致失敗。 目錄介紹 10.0.0.1 Window是什么?如何通過WindowManager添加Window(代碼實(shí)現(xiàn))?WindowManager的主要功能是什么? 1...

    Lorry_Lu 評論0 收藏0
  • Snackbar源碼分析

    摘要:分別對應(yīng)于中的幾個(gè)常量值。源碼分析的方法源碼分析創(chuàng)建需要使用靜態(tài)的方法,并且其中的參數(shù)是一個(gè)查找父布局的起點(diǎn)這里可以看到,的布局是,假如我們需要自定義并且設(shè)置字體顏色,大小等屬性。表示回調(diào)已在隊(duì)列中。 目錄介紹 1.最簡單創(chuàng)造方法 1.1 Snackbar作用 1.2 最簡單的創(chuàng)建 1.3 Snackbar消失的幾種方式 2.源碼分析 2.1 Snackbar的make方...

    why_rookie 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<