1. 程式人生 > >Android程式設計之DialogFragment原始碼詳解(一)

Android程式設計之DialogFragment原始碼詳解(一)

DialogFragment是Fragment家族成員之一,如果你把它簡單的理解成Dialog,那就錯了。它的確可以做作dialog顯示,還可以顯示出自己定義的Dialog或者AlertDialog,但它同時也是一個Fragment。

按照官方的話來理解就是,你既可以把它當成一個dialog顯示出來,也可以讓它作為一個Fragment巢狀在Activity中,這樣更方便開發。

為什麼這麼說呢?試想一下,當產品需求最開始把它作為一個介面顯示的時候,你可能已經把它作為Fragment已經寫好了,但中途產品又把它設計成一個dialog,那你該怎麼辦?重新去一個dialog或者activity嗎?以前的傳參怎麼辦?過兩天,產品又將它改回去,你還要再重寫一遍嗎?等等一系列的問題就來了。

所以,這個時候,你只需要把當前的Fragment繼承類改為DialogFragment,再新增幾行程式碼就可以了。其他的,基本都不用動。即使過兩天再改回來,或者別的介面也需要它的時候,你就可以直接把它當做Fragment,繼續使用,程式碼都不用改。

這一點,不得不讚一下Fragment這個的出現,大大方便了開發,再也不怕產品設計調整介面佈局了!

這裡多囉嗦一句,如果產品已經定義好了作為dialog,或者之前就是dialog的,就不要將它們改成DialogFragment的了,還是那句話:只做有意義的程式碼改動!

DialogFragment的使用用例,官方文件已經寫得很清楚了,Demo例子也有,在androidSDK的sample資料夾中,有需要的請自行查閱。

今天之所以翻出原始碼來,主要還是希望通過對程式碼的瞭解,更好使用DialogFragment。而且有些細節部分,不看原始碼的話,可能就真在方法傳值時傳錯了。比如:style的設定!

在原始碼最開始部分,就定義了style的常量:

    public static final int STYLE_NORMAL = 0;
    public static final int STYLE_NO_TITLE = 1;
    public static final int STYLE_NO_FRAME = 2;
    public static final int STYLE_NO_INPUT = 3;

STYLE_NORMAL:會顯示一個普通的dialog

STYLE_NO_TITLE:不帶標題的dialog

STYLE_NO_FRAME:無框的dialog

STYLE_NO_INPUT:無法輸入內容的dialog,即不接收輸入的焦點,而且觸控無效。

說起來,android很多引數的設定,都有用到“|”的方法,表示支援兩種或兩種以上。最常見的,就是“Top|Left”,所以,在這裡有很多人會想用吧:STYLE_NO_TITLE|STYLE_NO_INPUT。那你可就錯了,這麼用的結果就是把style設定成了:STYLE_NO_INPUT ( 因為:1 | 3 = 3 )

接下來,再看一下它的內部變數:

    int mStyle = STYLE_NORMAL;
    int mTheme = 0;
    boolean mCancelable = true;
    boolean mShowsDialog = true;
    int mBackStackId = -1;

    Dialog mDialog;
    boolean mViewDestroyed;
    boolean mDismissed;
    boolean mShownByMe;

mStyle:預設的樣式為STYLE_NORMAL;

mTheme:主題,預設沒有設定,而是在setStyle(int style, int theme) 方法中,對其初始化設定,下面會講到;

mCancelable:是否可以取消,預設是ture,實際上就是設定給Dialog的mDialog.setCancelable(mCancelable);

mShowsDialog:這個引數我放到下面去講,預設也為true

mBackStackId:後退棧的ID,也就是說,當DialogFragment不顯示時,會清空棧裡的資料。(關於後退棧的問題,請留心我後面關於FragmentManager詳解的文章);

mDialog:DialogFragment之所以會以視窗方式顯示,實際上就是其內部有一個Dialog,也就是它,上面的樣式、主題、可取消都是設定給它的;

後面三個boolean的變數,就是標誌位:

mViewDestroyed:標誌位,在Dialog不顯示時,處理Fragment的移除操作;

mDismissed:標誌位,Dialog是否不顯示了;

