您的位置:首页 > 移动开发 > Android开发

从Java回调机制分析Android动态加载布局过程中出现的IllgalStateException

2016-01-14 20:23 597 查看
先说说自己对回调的理解吧。
1.什么是回调?指出某个特定事件发生时应该采取的动作,见《Java核心技术:卷一》
2.接触过的回调方法:Android 对控件注册点击监听:button.setOnClickListener(OnClickListener l)。
传入一个OnClickListener(接口实现类)类型的参数(在此类中实现接口中定义的回调方法onClick(View v)),
当点击事件发生时,经过系统的事件传递机制,会被监听到,然后调用接口实现类中设置好的的onClick(View v)方法,做出响应。
该响应方法,在接口中声明,在接口实现类中定义,即onClick(View v)方法,就是回调方法。
套用定义:点击事件发生时采取的动作(即点击事件的回调方法)是onClick(View v)方法
 我是一个Android初学者,目前进度到UI。最近在练习自定义对话框,动态加载对话框布局文件,遇到了IllgalStateException异常,代码如下:
button_user_alert.setOnClickListener(new OnClickListener() {
//放在这里定义程序会崩溃,抛出IllgalStateException
View view = View.inflate(DialogComponentTest.this, R.layout.user_dialog, null);
final EditText userName = (EditText) view.findViewById(R.id.edit_text_name);
final EditText passWord = (EditText) view.findViewById(R.id.edit_text_password);
@Override
public void onClick(View v) {
//				View view = View.inflate(DialogComponentTest.this, R.layout.user_dialog, null);
//				final EditText userName = (EditText) view.findViewById(R.id.edit_text_name);
//				final EditText passWord = (EditText) view.findViewById(R.id.edit_text_password);

new AlertDialog.Builder(DialogComponentTest.this)
.setView(view)
.setPositiveButton("取消", null)
.setNegativeButton("确定", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int which) {
String strUserName = userName.getText().toString();
String strPassWord = passWord.getText().toString();
Toast.makeText(DialogComponentTest.this,strUserName +" : "+strPassWord, 0).show();
}
})
.show();

}
});
    我在看到这样的异常的信息(同一个子类对象对应对个父类对象)也不是太理解,试图从程序运行过程分析,但是由于对回调机制理解不够,也摸不清程序的运行过程。经过查找资料,确定了以上代码的执行顺序:
    1. 向button_user_alert注册监听:方法setOnClickListener(OnClickListener l);
    2. 创建注册监听方法中的OnClickListener接口实现类的对象
    3. 当接收到点击事件时,调用接口实现类中设置好的的onClick(View v)方法。
上面的代码在第二步,创建了对话框的子视图对象,在回调方法中构建对话框时加载子视图。第一次点击时,程序能正常运行,如果再次点击,抛出异常,程序崩溃。原因是第二次点击后,再次调用onClick(View v)方法,重新构建对话框,加载在注册监听时就创建好的子View(还是第一次点击时的子view),这就造成了同一个子View对应多个父View。
   最后,关于回调,在不考虑异步的情况下,在这里用HarryPotter中修眼镜的桥段举个例子,HarryPotter的眼睛碎了(事件),让赫敏修复,赫敏使用魔法修复好,交HarryPotter。
   问题分析:事件:Harrypotter的眼镜碎了,动作:HermioneGranger修眼镜  那么回调方法是HermioneGranger的修眼镜方法
//定义修眼镜接口
public interface RescoverGlass {
//HarryPotter类型参数的修眼镜方法
void rescover(HarryPotter h);
}


//定义HermioneGranger类实现修眼镜接口
public class HermioneGranger implements RescoverGlass{

@Override
//重写修眼镜方法,调用HarryPotter类中的getName方法
public void rescover(HarryPotter h) {
// TODO 自动生成的方法存根
System.out.println("Rescover it");
System.out.println(h.getName()+"here you are!");
}

}
//定义HarryPotter类
public class HarryPotter {
//
private static final String NAME="Harry potter";
//以修眼镜接口实现类类型为参数,调用实现类的修眼镜方法
public void breakMyGlasses(RescoverGlass r){
System.out.println("My glasses are broken!");
r.rescover(this);
}
public String getName(){
return NAME;
}
}


//测试,使用匿名内部类对象实现,类似于setOnClickListener
public class CallBackTestUseInnerClass {
public static void main(String[] args) {
HarryPotter harry = new HarryPotter();//创建一个harry
harry.breakMyGlasses(new RescoverGlass() {

@Override
public void rescover(HarryPotter h) {
// TODO 自动生成的方法存根
System.out.println("Rescover it!");
System.out.println(h.getName()+" , here you are!");

}
});//打碎harry的眼镜,让hermione知道
//最终实现了只要眼镜碎了的事件发生了,就会调用回调方法将眼镜修好
}
}


以上,是自学过程中对回调的一点理解,我的Android和Java是一起看的,非科班出身,基础不好,如果理解有误还忘指正,谢谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: