Android多线程同步转异步方法总结
//实现网络传输,要求:【线程同步转异步】在子线程完成数据上报,当前调用线程必须等待"子线程"返回的结果后,才继续向下执行,返回 response byte数组。
一、归纳总结
1. Thread\Handler + Callback
2. Thread\LooperHandler + FutureTask
3. AsyncTask
二、引子
Android之NetworkOnMainThreadException异常
看名字就应该知道,是网络请求在MainThread中产生的异常
三、详细介绍及示例
1. Thread\Handler + Callback (无阻塞结果返回)
说明:通过Callback回调结果,只切换线程了;未进行线程同步转异步后的结果阻塞返回。
private final static Handler mLooperHandler; static { HandlerThread handlerThread = new HandlerThread("BackgroundHandler"); handlerThread.start(); mLooperHandler = new Handler(handlerThread.getLooper()); } public static void login(final String code, final LoginCallback<UserInfo> cb) { mLooperHandler.post(new Runnable() { @Override public void run() { final UserInfo userInfo = loginAsync(code); Handler mainHandler = new Handler(Looper.getMainLooper()); mainHandler.post(new Runnable() { @Override public void run() { //已在主线程中,可以更新UI cb.onResult(userInfo); } }); } }); }
2. Thread\LooperHandler + FutureTask
public static byte[] networkTransport(byte datas[]) { final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式 String date = df.format(new Date());// new Date()为获取当前系统时间,也可使用当前时间戳 System.out.println("networkTransport thread=" + Thread.currentThread().getName() + " task datas=" + datas + " entry date=" + df.format(new Date())); final byte[] arrByte = datas; FutureTask<byte[]> task = new FutureTask<byte[]>((Callable<byte[]>) () -> { System.out.println("networkTransport thread=" + Thread.currentThread().getName() + " task datas=" + arrByte + " inThreadTask date=" + df.format(new Date())); Thread.sleep(2 * 1000); return arrByte; }); new Thread(task, "do").start(); byte[] outArrByte = new byte[0]; try { outArrByte = task.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } System.out.println("networkTransport thread=" + Thread.currentThread().getName() + " task datas=" + datas + " postThreadTaskGet date=" + df.format(new Date())); return outArrByte; }
说明:new Thread(task, "do").start();换成mLooperHandler.post(new Runnable() {…});亦可。
3. AsyncTask
说明:即可通过Callback回调结果,也可线程同步转异步后的结果阻塞返回。
public static byte[] httpGet(final String url) { Log.i(TAG, "httpGet foreground thread=" + Thread.currentThread().getName() + " url=" + url); AsyncTask<String, Void, byte[]> asyncTask = new AsyncTask<String, Void, byte[]>() { @Override protected byte[] doInBackground(String... strings) { Log.i(TAG, "httpGet background thread=" + Thread.currentThread().getName() + " url=" + strings[0]); byte[] arrByte = httpGetAsync(strings[0]); return arrByte; } @Override protected void onPostExecute(byte[] result) { Log.i(TAG, "httpGet foreground thread=" + Thread.currentThread().getName() + " result=" + result); } }; asyncTask.execute(url); //asyncTask.executeOnExecutor(url); try { byte[] arrByte = (byte[]) asyncTask.get(); Log.i(TAG, "httpGet foreground thread=" + Thread.currentThread().getName() + " arrByte=" + arrByte); return arrByte; } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } return null; }
欢迎大家讨论,提供新思路新解决方案。