时间:2021-01-21 10:54:07 | 栏目:Android代码 | 点击:次
Android强制异步转同步方法,供大家参考,具体内容如下
Android系统中规定耗时任务需要在异步线程中进行,特别是网络请求必须在异步线程中进行否则会抛出NetworkOnMainThreadException,但是在一些特殊的情况我们需要保证在获得到网络请求结果之后在进行余下操作,这时候便需要在UiThread中进行相关操作。
这样就需要用到线程阻塞的原理,这里可以借助Callable或FutureTask来实现。
public static String getSyncBusiness(final String url){ try { FutureTask<String> task = new FutureTask<String>(new Callable<String>() { @Override public String call() throws Exception { URL u = new URL(url); HttpURLConnection connection = (HttpURLConnection) u.openConnection(); connection.setDoInput(true); connection.setRequestMethod("GET"); connection.connect(); InputStream in = connection.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf8")); final StringBuilder sb = new StringBuilder(); String line = null; while((line = br.readLine())!=null){ sb.append(line); } return sb.toString(); } }); new Thread(task).start(); return task.get(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("网络访问错误"); } }
FutureTask接口是一个泛型接口,可以设置需要返回的类型,并且可以看出该方法为了方便程序员的操作,巧妙的通过抛出一个总Exception来保证方法统一执行统一判断,类似于RxJava的Exception机制。并且通过源码可以看出,该接口实现了RunnableFuture<>接口,而RunnableFuture接口又继承于Runnable这也就解释了为什么可以直接在new Thread中传入Task对象。
可以理解为FuturTask通过实现Runnable对子线程进行驱动,进行异步的网络请求等操作,但是并没有进行异步并发操作,而是同时阻塞了UI线程,直到该子线程执行完毕。
除了以上还可以直接使用Callable接口,需要注意,Callable需要线程池ExecutorService才可以进行驱动。
public static String getSyncBusiness2(final String url){ try { Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { URL u = new URL(url); HttpURLConnection connection = (HttpURLConnection) u.openConnection(); connection.setDoInput(true); connection.setRequestMethod("GET"); connection.connect(); InputStream in = connection.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf8")); final StringBuilder sb = new StringBuilder(); String line = null; while((line = br.readLine())!=null){ sb.append(line); } return sb.toString(); } }; ExecutorService exec = Executors.newFixedThreadPool(1); Future<String> task = exec.submit(callable); return task.get(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("网络访问错误"); } }
由于原理终归是对UI线程进行了阻塞,所有非特别需要不推荐使用,阻塞时间过长同样会触发ANR。