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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android弹窗组件工作机制之Dialog、DialogFragment(二)

發布時間:2025/3/20 Android 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android弹窗组件工作机制之Dialog、DialogFragment(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

二、Dialog的消失

1、dismiss

private final Runnable mDismissAction = this::dismissDialog;public void dismiss() {if (Looper.myLooper() == mHandler.getLooper()) {dismissDialog();} else {mHandler.post(mDismissAction);} } 復制代碼

保證UI操作都在主線程執行,而且引用了Java8新特性寫法this::dismissDialog,最后都會調用dismissDialog()

2、dismissDialog

void dismissDialog() {if (mDecor == null || !mShowing) {return;}if (mWindow.isDestroyed()) {Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");return;}try {//這里移除DecorViewmWindowManager.removeViewImmediate(mDecor);} finally {if (mActionMode != null) {mActionMode.finish();}mDecor = null;mWindow.closeAllPanels();onStop();mShowing = false;sendDismissMessage();} } 復制代碼

從show中知道,我們將DecorView加入到WindowManager中去,所以這里移除的是DecorView

3、WindowManagerImpl.removeViewImmediate

public void removeViewImmediate(View view) {//委托給mGlobal來進行實現mGlobal.removeView(view, true); } 復制代碼

同樣的交給WindowManagerGlobal去處理

4、WindowManagerGlobal.removeView

public void removeView(View view, boolean immediate) {if (view == null) {throw new IllegalArgumentException("view must not be null");}synchronized (mLock) {//待remove view的索引int index = findViewLocked(view, true);//mRoots保存著每一個viewRootImpl對象View curView = mRoots.get(index).getView();//真正對view進行了remove操作removeViewLocked(index, immediate);if (curView == view) {return;}throw new IllegalStateException("Calling with view " + view+ " but the ViewAncestor is attached to " + curView);} } 復制代碼

找到對應要移除的View后進行View邏輯處理工作

5、WindowManagerGlobal.removeViewLocked

private void removeViewLocked(int index, boolean immediate) {ViewRootImpl root = mRoots.get(index);View view = root.getView();if (view != null) {InputMethodManager imm = InputMethodManager.getInstance();if (imm != null) {imm.windowDismissed(mViews.get(index).getWindowToken());}}//重點在ViewRootImpl中的die方法中boolean deferred = root.die(immediate);if (view != null) {view.assignParent(null);if (deferred) {mDyingViews.add(view);}} } 復制代碼

找到對應的ViewRootImpl,進行移除并釋放工作

6、ViewRootImpl.die

boolean die(boolean immediate) {if (immediate && !mIsInTraversal) {//繼續跟蹤doDie();return false;}if (!mIsDrawing) {destroyHardwareRenderer();} else {Log.e(TAG, "Attempting to destroy the window while drawing!\n" +" window=" + this + ", title=" + mWindowAttributes.getTitle());}mHandler.sendEmptyMessage(MSG_DIE);return true; } 復制代碼

7、ViewRootImpl.doDie

void doDie() {checkThread();if (LOCAL_LOGV) Log.v(TAG, "DIE in " + this + " of " + mSurface);synchronized (this) {if (mRemoved) {return;}mRemoved = true;if (mAdded) {//這里是真正移除Dialog的ViewdispatchDetachedFromWindow();}if (mAdded && !mFirst) {//硬件渲染destroydestroyHardwareRenderer();if (mView != null) {int viewVisibility = mView.getVisibility();boolean viewVisibilityChanged = mViewVisibility != viewVisibility;if (mWindowAttributesChanged || viewVisibilityChanged) {// If layout params have been changed, first give them// to the window manager to make sure it has the correct// animation info.try {if ((relayoutWindow(mWindowAttributes, viewVisibility, false)& WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {mWindowSession.finishDrawing(mWindow);}} catch (RemoteException e) {}}//Surface的釋放mSurface.release();}}mAdded = false;}//移除之前存儲的變量WindowManagerGlobal.getInstance().doRemoveView(this); } 復制代碼

保證線程安全后,做移除和釋放工作

8、WindowManagerGlobal.doRemoveView

一般程序最后的工作都是釋放工作,移除之前存儲的變量

void doRemoveView(ViewRootImpl root) {synchronized (mLock) {final int index = mRoots.indexOf(root);if (index >= 0) {//釋放工作mRoots.remove(index);mParams.remove(index);final View view = mViews.remove(index);mDyingViews.remove(view);}}if (HardwareRenderer.sTrimForeground && HardwareRenderer.isAvailable()) {doTrimForeground();} } 復制代碼

9、ViewRootImpl.dispatchDetachedFromWindow

void dispatchDetachedFromWindow() {if (mView != null && mView.mAttachInfo != null) {mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false);//此方法會回調onDetachedFromWindow方法,會做資源的回收mView.dispatchDetachedFromWindow();}mAccessibilityInteractionConnectionManager.ensureNoConnection();mAccessibilityManager.removeAccessibilityStateChangeListener(mAccessibilityInteractionConnectionManager);mAccessibilityManager.removeHighTextContrastStateChangeListener(mHighContrastTextManager);removeSendWindowContentChangedCallback();destroyHardwareRenderer();setAccessibilityFocus(null, null);mView.assignParent(null);mView = null;mAttachInfo.mRootView = null;mSurface.release();if (mInputQueueCallback != null && mInputQueue != null) {mInputQueueCallback.onInputQueueDestroyed(mInputQueue);mInputQueue.dispose();mInputQueueCallback = null;mInputQueue = null;}if (mInputEventReceiver != null) {mInputEventReceiver.dispose();mInputEventReceiver = null;}try {//這里調用了mWindowSession的remove方法,在WindowManagerService層通過IPC機制完成真正的window刪除mWindowSession.remove(mWindow);} catch (RemoteException e) {}// Dispose the input channel after removing the window so the Window Manager// doesn't interpret the input channel being closed as an abnormal termination.if (mInputChannel != null) {mInputChannel.dispose();mInputChannel = null;}mDisplayManager.unregisterDisplayListener(mDisplayListener);unscheduleTraversals(); } 復制代碼

到最后會和添加View的時候完成閉環,還是通過WindowSession的IPC機制去調用的,最后在WindowManagerService層通過IPC機制去實現的 ##總結 1.Dialog的dismiss和show形成閉環,調用的過程是相似的,只不過多了資源的釋放環節

DialogFragment

DialogFragment本身繼承自Fragment

public class DialogFragment extends Fragmentimplements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener 復制代碼

在平時中,我們需要自定義WeDialogFragment,而且在正式開發中踩過的坑:

  • 需要對參數進行onSaveInstanceState操作,這類操作主要是防止異步吊起DialogFragment報nullPoint的Bug
  • 需要重寫show(),對show做一層彈出時候的保護,這類操作主要是防止異步吊起DialogFragment報onSaveInstanceState的Bug
public class WeDialogFragment extends DialogFragment {@Overridepublic void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);Bundle bundle = new Bundle();bundle.putString(BUNDLE_TITLE, title);}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setStyle(DialogFragment.STYLE_NO_TITLE, R.style.WeDialog);if (savedInstanceState != null) {title = savedInstanceState.getString(BUNDLE_TITLE);}}@Overridepublic Dialog onCreateDialog(Bundle savedInstanceState) {Dialog dialog = super.onCreateDialog(savedInstanceState);dialog.setCanceledOnTouchOutside(true);dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);dialog.getWindow().setWindowAnimations(R.style.DialogAnimation);dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);return dialog;}@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {return inflater.inflate(R.layout.view_fragment_dialog, container, false);}@Overridepublic void show(FragmentManager manager, String tag) {if (!manager.isStateSaved()) {super.show(manager, tag);}} } 復制代碼

然后在Activity中彈出DialogFragment

WeDialogFragment weDialogFragment = new WeDialogFragment(); weDialogFragment.show(activity.getSupportFragmentManager(),"weDialogFragment"); 復制代碼

一、DialogFragment的顯示

1、DialogFragment.show

public void show(FragmentManager manager, String tag) {mDismissed = false;mShownByMe = true;FragmentTransaction ft = manager.beginTransaction();ft.add(this, tag);ft.commit(); } 復制代碼

show的方法其實就是對Fragment的處理,將Fragment添加到Fragment棧中

二、DialogFragment的隱藏

####1、DialogFragment.dismiss

public void dismiss() {dismissInternal(false); }public void dismissAllowingStateLoss() {dismissInternal(true); }void dismissInternal(boolean allowStateLoss) {if (mDismissed) {return;}mDismissed = true;mShownByMe = false;if (mDialog != null) {mDialog.dismiss();}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();}} } 復制代碼

dismiss的方法也是對Fragment的處理,將Fragment移除到Fragment棧中

三、Dialog的創建

1、DialogFragment.onCreateDialog

@NonNull public Dialog onCreateDialog(Bundle savedInstanceState) {return new Dialog(getActivity(), getTheme()); } 復制代碼

和創建普通的Dialog沒什么區別,我們重寫該方法,可以自定義彈出AlertDialog等其他自定義Dialog

四、Dialog的視圖

1、DialogFragment.onActivityCreated

@Override public void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);if (!mShowsDialog) {return;}//拿到的就是onCreateView返回值的view對象,具體可以在Fragment源碼找到View view = getView();if (view != null) {if (view.getParent() != null) {throw new IllegalStateException("DialogFragment can not be attached to a container view");}//真正設置viewmDialog.setContentView(view);}final Activity activity = getActivity();if (activity != null) {mDialog.setOwnerActivity(activity);}mDialog.setCancelable(mCancelable);mDialog.setOnCancelListener(this);mDialog.setOnDismissListener(this);if (savedInstanceState != null) {Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG);if (dialogState != null) {mDialog.onRestoreInstanceState(dialogState);}} } 復制代碼

在Activity創建的時候,Fragment的周期會回調onActivityCreated,從而對Dialog設置視圖

五、Dialog的顯示隱藏

Dialog顯示隱藏就簡單了,隨著Fragment的生命周期顯示和隱藏,直接看代碼就行了

@Override public void onStart() {super.onStart();if (mDialog != null) {mViewDestroyed = false;mDialog.show();} }@Override public void onStop() {super.onStop();if (mDialog != null) {mDialog.hide();} } 復制代碼

總結

DialogFragment = Fragment + Dialog,DialogFragment本身繼承Fragment,Fragment只是用來依附在Activity上,可以監聽Activity的生命周期,從而去通知Dialog做對應的操作,而Dialog才是我們正在顯示在屏幕上的彈窗,而非一個Fragment。這里的Dialog真正顯示出來的View是從**onCreateView()中獲取view后,在源碼中調用dialog的setContentView()**顯示出來的

文末送福利啦!!

同時我經過多年的收藏目前也算收集到了一套完整的學習資料以及高清詳細的Android架構進階學習導圖及筆記免費分享給大家,希望對想成為架構師的朋友有一定的參考和幫助。 **下面是部分資料截圖,誠意滿滿:特別適合有開發經驗的Android程序員們學習。

資料免費領取方式:現在關注我并且加入群聊 群號:1018342383 或者是點擊鏈接加入群聊【Android開發交流】:jq.qq.com/?_wv=1027&a…

總結

以上是生活随笔為你收集整理的Android弹窗组件工作机制之Dialog、DialogFragment(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日本三级一区 | 就是色 | 久草精品在线观看 | 免费网站在线高清观看 | 男男成人高潮片免费网站 | 久久a毛片 | 污污内射在线观看一区二区少妇 | 免费毛片视频 | 欧美浓毛大泬视频 | 成年人黄色 | 亚洲一二三 | 日日干天天操 | 无码人妻精品一区二区三区蜜桃91 | 97黄色网| 中文字幕第 | 伊人成人久久 | 国产亚洲精品久久久久久无几年桃 | 双性懵懂美人被强制调教 | 又污又黄的视频 | 男人私人影院 | 五月激情小说 | 美女一级黄色片 | 免费成人结看片 | 精品中文字幕一区二区 | 国内激情自拍 | 无码人妻精品一区二区蜜桃色欲 | 亚洲国产区| 中文在线观看免费 | 欧美性色黄大片手机版 | 天天宗合 | 无码人妻一区二区三区免费n鬼沢 | 色吧五月天 | 97综合| 色8久久 | 精品国产第一页 | 国产精品婷婷午夜在线观看 | 国内国产精品天干天干 | 91影院在线观看 | 亚洲女人初尝黑人巨大 | 在线日韩欧美 | 亚洲精品高潮 | jizz国产免费| 国产精品久久777777换脸 | 欧美大白屁股 | 伊人色av| 熟女少妇精品一区二区 | 天堂网av在线 | 无码毛片aaa在线 | 美女av免费在线观看 | 97干在线| 欧美性大战久久久久久 | 四虎精品久久 | 日本少妇吞精囗交视频 | 欧美成人一区二免费视频软件 | 日韩色图在线观看 | 不卡中文| 中文字幕无产乱码 | 中文字幕久久综合 | 又大又粗弄得我出好多水 | 在线观看国产亚洲 | 国产精品久久久久久久毛片 | 日本少妇色视频 | 欧美一级性生活视频 | 福利在线一区二区三区 | 国产一区二区三区视频网站 | 中文字幕在线看高清电影 | 色天天 | 迈开腿让我尝尝你的小草莓 | 在线视频一区二区三区 | www五月 | 国产精品一级二级三级 | 欧美激情精品久久久久久变态 | 成人av小说| 丁香婷婷久久 | 国产精品福利一区二区三区 | 91搞搞| 天天伊人网 | 欧美性xxxxx| 国产精品久久久久久久久久 | 又大又粗弄得我出好多水 | 四虎影视成人永久免费观看亚洲欧美 | 中文字幕在线看片 | 九色视频网站 | 日本久久伊人 | 天天爽天天 | 性欧美视频在线观看 | 天天操天天干天天操 | 色婷婷国产精品综合在线观看 | 亚洲激情视频网站 | 98堂 最新网名| 国产在线观看第一页 | 精品一区二区三区不卡 | 国产免费观看视频 | 国产精品亚洲lv粉色 | 日本美女动态图 | 91av看片| 国产福利在线视频观看 | 欧美一区二区三区在线观看视频 | 亚洲av电影天堂男人的天堂 |