安卓使用回调的方法进行线程间通讯

0.背景

 

        网上关于安卓线程间通讯的文章多如牛毛,以子线程和UI线程为例,我所看到的所有文章都是使用Handler进行通讯,这种方法是非常好的,但是不能应对所有的情况。

        问题是这样的,如果我写了一个MainActivity.java,但是我的子线程没有写在这个文件里,而是单独写到了SendThread.java中。那么,在这种情况下二者没有办法共用同一个mHandler,就造成了网上其他文章的方法不适用的情况。

1.View点击事件的相关源码

在阅读相关源码前,先看一下一个很简单的按钮点击事件的实现:

sendButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //TODO:do something
    }
});

这里面涉及到两段,一个是setOnClickListener(OnClickListener l),一个是View中的OnClickListener()。代码如下:

    /**
     * Register a callback to be invoked when this view is clicked. If this view is not
     * clickable, it becomes clickable.
     *
     * @param l The callback that will run
     *
     * @see #setClickable(boolean)
     */
    public void setOnClickListener(@Nullable OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }



    /**
     * Interface definition for a callback to be invoked when a view is clicked.
     */
    public interface OnClickListener {
        /**
         * Called when a view has been clicked.
         *
         * @param v The view that was clicked.
         */
        void onClick(View v);
    }

这两段代码都写在了View.java中,这样一来就很明了了,实现一个监听点击的接口,重写其中的点击函数,这样就可以实现回调的功能。

仿照这种写法,我们也可以在线程间通讯时运用相似的思想。

2.核心代码展示

UI线程:

public class MainActivity extends AppCompatActivity {

    private TextView recvTextView;
    private Button sendButton;
    private SendThread mSendThread = new SendThread();
    private Handler mHandler;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        uiInit();
        
        //设置接口回调函数
        mSendThread.setCallback(new SendThread.onDataChangeListener() {
            @Override
            public void dataChange(Message msg) {
                Message mMsg = Message.obtain();
                mMsg = msg;
                mHandler.sendMessage(mMsg);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();

        //接收msg
        mHandler = new Handler() {
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 1:
                        Toast.makeText(MainActivity.this,""+msg.arg1,Toast.LENGTH_SHORT).show();
                        recvTextView.setText((String)msg.obj);
                        break;
                    default:
                        Toast.makeText(MainActivity.this,"default",Toast.LENGTH_SHORT).show();
                        break;
                }
            }
        };

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //启动子线程
                mSendThread.start();
            }
        });
    }

    public void uiInit() {
        recvTextView = findViewById(R.id.recvTextView);
        sendButton = findViewById(R.id.sendButton);
    }
    
}

子线程:

public class SendThread extends Thread {

    //实例化监听器
    private static onDataChangeListener mDataChangeListener = null;

    //回调接口
    public interface onDataChangeListener {
        void dataChange(Message msg);
    }

    //设置监听器
    public void setCallback(onDataChangeListener o) {
        mDataChangeListener = o;
    }

    //数据发生变化时,子线程调用这个函数
    private static void onDataChanged(Message msg) {
        if (mDataChangeListener != null) {
            mDataChangeListener.dataChange(msg);
        }
    }


    public void run() {
        Message msg = Message.obtain();
        msg.what = 1;
        msg.arg1 = 123;
        msg.obj = "SendThread发来信息";
        onDataChanged(msg);
    }
}

3.实现的效果

当我点击一个按钮时,它会启动一个子线程,刷新了UI中的一个TextView同时打了一个Toast显示123。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值