在Activity中我们要保持横竖屏切换时用户的数据一般是用onSaveinstancestate的方式,dialog也是可以的,但是有更好的方法,Activity专门对dialog提供了自己的管理机制。

我们都知道Activity负责生成、保存、恢复对话框,下面我们就来了解一下Activity的对话框管理机制。

在Activity的源码中我们可以看到private static class ManagedDialog {

Dialog mDialog;

Bundle mArgs;

}

private SparseArray mManagedDialogs;

私有类ManagedDialog通过封装一个Dialog和一个Bundle保存对话框的引用及相关参数,另外使用一个SparseArray数组,来保存了Activity生成的每一个对话框的信息。

SparseArray是一个升序排列的有序数组,采用Key+Value的方式形成类似于字典的数据结构,通过Key即可操作Value,其中Key是一个Int类型,Value是一个Object类型。该数组的内部搜索采用了二分查找算法,因此搜索速度很快。

下面我们来看一下显示对话框时的Activity中的处理机制。public final boolean showDialog(int id, Bundle args) {

if (mManagedDialogs == null) {

mManagedDialogs = new SparseArray();

}

ManagedDialog md = mManagedDialogs.get(id);

if (md == null) {

md = new ManagedDialog();

md.mDialog = createDialog(id, null, args);

if (md.mDialog == null) {

return false;

}

mManagedDialogs.put(id, md);

}

md.mArgs = args;

onPrepareDialog(id, md.mDialog, args);

md.mDialog.show();

return true;

}

从上面的代码不难看出,通过在mManagedDialogs数组中查找,可以判断指定id的对话框是否已经生成,如果没有生成,就新建一个ManagedDialog对象,为其mDialog创建一个对话框createDialog(),并将该ManagedDialog对象存入mManagedDialogs数组中;否则则直接调用onPrepareDialog()函数,能过show()将对话框显示出来。

这里值得一提的是createDialog()函数,其实现代码如下:private Dialog createDialog(Integer dialogId, Bundle state, Bundle args) {

final Dialog dialog = onCreateDialog(dialogId, args);

if (dialog == null) {

return null;

}

dialog.dispatchOnCreate(state);

return dialog;

}

在该函数的第一行就回调了onCreateDialog()函数。

结合前面的代码可以发现,onCreateDialog()与onPrepareDialog()函数为我们提供了对对话框额外的处理能力,在我们自己的派生Activity中可以通过重写这两个函数来做一些特殊处理,但是需要注意的是,onCreateDialog()函数中在一个ID标识的对话框第一次创建的时候才会被回调,如果该对话框已经创建过,即使没有显示,由于存在于mManagedDialogs数组中,所以是不会再次触发onCreateDialog()函数的,但onPrepareDialog()函数是不受此限制的。

同样我们再来看一下隐藏对话框的代码。public final void dismissDialog(int id) {

if (mManagedDialogs == null) {

throw missingDialog(id);

}

final ManagedDialog md = mManagedDialogs.get(id);

if (md == null) {

throw missingDialog(id);

}

md.mDialog.dismiss();

}

这段代码很简单,利用id在mManagedDialogs数组中找到ManagedDialog并调用其mDialog.dismiss()即可。

移除对话框也可以想见,只是从mManagedDialogs数组中remove()掉即可。

public final void removeDialog(int id) {

if (mManagedDialogs == null) {

return;

}

final ManagedDialog md = mManagedDialogs.get(id);

if (md == null) {

return;

}

md.mDialog.dismiss();

mManagedDialogs.remove(id);

}

我们知道Activity的生命周期,当Activity在前后台切换的时候,涉及到保存和恢复状态,这其中当然也要对对话框的状态进行处理,我们先来看一下当Activity切到后台时的状态保存处理。

private void saveManagedDialogs(Bundle outState) {

if (mManagedDialogs == null) {

return;

}

final int numDialogs = mManagedDialogs.size();

if (numDialogs == 0) {

return;

}

Bundle dialogState = new Bundle();

int[] ids = new int[mManagedDialogs.size()];

// save each dialog's bundle, gather the ids

for (int i = 0; i < numDialogs; i++) {

final int key = mManagedDialogs.keyAt(i);

ids[i] = key;

final ManagedDialog md = mManagedDialogs.valueAt(i);

dialogState.putBundle(savedDialogKeyFor(key), md.mDialog.onSaveInstanceState());

if (md.mArgs != null) {

dialogState.putBundle(savedDialogArgsKeyFor(key), md.mArgs);

}

}

dialogState.putIntArray(SAVED_DIALOG_IDS_KEY, ids);

outState.putBundle(SAVED_DIALOGS_TAG, dialogState);

}

整个的对话框信息保存用的是dialogState这个Bundle对象,遍历mManagedDialogs数组,对其中的每一个对话框信息,把对话框自身的onSaveInstanceState()返回的Bundle加入到dialogState中,再把对话框信息中保存的对话框参数存入dialogState中。最后将所有的对话框id形成的int数组再存入dialogState中,对话框的保存即告完成。

同理,恢复对话框是保存的逆过程,源码如下:private void restoreManagedDialogs(Bundle savedInstanceState) {

final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);

if (b == null) {

return;

}

final int[] ids = b.getIntArray(SAVED_DIALOG_IDS_KEY);

final int numDialogs = ids.length;

mManagedDialogs = new SparseArray(numDialogs);

for (int i = 0; i < numDialogs; i++) {

final Integer dialogId = ids[i];

Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId));

