##(1)多线程通信
###(1)Android层面
####(1)runOnUiThread
runOnUiThread(new Runnable() {
@Override
public void run() {
//更新UI
}
});
####(2)View.post和View.postDelayed
View默认带一个Handler属于mainLooper的,View.post相当于这个Handler.post,post带一个Runnable,但这个Runnable的工作是在UI线程中执行,可直接在Runnable内对UI进行更新操作。
view.post(new Runnable() {
@Override
public void run() {
view.getHeight()
}
});
view.setEnabled(false);
view.postDelayed(new Runnable() {
@Override
public void run() {
view.setEnabled(true);
}
},300);
####(3)Handler
最常用的线程通信方式
mHandler.post(new Runnable() {
@Override
public void run() {
}
});
mHandler.sendMessage(Message.obtain());
####(4)AsyncTask
public class ProgressBarAsyncTask extends AsyncTask<Integer, Integer, String> {
/**
* 这里的Integer参数对应AsyncTask中的第一个参数
* 这里的String返回值对应AsyncTask的第三个参数
* 该方法并不运行在UI线程当中,主要用于异步操作,所有在该方法中不能对UI当中的空间进行设置和修改
* 但是可以调用publishProgress方法触发onProgressUpdate对UI进行操作
*/
@Override
protected String doInBackground(Integer... params) {
}
/**
* 这里的String参数对应AsyncTask中的第三个参数(也就是接收doInBackground的返回值)
* 在doInBackground方法执行结束之后在运行,并且运行在UI线程当中 可以对UI空间进行设置
*/
@Override
protected void onPostExecute(String result) {
}
//该方法运行在UI线程当中,并且运行在UI线程当中 可以对UI空间进行设置
@Override
protected void onPreExecute() {
}
/**
* 这里的Intege参数对应AsyncTask中的第二个参数
* 在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行
* onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作
*/
@Override
protected void onProgressUpdate(Integer... values) {
}
}
####(5)第三方EventBus
//事件类
public class MessageEvent {
...
}
//注册事件
EventBus.getDefault().register(this);
//发送事件
EventBus.getDefault().post(messageEvent);
//处理事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
...
}
//取消事件
EventBus.getDefault().unregister(this);
###(2)Java层面
####(1)Object类的wait()和notify()
public class Service {
public void testMethod(Object lock) {
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void synNotifyMethod(Object lock) {
try {
synchronized (lock) {
lock.notify();
Thread.sleep(5000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
####(2)Condition类的await()和signal()
private Lock lock = new ReentrantLock();
public Condition condition = lock.newCondition();
public void await() {
try {
lock.lock();
//await之前必须调用lock,await有释放锁动作
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signal() {
try {
lock.lock();
condition.signal();
} finally {
lock.unlock();
}
}
public void signalAll() {
try {
lock.lock();
condition.signalAll();
} finally {
lock.unlock();
}
}
####(3)管道流进行通信
- PipedInputStream和PipedOutputStream
- PipedReader和PipedWriter
public void writeMethod(PipedOutputStream out) {
try {
for (int i = 0; i < 300; i++) {
String outData = "" + (i + 1);
out.write(outData.getBytes());
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readMethod(PipedInputStream input) {
try {
byte[] byteArray = new byte[20];
int readLength = input.read(byteArray);
while (readLength != -1) {
String newData = new String(byteArray, 0, readLength);
System.out.print(newData);
readLength = input.read(byteArray);
}
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
PipedInputStream inputStream = new PipedInputStream();
PipedOutputStream outputStream = new PipedOutputStream();
outputStream.connect(inputStream);
####(4)阻塞队列(BlockingQueue)
当试图向BlockingQueue中放入元素时,如果队列已满则该线程被阻塞,当试图向BlockingQueue中取出元素时,如果队列为空则该线程被阻塞;
(1)put(E e):尝试把E元素放入BlockingQueue中,如果队列已满则阻塞线程;
(2)take():尝试从BlockingQueue头部取出元素,如果该队列元素为空,则阻塞该线程;
##(2)跨进程通信
####(1)Bundle/Intent传递数据
可传递基本类型,String,实现了Serializable或Parcellable接口的数据结构。Serializable是Java的序列化方法,Parcellable是Android的序列化方法,前者代码量少(仅一句),但I/O开销较大,一般用于输出到磁盘或网卡;后者实现代码多,效率高,一般用户内存间序列化和反序列化传输。
####(2)文件共享
对同一个文件先后写读,从而实现传输,Linux机制下,可以对文件并发写,所以要注意同步。顺便一提,Windows下不支持并发读或写。
####(3)Messenger
Messenger是基于AIDL实现的,服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler来创建Messenger,在onBind时返回Messenger的binder。
双方用Messenger来发送数据,用Handler来处理数据。Messenger处理数据依靠Handler,所以是串行的,也就是说,Handler接到多个message时,就要排队依次处理。
####(4)AIDL
AIDL通过定义服务端暴露的接口,以提供给客户端来调用,AIDL使服务器可以并行处理,而Messenger封装了AIDL之后只能串行运行,所以Messenger一般用作消息传递。
通过编写aidl文件来设计想要暴露的接口,编译后会自动生成响应的java文件,服务器将接口的具体实现写在Stub中,用iBinder对象传递给客户端,客户端bindService的时候,用asInterface的形式将iBinder还原成接口,再调用其中的方法。
####(5)ContentProvider
系统四大组件之一,底层也是Binder实现,主要用来为其他APP提供数据,可以说天生就是为进程通信而生的。自己实现一个ContentProvider需要实现6个方法,其中onCreate是主线程中回调的,其他方法是运行在Binder之中的。自定义的ContentProvider注册时要提供authorities属性,应用需要访问的时候将属性包装成Uri.parse(“content://authorities”)。还可以设置permission,readPermission,writePermission来设置权限。 ContentProvider有query,delete,insert等方法,看起来貌似是一个数据库管理类,但其实可以用文件,内存数据等等一切来充当数据源,query返回的是一个Cursor,可以自定义继承AbstractCursor的类来实现。
####(6)Socket
学过计算机网络的对Socket不陌生,所以不需要详细讲述。只需要注意,Android不允许在主线程中请求网络,而且请求网络必须要注意声明相应的permission。然后,在服务器中定义ServerSocket来监听端口,客户端使用Socket来请求端口,连通后就可以进行通信。