日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DialogFragment源码分析

發布時間:2025/6/17 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DialogFragment源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

目錄介紹

  • 1.最簡單的使用方法
    • 1.1 官方建議
    • 1.2 最簡單的使用方法
    • 1.3 DialogFragment做屏幕適配
  • 2.源碼分析
    • 2.1 DialogFragment繼承Fragment
    • 2.2 onCreate(@Nullable Bundle savedInstanceState)源碼分析
    • 2.3 setStyle(@DialogStyle int style, @StyleRes int theme)
    • 2.4 onActivityCreated(Bundle savedInstanceState)源碼分析
    • 2.5 onCreateDialog(Bundle savedInstanceState)源碼分析
    • 2.6 重點分析彈窗展示和銷毀源碼
  • 3.經典總結
  • 4.DialogFragment封裝庫介紹
  • 5.常見問題總結
    • 5.1 使用中show()方法遇到的IllegalStateException

好消息

  • 博客筆記大匯總【16年3月到至今】,包括Java基礎及深入知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug匯總,當然也在工作之余收集了大量的面試題,長期更新維護并且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計47篇[近20萬字],轉載請注明出處,謝謝!
  • 鏈接地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好,可以star一下,謝謝!當然也歡迎提出建議,萬事起于忽微,量變引起質變!
  • DialogFragment封裝庫項目地址:https://github.com/yangchong211/YCDialog

1.最簡單的使用方法

1.1 官方建議

  • Android比較推薦采用DialogFragment實現對話框,它完全能夠實現Dialog的所有需求,并且還能復用Fragment的生命周期管理,被后臺殺死后,可以恢復重建。

1.2 最簡單的使用方法

  • 如下所示: public class CustomDialogFragment extends DialogFragment {@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);//設置樣式setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CenterDialog);}@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {return inflater.inflate(R.layout.view_fragment_dialog, container, false);}public static void showDialog(FragmentActivity activity){CustomDialogFragment customDialogFragment = new CustomDialogFragment();customDialogFragment.show(activity.getSupportFragmentManager(),"yc");} }//然后一行代碼調用 CustomDialogFragment.showDialog(this);
  • 1.2.1 創建theme主題樣式,并且進行設置
    • 設置樣式,以DialogFragment為例,只需要在onCreate中setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CenterDialog)即可。
    • 注意,CenterDialog中可以設置彈窗的動畫效果。
    • 注意一下style常量,這里只是展示常用的。
    STYLE_NORMAL:會顯示一個普通的dialog STYLE_NO_TITLE:不帶標題的dialog STYLE_NO_FRAME:無框的dialog STYLE_NO_INPUT:無法輸入內容的dialog,即不接收輸入的焦點,而且觸摸無效。
  • 1.2.2 重寫onCreateView方法創建彈窗
  • 1.2.3 創建類的對象,然后調用show(FragmentManager manager, String tag)方法即可創建出彈窗
  • 1.2.4 如何去掉標題欄,也許你會問,為什么第二種要在super.onActivityCreated(savedInstanceState)之前設置呢。這個是因為,看了源碼之后才知道onActivityCreated這個方法中,有mDialog.setContentView(view)這一步,說到setContentView是不是很熟悉。沒錯,后面再深度解析這塊源碼思路…… //第一種 //設置樣式時,使用STYLE_NO_TITLE setStyle(DialogFragment.STYLE_NO_TITLE, R.style.CenterDialog);//第二種 @Override public void onActivityCreated(Bundle savedInstanceState) {Window window = getDialog().getWindow();if(window!=null){window.requestFeature(Window.FEATURE_NO_TITLE);}super.onActivityCreated(savedInstanceState); }

2.源碼分析

2.1 DialogFragment繼承Fragment

  • DialogFragment是繼承Fragment,具有Fragment的生命周期,本質上說就是Fragment,只是其內部還有一個dialog而已。你既可以當它是Dialog使用,也可以把它作為Fragment使用。

2.2 onCreate(@Nullable Bundle savedInstanceState)源碼分析

  • onCreate這個方法主要是保存一些屬性狀態,比如style樣式,theme注意,是否可以取消,后退棧的ID等等。
    • 重點看一下mShowsDialog這個參數,這個參數是Boolean值,mShowsDialog = mContainerId == 0;所以,默認情況下,mContainerId就是0,所以mShowsDialog就是true;而當你在把它當成Fragment使用時,會為其指定xml布局中位置,那么mContainerId也會不為0,所以mShowsDialog就是false。
    @Override public void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);mShowsDialog = mContainerId == 0;if (savedInstanceState != null) {mStyle = savedInstanceState.getInt(SAVED_STYLE, STYLE_NORMAL);mTheme = savedInstanceState.getInt(SAVED_THEME, 0);mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, true);mShowsDialog = savedInstanceState.getBoolean(SAVED_SHOWS_DIALOG, mShowsDialog);mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, -1);} }
  • mShowsDialog這個參數的作用
    • 然后直接搜索,可以看到這個參數,可以看到mShowsDialog是false,如果不是Dialog,則調用Fragment自身的方法;否則,就先創建一個dialog,然后,根據之前設置的style,通過setupDialog(mDialog, mStyle),對dialog賦值。所以,setStyle這個方法調用,一定要在onCreateView之前。一般來講,都會放到onCreate中調用。

