Android上子线程处理UI更新内容方案

1.简述

子线程里面进行逻辑运算,较耗时(里面有数据采集、滤波、计算等),需要在结果完毕 后通知UI线程进行更新数据,展示给用户看。(实例demo:后台计算GPS测量跑步距离,UI上 显示跑步距离和提醒用户GPS的一些状态)

2.方案简述

新增加一个interface,这个interface里面进行,定义一个状态变更函数接口。 在业务处理里面,进行处理,也就是何时触发,何种操作,UI线程里面,进行刷新 展示内容。

2.1 接口定义
public interface GPSCalculateStatusListener {
    /**
     * 状态变更,通知处理(key value--方便UI线程里面区分消息和消息值)
     */
    void onStatusChanged(String key, Object value);
}
2.2 业务里面处理

业务里面,要提供注册、注销观察Listener(防止异常、内存泄漏)

/**
     * 注册监听器,UI里面注册调用
     */
    public void registerListener(GPSCalculateStatusListener listener) {
        listeners.add(listener);
    }

    /**
     * 注销监听器,UI里面注销-destory时
     */
    public void unregisterListener(GPSCalculateStatusListener listener) {
        listeners.remove(listener);
    }

    /**
     * 状态变量后,通知所有的listeners进行处理,在业务里面完成
     */
    private void notifyListenerChanged(String key,Object value) {
        for (GPSCalculateStatusListener listener : listeners) {
            listener.onStatusChanged(key, value);
        }
    }

    //判断处理逻辑-----伪代码,实际处理,自行注意
    if(condition == true){
     notifyListenerChanged("key_name", key_value);//不同的消息类型
    }

3.UI线程(监听者,进行使用)

因为这里是刷新控件等,发生变化后,回调,使用post会UI线程执行

public class gpsActivity extends Activity implements OnClickListener, GPSCalculateStatusListener {//增加这个监听接口

    @Override
    protected void onCreate(Bundle savedInstanceState) {
     //伪代码
      mGPSCalculateDistance.registerListener(this);
  }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
       //注销listener
        mGPSCalculateDistance.unregisterListener(this);
    }

    //扔到UI线程里面执行,刷新控件,比如:某个传感器的数值
    @Override
    public void onStatusChanged(final String key, final Object value) {

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 更新 UI
                switch (key) {
                    case "key_val1":
                        if (value instanceof Number) {
                            int dis = ((Number) value).intValue();
                            textlabel.setText("UI更新: " + (int)dis + " m");
                        }
                        break;
                    case "key_val2":
                        if (value instanceof Boolean) {
                            if((Boolean)value == true) {
                                Toast.makeText(gpsActivity.this, "key_val2", Toast.LENGTH_SHORT).show();
                            }
                        }

                        break;
                }
            }
        });

    }
}

4.总结

  • 1)对于需要后台计算量,这个方式较好,不能UI里面做大量运算,ANR!!
  • 2)后台计算给果,计算后,通过listener,UI自动更新,比如后台数据采集,前端 UI进行更新,不需要前端实时刷新。