点击事件,Android进程、线程与Handler

  • 一 按钮点击事件
  • 1 .xml文件中的onClick方法
  • 2 匿名内部类(第一行代码中的方法)
  • 3 实现OnClickListener接口的onClick方法
  • 二 线程和进程
  • 1 几个概念
  • 1)程序
  • 2)进程
  • 3)线程
  • 4)并发
  • 5)并行
  • 6)线程的生命周期
  • 7)线程池
  • 2 安卓的线程和进程
  • 1) 进程
  • 2 )线程
  • 3 实战
  • 1)线程的创建
  • 三 Android多线程编程(handler)
  • 1 引入
  • 2 几个概念
  • 1)Handler
  • 2)Message
  • 3 实战
  • 4 原理
  • 最后再说一句
  • 参考资料


一 按钮点击事件

首先介绍一下常用的3种按钮点击事件的实现方法:
1)实现.xml文件中相应控件的onClick方法实现点击事件

2)使用匿名内部类的方法实现点击事件

3)实现OnClickListener接口中的onClick方法实现点击事件

1 .xml文件中的onClick方法

1)在.java中写好实现方法

android中点击事件 android点击事件和handler关系_点击事件


2)在.xml文件中给相应控件添加onClick属性,指明点击事件的实现方法

android中点击事件 android点击事件和handler关系_主线程_02


2 匿名内部类(第一行代码中的方法)

1)绑定控件id
2)设置点击事件

public class MainActivity extends ActionBarActivity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //绑定
        Button btn_call = (Button) findViewById(R.id.button1);
        //为button按钮注册一个监听器
        btn_call.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	//执行动作
                System.out.println("按钮被点击了");
            }
        });
    }   
}

3 实现OnClickListener接口的onClick方法

一般用于有很多按钮需要被点击的时候
1)实现接口
2)绑定按钮
3)设置点击事件
4)重写onClick方法在内部判定点击的按钮是哪个并执行相应代码

//实现OnClickListener接口
public class MainActivity extends ActionBarActivity implements OnClickListener {    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 绑定
        Button btn_call = (Button) findViewById(R.id.button1);
        Button btn_call1 = (Button) findViewById(R.id.button2);
        Button btn_call2 = (Button) findViewById(R.id.button3);
        Button btn_call3 = (Button) findViewById(R.id.button4);
        // 给按钮设置一个点击事件
        btn_call.setOnClickListener(this);
        btn_call1.setOnClickListener(this);
        btn_call2.setOnClickListener(this);
        btn_call3.setOnClickListener(this);
    }

    // 当点击按钮的时候执行
    @Override
    public void onClick(View v) {
        // 具体判断点击的哪个按钮
        switch (v.getId()) {
        case R.id.button1:
            System.out.println("1按钮被点击了");
            break;
        case R.id.button2:
            System.out.println("2按钮被点击了");
            break;
        case R.id.button3:
            System.out.println("3按钮被点击了");
            break;
        case R.id.button4:
            System.out.println("4按钮被点击了");
            break;

        default:
            break;
        }
    }
}

实践一下

二 线程和进程

1 几个概念

1)程序

程序是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码

2)进程

进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。

简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着。

3)线程

线程是操作系统中最小的执行单元,一个进程中可以有多个线程,他们可以并发的执行多个任务。同一个进程中的多线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

线程是一次性消费品,一般用于耗时任务中,避免阻塞UI线程(UI线程只能在主线程中执行),用多线程把占据长时间的程序中的任务放到后台去处理。

4)并发

并发是指两个或多个事件在同一时间间隔内发生。

如果系统只有一个CPU,那么它在同一个时间段只能运行一个线程,那么单CPU的电脑如何运行多个线程?

系统会把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行。这就好比你有一张嘴但是要吃两个苹果,你就一个苹果咬一口的吃。那么在一段时间内你把两个苹果都吃完了,这就是线程的并发

5)并行

并行是指两个或者多个事件在同一时刻发生。

当系统有一个以上CPU时,则线程的操作有可能并行。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源。这就好比你有两张嘴吃两个苹果,你左手一个右手一个同时咬着吃,这就是线程的并行

6)线程的生命周期

百度

7)线程池

百度

2 安卓的线程和进程

1) 进程

安卓进程分为前台进程、后台进程、空进程、服务进程和可见进程。

大家平常说手机卡可以清理一下后台讲的就是后台的进程。

一个安卓程序第一次启动的时候是如何运作的呢?

当第一个安卓程序第一次启动的时候,安卓系统会为它分配一个进程和里面的主线程,该程序所有组件和服务都在这个主线程中运行。安卓会尽量保存正在运行的进程,只有当内存不足的时候,安卓才会去释放一些进程以保证有内存资源去给新的进程或是去响应用户的事件。

2 )线程

线程的概念都是一样的,无论是安卓线程还是Windows线程。

3 实战

extends 继承
implements 实现接口
重写:已实现重新写
实现:未实现新写

1)线程的创建

下面介绍三种创建线程的方法
(1)继承Thread类
新建MyThread.java文件,继承Thread类,重写run方法;

