-
截获Handler要接收的消息
查看全部 -
Handler 作用:1 更新UI, 2发送消息,处理消息
查看全部 -
---转: handler总结:<br> 1.不能直接在非UI线程直接更新UI(大多数时候)。<br> 2.每次创建Handler时需要给它绑定一个looper,如果是主线程不给定具体的looper则会绑定默认的looper。<br> 3.子线程运行时一定要调用start()方法。<br> 4.在某些特殊情况下在非UI线程是可以更新UI的//不推荐使用(当刚启动Activity即onCreate里面此时onResume方法还没有执行的时候可以,因为在线程中更新UI时会调用ViewParent.invalidateChild()方法检查当前的Thread是否是UIThread,若为UIThread则可以更新(ViewParent是一个接口类,其实现是ViewRootImpl;invalidateChild()方法调用checkThread()方法来检查线程是否为主线程)。ViewRootImp是在onResume方法中初始化的,所以只要在ViewRootImpl创建之前更新UI(在onCreate方法中创建线程并执行,此时还没有初始化ViewRootImp),就可以逃避掉checkThread()的检查进而更新UI。)<br> 5.更新UI的四种方式:<br> a>使用handler.post方法<br> b>使用handler.sendMessage方法,用hanleMessage方法更新UI。<br> c>用runOnUiThread方法。<br> d>使用view.post方法。<br> 6.HandlerThread本质是子线程,在创建子线程的handler时绑定的是handlerThread对象的getLooper()。
查看全部 -
---摘自评论区 在ViewRootImpl没有实例化的时候是不会check是否是主线程,也就是说,在非UI线程中是可以更新UI的,但是为了线程安全的原因,系统会强制要求只能在主线程中更新UI(猜测)。之所以说没有太大的意义是因为实际开发中是不会有这种情况的,谷歌官方也是说了只能在UI线程更新UI,这顶多算是一个BUG吧,看不懂的朋友们知道就行了,不用深究~ 非UI线程能否更新UI
非UI线程能否更新UI --->刚启动的时候,立即在非UI线程更新->不报错。 --->休眠2s钟以后,更新——————>报错 更新UI-->会调用checkForRelayout()方法 -->invalidate()方法-->invalidate(true)方法,关注viewParent-->ViewRootImpl是ViewParent的实现类 --->p.invalidateChild()-->查看ViewRootImpl.invalidateChild()-->checkThread()方法-->判断UI线程是否是当前线程,不想等抛出异常。 ViewRootImpl是onResume()方法才会创建。所以onCreate()方法中要延迟才可以。 handleResumeActivity()方法---》viewManager.addView()-->ViewRootImpl初始化。,关注viewParent-->ViewRootImpl是ViewParent的实现类
查看全部 -
Android中更新UI的几种方式: 1. public void activityUpdateUI(){ runOnUiThread(new Runnable() { @Override public void run() { textView.setText("Changed by Activity"); } }); } 2. public void handlerChangeUI(){ handler.post(new Runnable(){ @Override public void run() { textView.setText("OK"); } }); } 3. public void handlerChangeUI2(){ handler.sendEmptyMessage(1); } 4. view.post() public void viewUpdateUI(){ textView.post(new Runnable() { @Override public void run() { textView.setText("UI was updated by view.post"); } }); } 通过源码我们可以发现: handler使用post()去发送一个Runnable,其实它内部也是封装了Message去发送的,本质上和直接发送Message没有区别; runOnUiThread()方法会判断当前线程是不是UI线程,不是的话,则调用Activity自己的Handler对象,通过该对象发送一个Runnable;如果是,则调用UI线程的run()方法。 View的post()方法会判断 attachInfo 是否为空。如果不为空,则通过 attachInfo 的Handler对象去post一个Runnable对象。如果为空,则调用ViewRootImpl的getRunQueue去拿到一个Handler去post一个Runnable对象。 综上,更新UI的四种方法,本质上都是通过Handler机制去更新UI的。
查看全部 -
public class Main2 extends Activity implements View.OnClickListener { int aaa=0; Button button1,button2; Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { Message message=new Message(); System.out.println("Handler"); threadHandler.sendMessageDelayed(message,1000); } }; Handler threadHandler; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main2); button1=(Button) findViewById(R.id.button1); button2=(Button) findViewById(R.id.button2); button1.setOnClickListener(this); button2.setOnClickListener(this); HandlerThread thread=new HandlerThread("threadHandler"); thread.start(); threadHandler=new Handler(thread.getLooper()){ @Override public void handleMessage(Message msg) { Message message=new Message(); System.out.println("ThreadHandler"); aaa++; System.out.println(aaa); if(aaa<5) { handler.sendMessageDelayed(message, 1000); } } }; } @Override public void onClick(View view) { switch (view.getId()){ case R.id.button1: handler.sendEmptyMessage(1); break; case R.id.button2: handler.removeMessages(0); threadHandler.removeMessages(0); break; default: break; } } }
查看全部 -
public class Main extends AppCompatActivity implements View.OnClickListener{ private TextView textView; private ImageView imageView; Button btn; Handler handler=new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { Toast.makeText(getApplicationContext(),""+222,Toast.LENGTH_SHORT).show(); return false; } }){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); textView.setText(msg.obj.toString()); Toast.makeText(getApplicationContext(),""+111,Toast.LENGTH_SHORT).show(); } }; private int imagesId[]={R.drawable.hy1,R.drawable.hy2,R.drawable.hy3}; private MyRunnable myRunnable=new MyRunnable(); int index; @Override public void onClick(View view) { handler.removeCallbacks(myRunnable); } class Person{ public int age; public String name; @NonNull @Override public String toString() { return "age:"+age+" name:"+name; } } class MyRunnable implements Runnable { @Override public void run() { index++; index=index%3; imageView.setImageResource(imagesId[index]); handler.postDelayed(myRunnable,1000); } } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView=(TextView) findViewById(R.id.tv); textView.setText("hh"); imageView=(ImageView) findViewById(R.id.imageView); btn=(Button)findViewById(R.id.button); btn.setOnClickListener(this); handler.postDelayed(myRunnable,1000); new Thread(){ @Override public void run() { super.run(); try { Thread.sleep(1000); handler.post(new Runnable() { @Override public void run() { /*textView.setText("爷"); handler.sendEmptyMessage(1);*/ } }); } catch (InterruptedException e) { e.printStackTrace(); } Person person=new Person(); person.age=18; person.name="爷"; Message message=handler.obtainMessage(); message.obj=person; message.sendToTarget(); } }.start(); } }
查看全部 -
new Thread() { public void run() { try { Thread.sleep(1000); handler.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub // 更新文本信息 // 此时直接在这里更新ui的时候,程序将会直接崩溃掉 textView.setText("更新了"); } }); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }; }.start(); 从上面的方法中我们可以知道,如果想直接更新ui,我们需要在Thread的run方法中通过 handler.post()的方法来实现,而post方法中的参数是一个new Runnable(){public void run(){} ,然后我们在这个run方法中去更新ui,这才是正确的方法
查看全部 -
handler原理图解:
查看全部 -
handler原理:
查看全部 -
ViewRootImpl是在WindowManagerGlobal类中的
查看全部 -
ActivityThread中
查看全部 -
checkThread()
查看全部 -
View的invalidateChild(View child)
查看全部 -
View的invalidate方法源码
查看全部
举报