Android——线程创建以及handler
一:创建子线程:
1:通过继承Thread类,并改写run方法来实现一个线程
new mThread().start();
public class mThread extends Thread{@Overridepublic void run(){System.out.print("继承Thread类,实现run方法");}};
2:创建Runnable类对象并复写Run()方法创建线程:
新建一个线程如下:
new Thread(mThread).start();
- Runnable mThread=newRunnable(){
- @Overrde
- publicvoidrun()
- {
- system.out.println(“实现一个Runnable类,并实现Run方法”);
- }
- };
注意:Runnable是一个接口,不是一个线程,一般线程会实现Runnable。 所以如果我们使用匿名内部类是运行在UI主线程的,如果我们使用实现这个Runnable接口的线程类,则是运行在对应线程的。
Runnable 并不一定是新开一个线程,比如下面的调用方法就是运行在UI主线程中的:
Handler mHandler=new Handler();mHandler.post(new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stub}});
通过调用handler的post方法,把Runnable对象(一般是Runnable的子类)传过去;handler会在looper中调用这个Runnable的Run方法执行。
二:子线程运作:
(1) Activity.runOnUiThread(Runnable)
在UI线程里运行指定的动作,如果当前线程是UI线程,则立刻被执行
,如果是主线程,则该动作被发送到UI线程的事件队列中,等待处理。
activity.runOnUiThread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub int i = 30;textView.setText(""+i+" s");}} });
Handler的定义:
* 主要接受子线程发送的数据, 并用此数据配合主线程更新UI。当应用程序启动时,
* Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说,
* 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。
* 如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,
* 如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示 "强制关闭"。
* 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的,
* 也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。这个时候,Handler就出现了,来解决这个复杂的问题 ,
* 由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,
* 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象(里面包含数据),把这些消息放入主线程队列中,配合主线程进行更新UI。
Handler一些特点:
* Handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
* 它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行
* Handler中分发消息的一些方法
* post(Runnable)
* postAtTime(Runnable,long)
* postDelayed(Runnable,long)
* sendEmptyMessage(int)
* sendMessage(Message)
* sendMessageAtTime(Message,long)
* sendMessageDelayed(Message,long)
* 以上post类方法允许你排列一个Runnable对象到主线程队列中,
当需要在不同于主UI线程中执行则需要配合HandlerThread进行使用:
Android中Handler的使用,一般都在UI主线程中执行,因此在Handler接收消息后,处理消息时,不能做一些很耗时的操作,否则将出现ANR错误。Android中专门提供了HandlerThread类,来解决该类问题。HandlerThread类是一个线程专门处理Hanlder的消息,依次从Handler的队列中获取信息,逐个进行处理,保证安全,不会出现混乱引发的异常。HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,它有个Looper成员变量
package cn.wzg.activity;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.HandlerThread;import android.os.Looper;import android.os.Message;public class HandlerTest extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); System.out.println("activity.............." + Thread.currentThread().getId()); System.out.println("activity.name.............." + Thread.currentThread().getName()); // HandlerThread handlerthread = new HandlerThread("handler_thread"); handlerthread.start(); Myhandler myhandler = new Myhandler(handlerthread.getLooper()); Message msg = myhandler.obtainMessage(); Bundle b = new Bundle(); b.putString("username", "lvjian"); b.putString("password", "zhanghaiyan"); msg.setData(b); msg.sendToTarget(); } class Myhandler extends Handler { public Myhandler() { super(); // TODO Auto-generated constructor stub } public Myhandler(Looper looper) { super(looper); // TODO Auto-generated constructor stub }@Override public void handleMessage(Message msg) { String username = (String) msg.getData().getString("username"); System.out.println("handler.............." + Thread.currentThread().getId() + username); System.out.println("handler.name.............." + Thread.currentThread().getName()); super.handleMessage(msg); } }}
Handler 与谁相关联不是看声明在什么地方,是看与哪个线程的looper挂钩。默认是主线程的looper.因为主线程中默认就有了looper,消息循环队列。
Android SDK中的方法说明:
//用于返回与该线程相关联的Looper对象
public Looper getLooper ()
//获得该线程的Id
public int getThreadId ()
//结束当前的Looper 循环。
public boolean quit ()
//用于looper取出的消息处理
public void run ()
handler自己有几种方式:
1,用来处理消息和线程,每个handler实例关联一个单线程和该线程 的一个消息队列。
2,handler可以执行一个线程对象(Runnable实例)也可以发送和处理消息
如下:
public class MainActivity extends Activity implements OnClickListener{public static final String TAG = "MainActivity";private Handler mHandler;private boolean mRunning = false;private Button mBtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);HandlerThread thread = new HandlerThread("MyHandlerThread");thread.start();//创建一个HandlerThread并启动它mHandler = new Handler(thread.getLooper());//使用HandlerThread的looper对象创建Handler,如果使用默认的构造方法,很有可能阻塞UI线程mHandler.post(mBackgroundRunnable);//将线程post到Handler中mBtn = (Button)findViewById(R.id.button);mBtn.setOnClickListener(this);}@Overrideprotected void onResume() {super.onResume();mRunning = true;}@Overrideprotected void onStop() {super.onStop();mRunning = false;}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}//实现耗时操作的线程Runnable mBackgroundRunnable = new Runnable() {@Overridepublic void run() {//----------模拟耗时的操作,开始---------------while(mRunning){Log.i(TAG, "thread running!");try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}//----------模拟耗时的操作,结束---------------}};@Overrideprotected void onDestroy() {super.onDestroy();//销毁线程mHandler.removeCallbacks(mBackgroundRunnable);}@Overridepublic void onClick(View v) {Toast.makeText(getApplication(), "click the button!!!", Toast.LENGTH_SHORT).show();}}销毁线程:
mHandler.removeCallbacks(mBackgroundRunnable);
更多相关文章
- Android(安卓)实现TextView字符串关键字变色
- 第14章 使用Kotlin 进行 Android(安卓)开发(1)
- Android(安卓)RecyclerView使用 及 滑动时加载图片优化方案
- Android(安卓)IPC机制及Binder原理
- android—OpenGL—GL10方法解析
- DialogFragment与Activity通信最佳实践
- 【Android】LitePal安装和使用
- android canvas 绘制bitmap并保存到本地
- android中重要知识点