mShownByMe:標誌位,在Dialog是否顯示,和mDismissed基本是一對;

DialogFragment的構造方法是空的,什麼也沒有:

    public DialogFragment() {
    }

然後就是setStyle方法:
    public void setStyle(int style, int theme) {
        mStyle = style;
        if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {
            mTheme = android.R.style.Theme_Panel;
        }
        if (theme != 0) {
            mTheme = theme;
        }
    }

開頭已經講過了,style使用注意事項。通過這個方法,可以看到,在不設定theme,即為0的情況下,theme會被設定為android.R.style.Theme_Panel。

這還可以根據自己定義的Dialog樣式設定進來。

下面就是show方法,共有兩個:

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

雖然是兩種寫法,但實際上還是將自己新增到FragmentManager中而已。

有顯示,就是得有不顯示的程式碼:

    public void dismiss() {
        dismissInternal(false);
    }

    public void dismissAllowingStateLoss() {
        dismissInternal(true);
    }

兩個方法都是呼叫了void dismissInternal(boolean allowStateLoss),只是傳參不一樣而已,看一下dismissInternal這個方法:

    void dismissInternal(boolean allowStateLoss) {
        if (mDismissed) {
            return;
        }
        mDismissed = true;
        mShownByMe = false;
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
        mViewDestroyed = true;
        if (mBackStackId >= 0) {
            getFragmentManager().popBackStack(mBackStackId,
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
            mBackStackId = -1;
        } else {
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.remove(this);
            if (allowStateLoss) {
                ft.commitAllowingStateLoss();
            } else {
                ft.commit();
            }
        }
    }

它做了幾件事:

1、呼叫dialog的dismiss方法

2、如果自己在後退棧中,就將自己從後退棧中移除掉(彈出)

3、如果自己不在後退棧中,就將自己從FragmentManager中移除掉。

關於commitAllowingStateLoss與commit的區別,網上有很多講解,這裡也不細說了。以後的FragmentManager中,會對它有更詳細的解釋。

今天就先寫到這裡,後面部分下次釋出。

相關推薦

Android程式設計DialogFragment原始碼

DialogFragment是Fragment家族成員之一,如果你把它簡單的理解成Dialog,那就錯了。它的確可以做作dialog顯示,還可以顯示出自己定義的Dialog或者AlertDialog,但它同時也是一個Fragment。 按照官方的話來理解就是,你既可以把它當

06.RTSP原始碼

6.7.rtsp傳輸原始碼分析1 6.8.rtsp傳輸原始碼分析2 6.9.rtsp傳輸原始碼分析3 6.10.rtsp傳輸原始碼分析4 6.11.rtsp傳輸實戰分析 6.12.直接傳送與環狀buffer傳送 6.13.rtsp分包傳送h264的原始碼分析 rtp_timestamp:http

三維深度學習pointnet系列

三維深度學習之pointnet系列詳解(一) 置頂 2018年05月09日 23:25:06 痛並快樂著呦西 閱讀數:4429 標籤: pointnet 三維深度學習 更多 個人分類: 3D Deep Learning

spring的BeanFactory和ApplicationContext原始碼

轉自http://www.sandzhang.com/blog/2011/04/10/Spring-BeanFactory-ApplicationContext-Detail-1/ 版本:spring-framework-3.0.5.RELEASE Spring的最核心的部分就是BeanFactory了,

EventBus原始碼:基本使用

寫在前面 對於Android程式設計師來說,相信大家都聽過EventBus的大名。EventBus是一個Android平臺上基於事件釋出和訂閱的輕量級框架,可以對釋出者和訂閱者解耦,並簡化Android的事件傳遞。正如官方介紹其優勢: 簡化了元件之間的通訊

Android 動畫】View Animation

安卓平臺目前提供了兩大類動畫,在Android 3.0之前,一大類是View Animation,包括Tween animation(補間動畫),Frame animation(幀動畫),在android3.0中又引入了一個新的動畫系統:property ani

Android 5.X 新特性——主題、Palette、陰影、著色和裁剪

Android 5.X 系列開始使用新的設計風格Material Design來統一整個Android系統的介面設計風格。 Material Design 主題 Material Design 現在有三種預設的主題可以設定,程式碼如下: @andr

YOLO原始碼-訓練

本系列文章會持續更新,主要會分以下幾個部分: 1、darknet下的yolo原始碼解讀 2、將yolo移植到mxnet下 3、模型壓縮與加速 白天需要工作,只有晚上時間寫,所以可能更新速度有點慢,還有就是該系列博文不一定會嚴格按照以上三點的順序來

jdbc原始碼:示例+Driver註冊流程

0x00 前言 自己一直說要某個開源專案的原始碼,但是一直沒有真正地好好開始,一是以為看原始碼其實不容易看懂,而是因為選擇猶豫,最後也敲定看哪個。 這次正式開始看jdbc的原始碼有兩個三個:一是因為《java程式設計思想》這本書快看完了,折騰一個多月的時間,

跟我學KafkaController控制器

我們的kafka原始碼分享已經進行過很多期了,主要的內容也都分享的差不多了,那麼那麼在今後的分享中,主要集中在kafka效能優化和使用 Kafka叢集中的其中一個Broker會被選舉為Controller,主要負責Partition管理和副本狀態管理,也會執行類似於重分配Partition之類的管理任務

MySQLSQL優化

目錄 慢查詢日誌 1. 慢查詢日誌開啟 2. 慢查詢日誌設定與檢視 3.日誌分析工具mysqldumpslow   序言: 在我面試很多人的過程中,很多人談到S

gRPC 原始碼配置化的結構體

grpc 原始碼結構詳解 DialOptions DialOptions 是最重要的一環,負責配置每一次 rpc 請求的時

Java程式設計師從笨鳥到菜鳥一百sql注入攻擊sql注入原理

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android開發最新Recyclerview控制元件的使用

    本篇博文主要給大家分享關於RecyclerView控制元件的使用及通過繼承RecyclerView來實現滑動時載入圖片的優化方案,也同樣能解決防止圖片亂序的問題,之前有在網上有看到大神對Android中ListView非同步載入圖片亂序問題進行過分析,並深入剖析原理

Windows滲透利器Pentest BOX使用

內存 標簽 配置 ram 添加 概覽 測試環境 功能 ruby 內容概覽: 知識科普 優缺點總結 功能參數詳解翻譯: 控制臺參

豹哥嵌入式講堂:ARM Cortex-M開發文件7- 反匯編文件(.s/.lst/.dump)

work cfi text1 翻譯 memory 進制數 補充 就是 datatable   大家好,我是豹哥,獵豹的豹,犀利哥的哥。今天豹哥給大家講的是嵌入式開發裏的反匯編文件(.s, .lst, .dump)。   豹哥在第四、五、六節課分別介紹了編譯器/鏈接器生成的

豹哥嵌入式講堂:ARM Cortex-M開發文件8- 鏡像文件(.bin/.hex/.s19)

linker 未定義 公司 編輯器 ascii 輔助 oca ddr ext   大家好,我是豹哥,獵豹的豹,犀利哥的哥。今天豹哥給大家講的是嵌入式開發裏的image文件(.bin, .hex, .s19)。   今天這節課是豹哥《ARM Cortex-M開發之文件詳解》

大數據入門第十七天——storm上遊數據源 kafka入門

不同 這也 接受 blog 存儲 發送 records ant post 一、概述   1.kafka是什麽     根據標題可以有個概念:kafka是storm的上遊數據源之一,也是一對經典的組合,就像郭德綱和於謙     根據官網:http://kafka.apa

Android EventBus3.x 使用

led AC target 分解 感覺 div activit .org android事 ?(^∇^*) 五一假期在家無事,新項目中用的是RxJava2+EventBus感覺還不錯,趁這閑暇總結下EventBus 一、概要簡述   EventBus

定時調度系列Quartz.Net

mys quic win 代碼 但是 提醒 tps 官網 etc 出處:https://www.cnblogs.com/yaopengfei/p/9216229.html 一. 背景   我們在日常開發中,可能你會遇到這樣的需求:"每個月的3號給用戶發信息,提醒用戶XX