小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
Android 异步方法以同步方式进行
我们一般在主线程创建子线程的时候,子线程启动之后,主线程会接着往下执行,当子线程执行完毕之后就会有接口回调,回调到主线程,主线程再去处理结果。该篇文章讲解如何使用阻塞方法,直接就可以得到返回值。
一、线程返回值的两种不同思想
为了更直观的表达,参考流程图,正常的接口回调是这样的。
接口回调伪代码:
new Thread(new TestTask(new TestTask.Callback() {
@Override
public void onDown() {
// todo 处理完毕
}
})).start();
阻塞方法伪代码:
private String getData(){
return blockThread();
}
那么这两种方法有什么不同呢?
第一种接口回调的方法不会影响主线程,但需要接口回调,在接口回到中切换到主线程进行更新;
第二种阻塞的方法会影响主线程,所以需要再开一个子线程中进行操作,由于直接就可以拿到返回值,所以代码的逻辑可读性会大大的增强。
查看一些第三方框架的源码,在mina通讯的框架中的连接方法则是使用的阻塞方法。
ConnectFuture future = connector.connect(new InetSocketAddress(host, port));
future.awaitUninterruptibly();
二、怎么实现阻塞方法
1. FutureTask作用
FutureTask 来自java。
一种可取消的异步计算。此类提供了Future的基本实现,其中包含启动和取消计算、查询以查看计算是否完成以及检索计算结果的方法。只有在计算完成后才能检索结果;如果计算尚未完成,get方法将阻塞。
2. 实现方式一
直接使用
为了不阻塞主线程,我们在线程中另开线程,对android来说,是允许这样操作的,因为阻塞方法阻塞的时长不一定。
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
String data = getData(i);
Log.e("===", "isMainThread:" + HandlerUtils.isMainThread() + " data:" + data);
}
}
}).start();
}
private String getData(int i) {
try {
FutureTask<String> task = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000);
Log.e("===", "isMainThread:" + HandlerUtils.isMainThread());
return "iii:" + i;
}
});
new Thread(task).start();
return task.get();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Exception");
}
}
}
2. 实现方式二
自定义类实现Callable接口
CallableThread 类
import android.util.Log;
import java.util.concurrent.Callable;
class CallableThread implements Callable<String> {
int mIndex;
public CallableThread(int i) {
this.mIndex = i;
}
@Override
public String call() throws Exception {
Thread.sleep(2000);
Log.e("===", "isMainThread:" + HandlerUtils.isMainThread());
return "iii" + mIndex;
}
}
MainActivity 类
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.concurrent.FutureTask;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
String data = getData(i);
Log.e("===", "isMainThread:" + HandlerUtils.isMainThread() + " data:" + data);
}
}
}).start();
}
private String getData(int i) {
try {
CallableThread callableThread = new CallableThread(i);
FutureTask<String> task1 = new FutureTask<String>(callableThread);
new Thread(task1).start();
return task1.get();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Exception");
}
}
}