zoukankan      html  css  js  c++  java
  • Android菜鸟的成长笔记(12)——Handler、Loop、MessageQueue

      当一个程序第一次启动时,Android会启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如按键事件、触屏事件、绘图事件,主线程也被称为UI线程。
    UI的操作只能是通过主线程来操作,为了解决多线程操作UI的问题,就用到了Handler类。
    一、Handler类
    Handler类的作用有两个:
    1、在新启动的线程中发送消息。
    2、在主线程中获取、处理消息。
    例如:
    package com.example.testlistener;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    import android.app.Activity;
    import android.content.res.Configuration;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnLongClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    	EditText txt;
    	final Handler hander = new Handler(){
    		public void handleMessage(android.os.Message msg) {
    			if(msg.what == 0x1234){
    				Toast.makeText(MainActivity.this, msg.arg1 + "", 1000).show();
    			}
    		};
    	};
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		new Timer().schedule(new TimerTask() {
    			int i = 0;
    			@Override
    			public void run() {
    				i++;
    				Message msg = new Message();
    				msg.what = 0x1234;
    				msg.arg1 = i;
    				hander.sendMessage(msg);
    			}
    		}, 0, 2000);
    	}
    	
    }
    
    Message是Hander接收和处理的消息对象。通过向Message中添加消息,将消息放入消息队列MessageQueue,然后通过Looper方法读取MessageQueue。
    打开Android系统源码可以看到:
        private Looper() {
            mQueue = new MessageQueue();
            mRun = true;
            mThread = Thread.currentThread();
        }
    程序创建时Looper会在它的构造器中创建MessageQueue对象。
    handlerMessage方法位于主线程,可以处理UI.
    二、Handler、Looper、MessageQueue的工作原理
    Looper:每个线程只有一个Looper,负责管理MessageQueue,会不断地从MessageQueue中取出消息,并将消息分给对应的Handler处理。
    MessageQueue:由Looper负责管理,采用先进先出的方式管理Message(消息队列).
    Handler:把消息发送给Looper管理的MessageQueue并负责处理Looper分给它的消息。
    为了保证当前线程中有Looper对象,有如下两种情况:
    1、主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可。
    2、自己定义的子线程,必须先创建一个Looper对象,并启动它。
    例如:将上面的例子加以修改
    package com.example.testlistener;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    import android.app.Activity;
    import android.content.res.Configuration;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.os.Message;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnLongClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    	EditText txt;
    	Button bt;
    	TestThread testThread;
    	int j = 0;
    	final Handler hander = new Handler(){
    		public void handleMessage(android.os.Message msg) {
    			if(msg.what == 0x1234){
    				Toast.makeText(MainActivity.this, msg.arg1 + "", 1000).show();
    			}
    		};
    	};
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		txt = (EditText) findViewById(R.id.txt);
    		bt = (Button) findViewById(R.id.bn);
    		testThread = new TestThread();
    		testThread.start();
    		bt.setOnClickListener(new OnClickListener() {
    			
    			@Override
    			public void onClick(View arg0) {
    				j++;
    				Message msg = new Message();
    				msg.what = 0x1000;
    				msg.arg1 = j;
    				testThread.thander.sendMessage(msg);
    			}
    		});
    		
    		new Timer().schedule(new TimerTask() {
    			int i = 0;
    			@Override
    			public void run() {
    				i++;
    				Message msg = new Message();
    				msg.what = 0x1234;
    				msg.arg1 = i;
    				hander.sendMessage(msg);
    			}
    		}, 0, 2000);
    	}
    	
    	//自定义子线程
    	class TestThread extends Thread{
    		public Handler thander;
    		@Override
    		public void run() {
    			//创建一个Looper对象
    			Looper.prepare();
    			thander = new Handler(){
    				@Override
    				public void handleMessage(Message msg) {
    					if(msg.what == 0x1000){
    						System.out.println("j = " + msg.arg1);
    						//txt.setText(msg.arg1 + "");
    					}
    				}
    			};
    			//启动Looper
    			Looper.loop();
    		}
    	}
    	
    }
    
    运行结果:







  • 相关阅读:
    [CSS] prefers-reduced-motion
    [VSCode] Adding Custom Syntax Highlighting to a Theme in VSCode
    Subversion/Git/ReviewBoard工作流程
    oracle hints
    Node.js学习(10)----文件系统fs
    网络子系统41_inet_peer平衡二叉树的删除
    由链表初始化看C语言的二级指针
    挣值管理不是搞数字游戏(4)——让挣值管理实用!
    关于数据库一致改关闭下redo日志文件丢失的处理办法的总结
    Android 操作系统的内存回收机制
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6469203.html
Copyright © 2011-2022 走看看