android使用ExecutorService来处理子线程与UI线程的通讯问题

android使用ExecutorService来处理子线程与UI线程的通讯问题


写在前面

对于android,为了不阻塞主线程UI的绘制,主线程中不允许有耗时操作,例如网络请求等。如果遇到网络请求,就需要开启子线程去处理请求,子线程得到结果后,再通知主线程更新UI,这就涉及到了android的异步线程处理机制Handler,很多大神对这一块都讲得很透彻了,本文不多赘述。
最近遇到一个需求,需要把子线程定义到方法中,子线程的结果需要作为方法返回值return出来。这样,handler机制实现起来就比较麻烦了。查了一些资料,终于得到了一种解决办法,就是利用ExecutorService来处理子线程和主线程之间的通讯,实现起来比较简单,调用代码很简洁。
废话不多说了,下边写一个demo看看简要的实现过程:

Demo

主要涉及到3个java类,ExecutorService,Callable,Future
ExecutorService是线程池或者叫任务执行者,用来管理分配线程执行任务
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.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的,这就达到目的了
返回值是json字符串

总结

使用线程池来处理子线程与主线程之间的通讯,可以使主线程的调用代码简洁明了,也可以定义本地接口,方便第三方调用得到返回值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值