//新建类MyThread继承自Thread类并重写run方法。
class MyThread extends Thread{
	@Override
	public void run(){
		//处理具体的逻辑(耗时任务)
	}
}

在使用时在活动中new出实例(实例化)后调用它的start()方法,这样run()方法中的代码就会在你刚创建的线程中运行了。

//匿名实例化
new MyThread().start();

(2)实现Runnable接口(常见)、
新建MyThread.java文件,实现Runnable接口,实现run方法。

//新建类MyThread继承自Runnable类并实现run方法。
class MyThread implements Runnable{
	@Override
	public void run(){
		//处理具体的逻辑(耗时任务)
	}
}

则在活动中使用的代码就需要改变成。

//创建MyThread的对象(实例化)
MyThread myThread = new MyThread();
/*用Thread的构造函数(接收一个Runnable参数即myThread对象)
匿名创建新的Thread对象并调用它的start方法。*/
new Thread(myThread).start();

(3)匿名类(常见)
上述两种方法都需要创建(定义)一个新的类,如果你不想(不需要),也可以使用匿名类的方式。

//创建新线程
new Thread(new Runnable() {
	@Override
	public void run(){
		//处理具体的逻辑(耗时任务)
	}
}).start();

三 Android多线程编程(handler)

1 引入

现在我们都知道,耗时操作可以另外创建一个线程来运行以避免堵塞主线程。但问题就出现了,由于Android的UI是线程不安全的(具体细节可以百度),所以想要更新UI元素必须在主线程中进行。那么如果我们需要在子线程里去执行耗时任务后根据返回的结果来更新UI控件,该怎么办呢?
这就需要用到这节所学的Handler工具,也就是异步消息处理机制。简单的说就是在子线程中回到主线程执行并带回结果。

2 几个概念

1)Handler

官方API

Handler是用来结合线程的消息队列来发送、处理“Message对象”和“Runnable对象”的工具。每一个Handler实例之后会关联一个线程和该线程的消息队列。当你创建一个Handler的时候,从这时开始,它就会自动关联到所在的线程/消息队列,然后它就会陆续把Message/Runnable分发到消息队列,并在它们出队的时候处理掉。

这个API大概看一下就行,简单来说Hanndler是个处理者,是用来发送和处理信息,让线程之间进行交互的。

发送消息一般是用Handler的sendMessage()方法,发出的消息最终会传递到Handler的handleMessage()方法中。

2)Message

Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。

3 实战

读代码:先大概看看有什么方法之类的

public class MainActivity extends AppCompatActivity implements View.OnclickListener {

	//整形常量用于表示TextView这个动作
	public static final int UPDATE_TEXT = 1;
    private TextView text;
    //创建handler
    //由于最新版本中使用new handler()来实例化可能会导致bug,所以官方舍弃了这种用法,我们只需要在参数中传入Looper.getMainLooper()就可以继续使用了。(网上查阅得到的信息是说需要确切的说明handler的Looper不能为空)
    private Handler handler = new Handler(Looper.getMainLooper()) {
    	
    	public void handlerMessage(Message msg) {
    	//对具体的Message进行处理(这里的代码会转到主线程中)
    		switch (msg.what) {
    			case UPDATE_TEXT:
    				//进行UI操作
    				text.setText("Nice to meet you");
    				break;
    			default:
    				break;
    		}
    	}
    };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		text = (TextView) findViewById(R.id.text);
		Button changeText = (Button)findViewById(R.id.change_text)
		changeText.setOnClickListener(this);
	}
    
    @Override
    public void onClick(View v){
    	switch (v.getId()) {
    		case R.id.change_text:
    			//开启子线程
   				new Thread(new Runnable(){
   					@override
   					public void run(){
   					//创建Message对象
   						Message message = new Message();
   						//将what字段的值指定为UPDATE_TEXT
   						message.what = UPDATE_TEXT;
   						//发送Message
   						handler.sendMessage(message);
   					}
   				}).start();
   				break;
   			default:
   				break;
   		}
   	}
}

思路
1创建一个Handler对象,重写它的handleMessage()方法用来进行UI操作。
2在点击事件里开启一个子线程,并在里面创建Message对象
3调用sendMessage()方法将Message发送出去给handleMessage()。
这时Handler就会在主线程中执行handleMessage()中的代码了。

4 原理

参考《第一行代码》P345页。

最后再说一句

今天学的内容其实是Android 开发四大组件中服务的基础,因为知道你们也快期末考没什么时间学习新的知识,所以这篇教程只是注重应用,并没有很多原理的东西,用最简单易懂的话教会你们使用。但想学好安卓光知道它怎么使用是不行的,大神都是懂得原理然后能够融会贯通,这样才能做出自己想做的东西而不是简单的搬运。所以我建议大家考完试之后,去好好的看一下原理,最重要也是最基础的就是Java的三特性:封装,多态,继承。学完之后再回来看你就会恍然大悟并且发现原来这东西你已经用了这么久了。
便于你们学习我就把我认为最好去学的东西大概罗列一下:
1Java的基本语法
2Java的三特性
3《第一行代码》

参考资料

《第一行代码》Android多线程编程。