从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是一起看的,非科班出身,基础不好,如果理解有误还忘指正,谢谢。
相关文章推荐
- android apk 防止反编译技术第二篇-运行时修改Dalvik指令
- android混淆去掉日志
- Android 图片处理之 Fresco
- android出现注: 某些输入文件使用或覆盖了已过时的 API。 注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。 注: 某些输入文件使用了未经检查或不安全的操作。
- Android 长度单位
- android初接触之activity2
- android控件拖动,移动、解决父布局重绘时控件回到原点
- Android aidl在Framework的使用
- 读写文件(内存,sd等多种) Android
- Android官方数据绑定框架DataBinding(一)
- android:descendantFocusability用法简析(Item失效问题)
- Android:验证手机和邮箱的正则表达式
- android调试debug快捷键
- Android 自定义可编辑图文混排EditText
- Android之DatePicker和TimePicker实现以及自定义大小
- Android Lint工具 优化代码 <12>
- android sqlite 不存在插入,存在更新语句
- Android性能优化典范(一)
- 从sd卡中显示一个图片 Android
- 【Android】Genymotion打开出现Unable to load VirtualBox engine