Android更新ui 的几种方式?Handler 机制(二)
2015-09-06 18:00
429 查看
activity runonuiThread
首先判断当前线程是不是UI线程,如果不是UI线程,activity自己有一个handler,通过handler的post 方法来发送一个runnable。如果是UI线程就调用UI 线程的run方法,其实内部还是通过handler机制更新UI
handler post(runnable)
内部调用sendMessageDelayed()方法 和sendMessage本质上是相同的
handler sendMessage(最常见)
view post
首先判断AttachInfo是否为空,如果不等于空,则通过AttachInfo拿到handler 。通过AttachInfo.handler.post(runnable)方法来更新UI 。不为空的情况下通过ViewRootImpl.getRunQueue().post(runnable);来更新UI
总结:这四种方法,本质上还是通过handler机制来更新UI 。只是在内部有些代码上的差异
代码如下
非UI线程真的不能更新UI么?
在有些情况下非UI 线程是可以更新UI 的。
可以更新的情况
报错的情况
所有更新UI 的操作都会调用view的 invalidate()方法,当我们调用textview.setText()方法会调用checkForRelayout()方法,重新绘制界面,其内部也会调用invalidate()方法。invalidate()方法内部调用ViewParent的invalidateChild()方法,其实真正判断当前线程是否在UI线程中更新界面的操作就是在ViewParent类当中,ViewParent是ViewRootImpl的一个实现类。对于上面的情况,当线程不休眠的时候ViewRootImpl还没有被创建出来,ViewRootImpl在activity的onResume()方法中被创建,onCreate()方法在onResume()方法之前,所以线程不休眠时就没有创建ViewRootImpl,所以就判断是在UI线程更新UI 就可以更新成功。
Avctivity 的启动类是activityThread
首先判断当前线程是不是UI线程,如果不是UI线程,activity自己有一个handler,通过handler的post 方法来发送一个runnable。如果是UI线程就调用UI 线程的run方法,其实内部还是通过handler机制更新UI
handler post(runnable)
内部调用sendMessageDelayed()方法 和sendMessage本质上是相同的
handler sendMessage(最常见)
view post
首先判断AttachInfo是否为空,如果不等于空,则通过AttachInfo拿到handler 。通过AttachInfo.handler.post(runnable)方法来更新UI 。不为空的情况下通过ViewRootImpl.getRunQueue().post(runnable);来更新UI
总结:这四种方法,本质上还是通过handler机制来更新UI 。只是在内部有些代码上的差异
代码如下
public class UpdateUIActivity extends Activity { private TextView text; private Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { text.setText("handler2sendEmptyMessage UI"); }; }; private void handler1() { // 第一中方式 handler.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub text.setText("handelr UI"); } }); } private void handler2() { // 第2中方式 handler.sendEmptyMessage(1); } private void updateUI(){ // 第3中方式 runOnUiThread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub text.setText("runOnUiThread UI"); } }); } private void viewUI(){ // 第4中方式 text.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub text.setText("viewUIpost UI"); } }); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_update_ui); text = (TextView) findViewById(R.id.textview1); new Thread() { @Override public void run() { try { Thread.sleep(2000); //handler2(); //updateUI(); //viewUI(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); } }
非UI线程真的不能更新UI么?
在有些情况下非UI 线程是可以更新UI 的。
可以更新的情况
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_update_ui); text = (TextView) findViewById(R.id.textview1); new Thread() { @Override public void run() { text.setText(" UI"); } }.start(); }
报错的情况
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_update_ui); text = (TextView) findViewById(R.id.textview1); new Thread() { @Override public void run() { try { Thread.sleep(2000); text.setText(" UI"); //handler2(); //updateUI(); //viewUI(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }.start(); }
所有更新UI 的操作都会调用view的 invalidate()方法,当我们调用textview.setText()方法会调用checkForRelayout()方法,重新绘制界面,其内部也会调用invalidate()方法。invalidate()方法内部调用ViewParent的invalidateChild()方法,其实真正判断当前线程是否在UI线程中更新界面的操作就是在ViewParent类当中,ViewParent是ViewRootImpl的一个实现类。对于上面的情况,当线程不休眠的时候ViewRootImpl还没有被创建出来,ViewRootImpl在activity的onResume()方法中被创建,onCreate()方法在onResume()方法之前,所以线程不休眠时就没有创建ViewRootImpl,所以就判断是在UI线程更新UI 就可以更新成功。
Avctivity 的启动类是activityThread
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories