导航

本文为原创文章,欢迎转载,但请注明出处http://www.cnblogs.com/yexiubiao/archive/2012/05/17/2506394.html,未在文章页面明显位置给出原文连接的,将保留追究法律责任的权利。
 
昨天朋友的android项目里出现了一个Bug,刚好我有时间,就帮他看了下。
在他的项目中有个Button,点击后弹出一个自定义的对话框,如果这时候按back键结束对话框,再次点击Button打开此对话框时,就出现了以下异常:
The specified child already has a parent. You must call removeView() on the child's parent first
大概意思为:这个指定的孩子已经有一个父亲了,你必须首先在该孩子的父亲处调用removeView() 方法。
 
出错的代码如下:
 
1 case R.id.set:
2     LocalActivityManager manager = getLocalActivityManager();
3     Intent intent = new Intent(PersonalActivity.this, SettingActivity.class);
4     View settingView = manager.startActivity("SettingActivity", intent).getDecorView();
5     AlertDialog.Builder set_builder = new AlertDialog.Builder(PersonalActivity.this);
6     set_builder.setView(settingView);
7     set_builder.show(); /这一行报错
8     break;

 

    照着异常信息的提示,打算去调用removeView() ,但是找遍了所有地方都没找到removeView() 这个方法,没办法只好从其他地方入手。
    在这个自定义对话框中,他的View(即settingView)是通过LocalActivityManager 将SettingActivity转换过来的,然后再通过调用set_builder.setView(settingView);将该settingView和对话框绑定在了一起,那么很显然父亲就是set_builder,孩子就是settingView。按照异常信息来说,第二次打开对话框的时候,settingView又被重新指定了一个新的父亲,即第二次调用set_builder.setView(settingView);的时候,参数settingView跟上一次是同一个对象。难道是说第二次执行以上代码时,settingView没有被重新生成?
 
    于是看了一下manager.startActivity)方法的注释:
Start a new activity running in the group. Every activity you start must have a unique string ID associated with it -- this is used to keep track of the activity, so that if you later call startActivity() again on it the same activity object will be retained.
When there had previously been an activity started under this id, it may either be destroyed and a new one started, or the current one re-used, based on these conditions, in order:
 
    该方法startActivity()会传入一个唯一的id,当下次再调用此方法时,如果id是一样的,那么还是会返回相同的activity对象。所以第二次生成的settingView 复用了原来的view,导致同一个settingView 被指定多个父亲。
  
解决方法1:
manager.removeAllActivities();     //加上这句代码即可
View settingView = manager.startActivity("SettingActivity", intent).getDecorView();
 
 
解决方法2:(设置Intent对象的Flag----FLAG_ACTIVITY_CLEAR_TOP)
Intent intent = new Intent(PersonalActivity.this, SettingActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  //加上此行代码即可
 
关于“FLAG_ACTIVITY_CLEAR_TOP”可参考http://hi.baidu.com/fenghuang1207/item/63e9b2df0683624cddf9be8a