2.3 setStyle(@DialogStyle int style, @StyleRes int theme)源碼分析

  • 這個方法很重要呢,注意是設置對話框的基本外觀和設置主題等等。通過手動設置Dialog和Window可以實現相同的效果,如果是在對話框創建之后調用它將會失去作用……
    • 通過這個方法,可以看到,在不設置theme,即為0的情況下,theme會被設置為android.R.style.Theme_Panel。
    public void setStyle(@DialogStyle int style, @StyleRes int theme) {mStyle = style;if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {mTheme = android.R.style.Theme_Panel;}if (theme != 0) {mTheme = theme;} }

2.4 onActivityCreated(Bundle savedInstanceState)源碼分析

  • 該方法的作用主要是:當DialogFragment依附的Activity被創建的時候調用,此時fragment的活動窗體被初始化
    • 可以看到這個方法,如果是彈窗已經show出來的話,則直接return。然后通過setContentView方法將view創建出來。同時還設置了彈窗是否可以被取消,以及點擊事件等等。

2.5 onCreateDialog(Bundle savedInstanceState)源碼分析

  • onCreateDialog方法,你可以重寫這個方法,創建一個自己定義好的dialog。默認情況下,會自己創建一個Dialog。 @NonNull public Dialog onCreateDialog(Bundle savedInstanceState) {return new Dialog(getActivity(), getTheme()); }

2.6 重點分析彈窗展示和銷毀源碼

2.6.1 show方法
  • 第一種:顯示對話框,將片段添加到給定的FragmentManager中。這對于顯式創建事務、使用給定的標記將片段添加到事務并提交它是很方便的。這樣做可以將事務添加到后臺堆棧。當片段被取消時,將執行一個新的事務來從活動中刪除它。
  • 第二種:顯示對話框,使用現有事務添加片段,然后提交事務。
  • 共同點:這兩種顯示方式都是通過tag的方式將DialogFragment以事務的形式提交,不同的是第二種方式是采用已經創建過的transaction,并且他返回了一個int類型的數值mBackStackId,mBackStackId是干什么用的呢?
    • mBackStackId:是做為將DialogFragment壓入回退棧的編號,初始值是-1,如果DialogFragment是用第二種方式show的話,他將被transaction默認壓入回退棧,mBackStackId=transaction.commit(),此時她的回退棧編號大于0,她的具體使用在dismissInternal方法中后面會具體介紹
    public void show(FragmentManager manager, String tag) {mDismissed = false;mShownByMe = true;FragmentTransaction ft = manager.beginTransaction();ft.add(this, tag);ft.commit(); }public int show(FragmentTransaction transaction, String tag) {mDismissed = false;mShownByMe = true;transaction.add(this, tag);mViewDestroyed = false;mBackStackId = transaction.commit();return mBackStackId; }
2.6.2 dismiss()銷毀方法
  • 在源碼中可以看到這兩個方法都調用了dismissInternal(boolean)方法,不同的是傳入的boolean值一個為false一個為true,那么究竟這個boolean起到什么作用呢?
    • 在dismissInternal這個方法中,主要操作了:如果對話框已經不可見就跳出方法體;設置對話框消失,然后將對話框屬性設置不可見;如果DialogFragment中的Dialog對象不為空,就讓其內的對話框消失;然后銷毀View;對于回退棧編號mBackStackId,在前面show方法源碼分析時提到這個呢!主要是用show(FragmentTransaction transaction, String tag)這個方法來壓棧的,所以要取消對話框需要在這里面判斷,已壓棧的要彈出回退棧,這個回退棧是由Activity來管理的,如果show(FragmentManager manager, String tag)方式的話則不需要彈棧,只需要在FragmentTransaction中將其remove掉即可。
    • 簡單總結就是:調用dialog的dismiss方法后,如果自己在后退棧中,就將自己從后退棧中移除掉;如果自己不在后退棧中,就將自己從FragmentManager中移除掉。
