Activity对Dialog的管理
2016-07-26 10:41
295 查看
优点
一般我们使用dialog时,都会在使用的时候创建一个新的dialog对象,然后显示出来,这样虽然很简单,但是当场景变得复杂时,就会出现问题:比如当我们需要多次弹出一样的一个或几个弹窗,如果我们每次都创建一个新的对象,就会创造出很多对象,导致内存开销增大,这显然是我们不愿意看到的。
又或者当我们dialog正在显示时,activity意外销毁,比如用户切换横屏模式,导致activity销毁重建,这时候如果你只是简单的创建并显示了dialog,你的dialog就会消失了。
但是当你把dialog交给activity去管理,这些就都不再是问题。activity可以让你的dialog轻松复用,并且可以保存并恢复其状态。
实现
下面我们就来看一下如何实现:既然是把dialog交给activity管理,就要让activity能够识别每个dialog。识别的方式就是给每个dialog加个编号,这个编号是int类型的。
创建:要创建一个dialog,需要在onCreateDialog()中实现创建dialog的语句。当然,不能忘了id。这里通常会采用switch语句,每一个id创建一个不同的dialog,像这样:
protected Dialog onCreateDialog(int id) { Dialog dialog; switch(id) { case 0: // do the work to define the 0 Dialog break; case 1: // do the work to define the 1 Dialog break; default: dialog = null; } return dialog; }
调用:调用的时候只需要使用showDialog(int id)方法,这个传入的id自然就是前面定义好的id。
隐藏:想要dismiss的时候,可以用dialog自身的dismiss()方法,也可以用activity的dismissDialog(int id)方法。当dialog被dismiss之后,并没有被销毁,而是被activity保存了下来,下次调用的时候即可被复用
删除:如果不想被activity保存,则可以用removeDialog(int id)方法,删除某个dialog。
原理
以上就是使用的方法,非常简单,但是却好处多多,接下来就要看一下activity究竟背着我们干了些什么,让dialog的管理如此方便。首先从调用的方法showDialog(id)说起:
public final void showDialog(int id) { showDialog(id, null); } public final boolean showDialog(int id, Bundle args) { if (mManagedDialogs == null) { mManagedDialogs = new SparseArray<ManagedDialog>(); } 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去找,无疑dialog就是在这里保存的,这是一个SparseArray,所以我们的id需要是int型的。但是仔细一看就会发现mManagedDialogs里保存的并不是dialog,而是ManagedDialog,这里面不光有dialog,还有一个bundle,用来保存dialog的一些状态参数。
private static class ManagedDialog { Dialog mDialog; Bundle mArgs; }
如果mManagedDialogs里没有,就去创建新的,这里我们自己实现的onCreateDialog()就派上用场了:
private Dialog createDialog(Integer dialogId, Bundle state, Bundle args) { final Dialog dialog = onCreateDialog(dialogId, args); if (dialog == null) { return null; } //执行dialog的onCreate方法 dialog.dispatchOnCreate(state); return dialog; }
到这里,就获取到了dialog的实例,就可以在show里面展示了。同时activity还把它放到了mManagedDialogs中进行保存,这样就可以在下次调用同类型dialog的时候进行复用了。当然,保存对象的作用不只复用这么简单:
final void performSaveInstanceState(Bundle outState) { onSaveInstanceState(outState); saveManagedDialogs(outState); mActivityTransitionState.saveState(outState); if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState); }
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); }
可以看到这是在activity保存状态的时候,会把mManagedDialogs中的所有dialog的状态都保存一遍,然后在恢复状态时就可以恢复到之前的状态:
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<ManagedDialog>(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); } } } }
这样就解决了上面所说的类似于切换横屏后正在显示的dialog消失的问题。
相关文章推荐
- MySQL 优化
- screen 命令示例:管理多个终端会话
- Google排名优化的几个影响因素
- IE7降低内存和降低CPU的几个技巧
- DB2优化(简易版)
- Mysql limit 优化,百万至千万级快速分页 复合索引的引用并应用于轻量级框架
- DWZ刷新dialog解决方法
- C#中尾递归的使用、优化及编译器优化
- 对优化Ruby on Rails性能的一些办法的探究
- 优化Ruby脚本效率实例分享
- 如何高效的使用内存
- DOS下内存的配置
- XP/win2003下发现1G的内存比512M还慢的解决方法
- Asp编码优化技巧
- 如何监测和优化OLAP数据库
- mysql -参数thread_cache_size优化方法 小结
- MySQL数据库优化技术之配置技巧总结
- Oracle数据库中SQL语句的优化技巧
- 深入学习SQL Server聚合函数算法优化技巧
- PowerShell实现动态获取当前脚本运行时消耗的内存