首先回答你第一个,什麽是线程,还有AsyncTask,估计是你大概的线程通讯.
1、同步:
在一个线程执行,先执行完了前面的代码,才会执行后面的代码,是阻塞的。
2、异步:
开启一个新的线程执行,不会等前面的代码执行完,就会执行后面的代码,是非阻塞的。
3、什麽是main(UI)线程:
android启动的第一个线程。主要负责处理ui和事件的工作。
【特别注意】
1、更新ui只能在ui线程进行,不可以在其他线程更新ui,否则会崩溃。
2、在ui线程不可以做耗时操作,比如网络请求等,如果做耗时操作,就会阻塞ui线程,就会导致界面卡顿。会出现ANR(application not response、应用无响应)。
4、异步通讯:
那么我们要请求网络或者其他耗时操作的时候怎么办?这就涉及到异步通讯或者叫线程通讯。
先在子线程加载数据,做耗时操作,然后把取得的数据传递给ui线程,让ui线程来更新ui。
5、线程通讯的方式:
1、Handler(可以理解成消息获取的工具,非官方翻译)
使用方法:
1、在主线程实例化一个Hanlder,复写handleMessage()方法,在里面做更新ui的操作;
2、让子线程持有handler的引用,使用handler来发送消息。
传递参数:
获取消息,请使用handler.obtainMessage();
what:用来区分消息的类型
obj:传递复杂参数
arg1:传递简单的int参数
arg2:传递简单的int参数
Handler的原理:
1、在主线线程新建一个handler,在子线程中调用这个Handler发送消息到消息队列,在发送的时候,message.target会保存发送它的Handler;
2、主线程只带一个looper循环,会不断的从消息队列中取出消息,如果没有消息,就阻塞;
3、在主线程中调用message.target(发送他的Handler)的DispatchMessage,间接调用handlerMeaage来处理消息。
在子线程中使用Handler:
因为使用Handler需要消息循环,子线程中没有消息循环,所以,这里有2中方法:
1、使用主线程的loop(getMainLooper()),然后在创建Handler的时候,把这个获取的主线程的loop传进去;但是,这种方法,子线程中的Handler还是在主线程处理消息。因为用的主线程的循环。
2、给子线程建立消息循环:
先调用 Looper.prepare();建立消息循环,消息队列等。
在建立了Handler之后,调用Looper.loop(),开始loop循环,如果不掉用,循环就不会开始运行,就不会处理消息。
代码如下:
new Thread(new Runnable() {
@Override
public void run() {
Log.i(TAG, "run: ");
//建立消息循环,建立消息队列
Looper.prepare();
han=new Handler(){
@Override
public void handleMessage(Message msg) {
Log.i(TAG, "handleMessage: "+Thread.currentThread().getName());
}
};
//开始loop循环
Looper.loop();
}
}).start();
Handler的其他使用
1、hander.post()方法可以直接把一个代码post到主线程执行;
handler.post(new Runnable() {
@Override
public void run() {
//这里在主线程执行
}
});
2、activity的runOnUITHread();
runOnUiThread(new Runnable() {
@Override
public void run() {
//这里在主线程执行
}
});
3、任何控件的Post方法();
tv.post(new Runnable() {
@Override
public void run() {
//这里在主线程执行
}
});
4、延时执行:
handler.postDelayed(new Runnable() {
@Override
public void run() {
//需要延时执行的代码
}
},1000);
getMainLooper();获得主线程looper, myLooper()
得到的是当前线程 内部调用 ThreadLocal.get();
2、HandlerThread:支持Handler的线程,内部实现了Loop循环
使用方法:
//新建一个代loop的子线程
final HandlerThread handlerThread=new HandlerThread("zixiancheng");
//让子线程开始执行
handlerThread.start();
//把线程的looper传给Hander运行,这样,这个Hander就在zixianchegn中执行了。
handler=new Handler(handlerThread.getLooper())
【5星级 注意!!】
使用了这个HandlerThread,他会开启一个循环一直跑,所以,在退出程序的时候,一定要调用quit(),退出循环。
@Override
protected void onDestroy() {
handlerThread.quit();
super.onDestroy();
}
3、AsyncTask:异步任务
继承自AsyncTask,写一个自己的异步任务,注意,AsyncTask有3个泛型。
从做到又分别是:参数的类型,进度的类型,返回结果的类型。
execute():执行这个异步任务,必须在主线程中调用
onPreExecute():在执行异步任务之前调用
doInBackground():执行任务的函数,比如去请求网络
publishProgress():在请求的过程中,更新一下进度,会调用onProgressUpdate
onProgressUpdate():更新进度,在主线程中运行
onPostExecute():请求完了以后,可以保存结果
cancel():取消任务的时候调用。
以上,是关于线程通讯,在回答你关于service:
service使用方法
1、startService:
特点:
仅仅需要长时间运行,不需要和其数据交互
使用stopService/stopself()停止服务
多次调用,onCreate方法只执行一次,onStartCommand多次执行
不与当前的Activity绑定,即使当前activity已经关闭了,服务也会急需运行
使用方法:
继承Service写一个类,实现自己的业务需要(onCreate、onStartCommand);
然后在清单文件中申明;
在activity里面通过startService来启动这个服务;
2、bindService:
特点:
需要和其进行数据交互,使用Binder类
使用unbindService停止服务
当activity销毁之后对应绑定的service自动停止、销毁
不能夸进程通信绑定
不能在广播中调用
使用方式:
继承Service写一个类,实现自己的业务需要(onCreate、onBind);
然后在清单文件中申明;
在activity里面通过bindService来启动这个服务,这里还需要一个参数,就是serviceConnection对象,通过这个对象来处理activity和service绑定的事件;
如果要相互通讯,还需要使用Binder:
继承自Binder来实现一个自己的Binder,在service的onBInd里面返回一个自己的Binder实例;
在activity的serviceconnection里面的onServiceConnected会把service里面的Binder的对象传递回来;我门可以在BInder里面,得到目标service的实例,这样,就可以和Service交互了。
那么,什么是IntentService?
IntentService:
特点:
会自动开启一个子线程,子线程任务结束以后,会自动stop,不需要手动去stopService或者stopself();
如果多次启动,会在一个队列中,依次的运行;
使用方法:
继承IntentService,实现自己的服务,然后重写onHandleIntent(),在里面做耗时操作;
intentService在启动的时候,需要一个默认的构造函数;