2.6.3 dialog顯示與隱藏
  • 具體看下面代碼
    • 在OnStart的時候,將dialog進行show出來;在生命周期方法onStop()時,則是將其先隱藏;最后在onDestroyView方法,它會將dialog銷毀并置null。
    @Override public void onStart() {super.onStart();if (mDialog != null) {mViewDestroyed = false;mDialog.show();} }@Override public void onStop() {super.onStop();if (mDialog != null) {mDialog.hide();} }@Override public void onDestroyView() {super.onDestroyView();if (mDialog != null) {// Set removed here because this dismissal is just to hide// the dialog -- we don't want this to cause the fragment to// actually be removed.mViewDestroyed = true;mDialog.dismiss();mDialog = null;} }

3.經典總結

  • DialogFragment是繼承Fragment,具有Fragment的生命周期,本質上說就是Fragment,只是其內部還有一個dialog而已。你既可以當它是Dialog使用,也可以把它作為Fragment使用。
  • onCreateView可以加載客戶化更高的對話框,onCreateDialog加載系統AlertDialog類型對話框比較合適。
  • DialogFragmnet對話框橫屏時對話框不會關閉,因為DailogFragment有Fragment屬性,會在屏幕發生變化時重新創建DialogFragment。
  • setStyle的調用點,要放在onCreateView前,一般是放在onCreat方法中執行,否則,設置的style和theme將不起作用!setStyle中,style的參數是不可以相互一起使用的,只能用一個,如果還不滿足你使用,可以通過設置theme來滿足。

4.DialogFragment封裝庫介紹

項目地址:https://github.com/yangchong211/YCDialog

  • 自定義對話框,其中包括:自定義Toast,采用builder模式,支持設置吐司多個屬性;自定義dialog控件,仿IOS底部彈窗;自定義DialogFragment彈窗,支持自定義布局,也支持填充recyclerView布局;自定義PopupWindow彈窗,輕量級,還有自定義Snackbar等等;還有自定義loading加載窗,簡單便用。這里只是展示dialogFragment用法!
  • 第一種:鏈式編程,如下所示 BottomDialogFragment.create(getSupportFragmentManager()).setViewListener(new BottomDialogFragment.ViewListener() {@Overridepublic void bindView(View v) {}}).setLayoutRes(R.layout.dialog_bottom_layout_list).setDimAmount(0.5f).setTag("BottomDialog").setCancelOutside(true).setHeight(getScreenHeight() / 2).show();
  • 第二種:直接繼承,可以高度定制自己想要的彈窗 public class ADialog extends BaseDialogFragment {@Overrideprotected boolean isCancel() {return false;}@Overridepublic int getLayoutRes() {return 0;}@Overridepublic void bindView(View v) {} }

5.常見問題總結

5.1 使用中show()方法遇到的IllegalStateException

  • 報錯日志如下: lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1493)
  • 出現該問題的原因
    • Activity 調用了onSaveInstanceState()以后有觸發了dialog的顯示,dialog.show()方法里邊用的是commit()而不是commitAllowingStateLoss()
  • 追蹤報錯日志的來源
    • 于是,我挺好奇,show方法中只有兩個參數,決定從getSupportFragmentManager()方法分析.FragmentManager是抽象類,我這里主要是看FragmentManagerImpl實現類代碼
    //第一步: public FragmentManager getSupportFragmentManager() {return mFragments.getSupportFragmentManager(); }//第二步: public FragmentManager getSupportFragmentManager() {return mHost.getFragmentManagerImpl(); }//第三步: FragmentManagerImpl getFragmentManagerImpl() {return mFragmentManager; }//第四步:看beginTransaction()方法 @Override public FragmentTransaction beginTransaction() {return new BackStackRecord(this); }//第五步:看BackStackRecord類中看commit方法 @Override public int commit() {return commitInternal(false); }@Override public int commitAllowingStateLoss() {return commitInternal(true); }//第六步:可以看到這倆函數的區別就是commitInternal()方法中參數一個為true,一個為false int commitInternal(boolean allowStateLoss) {if (mCommitted) throw new IllegalStateException("commit already called");if (FragmentManagerImpl.DEBUG) {Log.v(TAG, "Commit: " + this);LogWriter logw = new LogWriter(TAG);PrintWriter pw = new PrintWriter(logw);dump(" ", null, pw, null);pw.close();}mCommitted = true;if (mAddToBackStack) {mIndex = mManager.allocBackStackIndex(this);} else {mIndex = -1;}mManager.enqueueAction(this, allowStateLoss);return mIndex; }//第七步:再追蹤到enqueueAction(this,allowStateLoss) public void enqueueAction(OpGenerator action, boolean allowStateLoss) {if (!allowStateLoss) {checkStateLoss();}synchronized (this) {if (mDestroyed || mHost == null) {throw new IllegalStateException("Activity has been destroyed");}if (mPendingActions == null) {mPendingActions = new ArrayList<>();}mPendingActions.add(action);scheduleCommit();} }//第八步:checkStateLoss()方法,這里可以看到拋出的錯誤日志呢 private void checkStateLoss() {if (mStateSaved) {throw new IllegalStateException("Can not perform this action after onSaveInstanceState");}if (mNoTransactionsBecause != null) {throw new IllegalStateException("Can not perform this action inside of " + mNoTransactionsBecause);} }

關于其他內容介紹

01.關于博客匯總鏈接

  • 1.技術博客匯總
  • 2.開源項目匯總
  • 3.生活博客匯總
  • 4.喜馬拉雅音頻匯總
  • 5.其他匯總

02.關于我的博客

  • 我的個人站點:www.yczbj.org,www.ycbjie.cn
  • github:https://github.com/yangchong211
  • 知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
  • 簡書:http://www.jianshu.com/u/b7b2c6ed9284
  • csdn:http://my.csdn.net/m0_37700275
  • 喜馬拉雅聽書:http://www.ximalaya.com/zhubo/71989305/
  • 開源中國:https://my.oschina.net/zbj1618/blog
  • 泡在網上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
  • 郵箱:yangchong211@163.com
  • 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
  • segmentfault頭條:https://segmentfault.com/u/xiangjianyu/articles

轉載于:https://my.oschina.net/zbj1618/blog/2244812

總結

以上是生活随笔為你收集整理的DialogFragment源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产丝袜在线视频 | 欧美激情视频在线播放 | 九九热九九爱 | 中文字幕一区二区三区av | 91精品国产99久久久久久红楼 | 国产中文字幕三区 | 熟妇高潮一区二区三区 | av最新版天堂资源在线 | 日本不卡一区二区三区在线观看 | 末发成年娇小性xxxxx | 最全aⅴ番号库 | 色天天天 | 欧美a一级 | 国产九九九九九 | 麻豆网站免费看 | 乱短篇艳辣500篇h文最新章节 | 国产一区欧美二区 | 国产成人精品亚洲线观看 | 九一国产在线观看 | 就是喜欢被他干 | 国产麻豆一精品一男同 | 日韩av成人 | 自拍偷拍21p | 幸福,触手可及 | 国产乱国产乱300精品 | 免费看a视频 | 性生活一级大片 | 国产女人毛片 | 都市激情麻豆 | 国产精品sm调教免费专区 | 久久亚洲综合色图 | 精品久久久久久久久久久久久 | mm131美女视频 | 久久黄色片视频 | 制服丝袜第二页 | 无码人妻一区二区三区线 | 亚洲麻豆一区 | 午夜在线观看av | 久久亚洲AV成人无码国产人妖 | 含羞草一区二区三区 | 成人黄网免费观看视频 | 国产无套精品一区二区 | 国产最新自拍视频 | 秋霞网一区 | 狠狠爱婷婷 | 天天色综合影视 | 欧美视频一二三 | 久久精品视频在线 | 蜜桃臀一区二区三区 | 欧美一区二区三区免费视频 | 一区二区av在线 | 免费a v视频 | 五月丁香久久婷婷 | 一本一道av | 日产精品一区 | 精品人妻av一区二区三区 | 精品国产乱码久久久久久郑州公司 | 前任攻略在线观看免费完整版 | 少妇av一区二区三区无码 | 超薄肉色丝袜一区二区 | 国产精品免费大片 | 免费在线观看的黄色网址 | 国产精品www色诱视频 | 成人性生交大片免费看vrv66 | 欧美国产精品一区二区 | 国产精品资源站 | 欧美视频一二三 | 久久国产精品无码一区二区 | 国产美女主播在线 | 成人交性视频免费看 | 日韩精品播放 | 亚洲精品91 | 成人在线观看免费高清 | 最新中文字幕视频 | 午夜剧场免费观看 | 久久网站免费看 | 日本九九视频 | 秋霞黄色片 | 久久精品福利视频 | 夜夜操天天操 | 久久精品99久久久久久 | 玉足调教丨vk24分钟 | jlzzjlzz亚洲女人18 | 亚洲精品视频一二三区 | 毛片毛片毛片毛片毛片毛片毛片毛片 | 高跟鞋调教—视频|vk | 国产人妻久久精品一区二区三区 | 四虎色 | av中文字幕在线看 | 日韩在线一区二区三区四区 | 成人h网站 | 亚洲免费精品 | 涩涩在线看| 日本五十路在线 | 国产精品女主播 | √资源天堂中文在线视频 | av男人的天堂在线 | 欧美成人国产 | 国产精品呻吟久久 |