android使用ExecutorService来处理子线程与UI线程的通讯问题
2016-07-12 14:26
591 查看
android使用ExecutorService来处理子线程与UI线程的通讯问题
写在前面
对于android,为了不阻塞主线程UI的绘制,主线程中不允许有耗时操作,例如网络请求等。如果遇到网络请求,就需要开启子线程去处理请求,子线程得到结果后,再通知主线程更新UI,这就涉及到了android的异步线程处理机制Handler,很多大神对这一块都讲得很透彻了,本文不多赘述。最近遇到一个需求,需要把子线程定义到方法中,子线程的结果需要作为方法返回值return出来。这样,handler机制实现起来就比较麻烦了。查了一些资料,终于得到了一种解决办法,就是利用ExecutorService来处理子线程和主线程之间的通讯,实现起来比较简单,调用代码很简洁。
废话不多说了,下边写一个demo看看简要的实现过程:
Demo
主要涉及到3个java类,ExecutorService,Callable,FutureExecutorService是线程池或者叫任务执行者,用来管理分配线程执行任务
Callable<>是一个接口,类似于 Runnable,只有一个有返回值的方法call(),返回的是call的处理结果,泛型是指返回结果的类型
Future是要执行的任务对象,用来具体执行callable中的任务
xml界面
界面很简单,一个button,一个textview<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@android:color/white" android:text="Hello World!" android:id="@+id/result"/> <Button android:layout_width="match_parent" android:layout_height="40dp" android:text="获取网络数据" android:background="@android:color/holo_blue_light" android:textColor="@android:color/white" android:id="@+id/getData"/> </LinearLayout>
定一个类,实现callable接口,并且重写call方法
call方法中写子线程要执行的动作public class GetResult implements Callable<String>{ //重写的call方法 @Override public String call() throws Exception { //这里我们做一个post请求 return HttpPost.getRequestData(map,url); } }
调用callable过程
//创建线程池 ExecutorService pool = Executors.newCachedThreadPool(); //通过submit得到具体执行 call方法的Future任务处理对象 Future f1 = pool.submit(new GetResult()); //调用get()进行任务处理,并得到处理结果 String r=(String)f1.get();
为了方便调用,我们将GetResult类完善一下
定义一个static方法,来获取post请求结果,以便日后调用public class GetResult implements Callable<String>{ //post请求的参数 private Map<String,String> map=new HashMap<>(); //post请求的接口地址 private String url; //创建static线程池 //Executors还有多种new线程池的方法,可以参看API根据需要来用 private static ExecutorService pool = Executors.newCachedThreadPool(); //私有构造方法,初始化参数 private GetResult(Map<String,String> map,String url){ this.map=map; this.url=url; } //重写的call方法 @Override public String call() throws Exception { return HttpPost.getRequestData(map,url); } //静态方法,用于处理post请求,并返回处理结果 public static String getResult(Map<String, String> map, String url) { GetResult getResult=new GetResult(map,url); Future f1 = pool 4000 .submit(getResult); String r=null; try { r= (String)(f1.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } return r; } }
Activity调用
public class MainActivity extends Activity{ private TextView result; private Button getData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化UI result=(TextView) findViewById(R.id.result); getData=(Button) findViewById(R.id.getData); //参数map Map<String,String> map=new HashMap<>(); map.put("menu","秘制红烧肉"); map.put("key","************************"); //接口url String url="http://apis.juhe.cn/cook/query.php"; //设置点击事件,点击获取网络数据 getData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //调用自定义方法,得到网络请求数据,并更新UI界面,是不是很简洁 String r=GetResult.getResult(map,url); result.setText(r); } }); } }
结果截图:
至此,调用就结束了,看看返回结果,是json字符串,由于没有注册app到该接口网站,所以服务器返回值说我的应用审核超时,但是至少说明我们请求网络数据的动作是OK的,这就达到目的了总结
使用线程池来处理子线程与主线程之间的通讯,可以使主线程的调用代码简洁明了,也可以定义本地接口,方便第三方调用得到返回值相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件