android多线程使用入门(简要笔记)
使用Handler进行主线程和子线程之间的通信
1 Handler是消息发送及处理器,为了方便在各线程中使用,可以考虑设置为全局变量,handler可用于精确时间的频繁操作。handler的回调操作handlermessage等方法在与handler关联的线程中进行,handler的关联线程与其关联的looper相同。
2 Looper是运行在一个且唯一一个线程中的消息循环控制器,负责控制消息输入输出的管理。
3 Message是数据的传输类。
4 MessageQueue是消息队列,被Looper管理。
原理图如下:
package com.multithread;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity{
private HandlerTest1 mhandler1;
private HandlerTest2 mhandler2;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textView=(TextView)findViewById(R.id.tv_test);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {;
//新建一个线程
new Thread(new Runnable() {
@Override
public void run() {
//准备该线程的LOOPER循环,获取LOOPER来初始化handler,并发送数据
Looper.prepare();
mhandler1 = new HandlerTest1(Looper.myLooper());
mhandler1.sendEmptyMessage(1);
Looper.loop();//开启循环
}
}).start();
}
});
}
//重写几个试验用的Handler内部类,也可以写作外部类防止内存泄漏
private class HandlerTest1 extends Handler{
private HandlerTest1(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//延时操作Ing...
//获取UI线程的LOOPER初始化Handler,并发送数据
mhandler2=new HandlerTest2(getMainLooper());
mhandler2.sendEmptyMessage(2);
//自建的looper通常需要手动关闭,可以在任务执行完毕的时候or在程序退出时候onDestroy方法里
getLooper().quit();
}
}
private class HandlerTest2 extends Handler{
private HandlerTest2(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//在ui线程中修改ui
textView.setText("successfull");
}
}
}
AsyncTask封装类的使用
AsyncTask是专门用于异步线程操作的封装类,使用简便。android3.0前它使用的是静态线程池,其旧线程可以被重复利用,不必重建。而后为了避免出现并行错误,改为在单一线程中运行。
AsyncTask可以按多个阶段回调。另外注意AsyncTask实例只能执行使用一次,且必须在主线程中创建。
- 首先扩展一个AsyncTask接口,此接口可以直接扩展或者传入三个泛型 《Params,Progress,Result》分别表示传入task的参数类型,progress进度publish推出的计算类型如Integer,还有最后便是task返回的结果类型。
- 接着重写四个阶段方法
void onPreExecute() 后台任务开始前条用,一般可以做界面初始化操作
Result doInBackground(Params…param) 此方法默认在子线程中运行,若要进行UI更新,可考虑在内调用publishProgress。只有这个方法是必须重写的
void onProgressUpdate(Integer…integer) 修改UI
void onPostExecute(Result result) 通过返回的数据操作UI
PS:官方文档要求不要手动调用以上所有方法!!
新建一个该扩展类的实例调用
.execute()/.execute(Params…param)就可以执行任务。此方法必须在UI线程中使用。
使用.cancel(boolean)进行取消,会直接跳过onPostExecute();