if (dialogState != null) {

// Calling onRestoreInstanceState() below will invoke dispatchOnCreate

// so tell createDialog() not to do it, otherwise we get an exception

final ManagedDialog md = new ManagedDialog();

md.mArgs = b.getBundle(savedDialogArgsKeyFor(dialogId));

md.mDialog = createDialog(dialogId, dialogState, md.mArgs);

if (md.mDialog != null) {

mManagedDialogs.put(dialogId, md);

onPrepareDialog(dialogId, md.mDialog, md.mArgs);

md.mDialog.onRestoreInstanceState(dialogState);

}

}

}

}

到此,我们已经能够想到Activity在onDestory中如何销毁对话框了,没错,只要销毁mManagedDialogs数组就行了。protected void onDestroy() {

// dismiss any dialogs we are managing.

if (mManagedDialogs != null) {

final int numDialogs = mManagedDialogs.size();

for (int i = 0; i < numDialogs; i++) {

final ManagedDialog md = mManagedDialogs.valueAt(i);

if (md.mDialog.isShowing()) {

md.mDialog.dismiss();

}

}

mManagedDialogs = null;

}

……

}

以上就是Activity对Dialog管理的全部.

android悬浮框横竖屏切换,Activity如何管理对话框(横竖屏切换保持对话框的最佳办法)...相关推荐

  1. Android悬浮框实践

    1.常见悬浮框显示样式示例及应用场景 现在很多的应用都在使用悬浮框,例如微信视频,点击Home键以后,微信视频窗口一直停留在桌面上,小米手机屏幕上的快捷键(Home,锁屏...)等,那么我们今天将实现 ...

  2. WindowManager解析(二)Android悬浮框无法弹出输入法的原因和无需权限显示悬浮窗

    Android悬浮框无法弹出输入法 最近要研究悬浮窗方面的东西,遇到一个问题,我的悬浮窗里面有一个输入框,但是不弹出输入法,后来找到一个方法: 在WindowManager的实例获取方式不对,之前是这 ...

  3. Android 悬浮框按钮

    示例: 悬浮框的xml代码:(layout_float.xml) <?xml version="1.0" encoding="utf-8"?> &l ...

  4. 用WindowManager实现Android悬浮框以及拖动事件

    下面的App程序代码实现通过主Activity的启动按钮,启动一个Service,然后在Service中创建添加悬浮窗口:(话不多说,直接上代码) 在这里我们先看一下需要创建的类和布局和需要添加的权限 ...

  5. Android零基础入门第76节:Activity数据保存和横竖屏切换

    在前面几期学习了Activity的创建.配置.启动和停止,还学了Activity的生命周期,本期一起来学习Activity有关的更多事儿. 一.数据保存 通过上一期 LogCat 窗口打印的日志可以看 ...

  6. android 录屏不录制自身的悬浮框

    通过MediaProjectionManager的录屏操作,做了个简单的应用,但是每次都把自身的悬浮框录制了进去,脑壳疼.使用系统自带的录屏工具就不会有这个问题.为了一探究竟,捣鼓出了系统的录屏工具a ...

  7. android录屏时不截入自定义悬浮框

    前提:使用MediaProjectionManager录屏方案. 问题:会截入自定义悬浮框 解决方案 1.本质上得修改framework层代码surfaceflinger去除悬浮框,在画布中就去除该悬 ...

  8. android 浮动文字提示,怎么在Android中实现一个自由拖动并显示文字的悬浮框

    怎么在Android中实现一个自由拖动并显示文字的悬浮框 发布时间:2021-01-27 15:34:05 来源:亿速云 阅读:107 作者:Leah 今天就跟大家聊聊有关怎么在Android中实现一 ...

  9. Android中的Window、WindowManager以及悬浮框视频播放的实现

    摘要:近日看公司直播项目,其中有一个功能就是退出某房间之后,直播界面会以悬浮窗的形式出现,并且可以拖动悬浮窗到界面中任意位置,点击悬浮框之后,又可以回到房间中继续观看直播.现在这个功能在主流的直播或者 ...

最新文章

  1. 机器学习入门(05)— 使用 NumPy 实现 3 层简单神经网络
  2. 玩双节棍的算法工程师:鱼佬的数据挖掘之路!
  3. lucene全文搜索之三:生成索引字段,创建索引文档(给索引字段加权)基于lucene5.5.3...
  4. 活动安排(信息学奥赛一本通-T1422)
  5. 前端知识整理 CSS盒模型
  6. php生成超链接完整代码_PHP自动把网站自动添加超链接怎么写
  7. HTTP method POST is not supported by this URL解决方案
  8. 【数理统计】显著性检验
  9. 字号大小对应表(字号换算磅值)
  10. css斜线边框,CSS border斜线效果
  11. 个人搭建网站主要流程以及六个基本步骤
  12. win10虚拟机连接不上内网服务器,win10系统虚拟机无法连接网络的解决方法
  13. 微信PC版Hook发送群艾特消息研究
  14. 【福利】百度云2018最新限速破解软件
  15. 微信开发如何优雅的注入token(2)
  16. Pixelmator Pro Mac(图像编辑软件)
  17. Kanzi软件开发与Android的关系
  18. 日语里面用言连体,连用,终止形分别是什么
  19. libtool已经安装了 但是报错libtool not found, please install first
  20. 如何将solidworks中的机械臂三维装配体导出matlab可以运行或者说可以识别的STEP和XML格式

热门文章

  1. android密码sha256解密,使用password_hash和SHA256加密和解密
  2. 写给Node.js新手的7个小技巧
  3. vue接入万达IAM(统一身份认证登录)记录
  4. 【vim】批量注释与取消注释
  5. golang 自定义封包协议(转的)
  6. 《生物信息学》阅读笔记 (四):非编码RNA
  7. springboot配置i18n国际化
  8. Mac上微信可以收发信息,但是无法上网问题解决方式
  9. QMatrix4x4基本使用
  10. OCaml从入门到放弃