Android死角——回调函数到底执行在主线程还是子线程?

写程序多了,发现回调函数用的越来越多,但是不知道到底回调函数执行在那个线程。

这算我的一个知识死角,写个回调去试试。

下面动手!


首先,我新建了个项目,然后开始写,emmmm…..这也得想想。我水平太差了吧也。

1、定义接口类

public interface CallBackInterface {
    void callbackMethod();
}

2、需要调用回调的类

class CallbackUtil {
    private CallBackInterface callBack;

    public CallbackUtil(CallBackInterface callBackInterface) {
        this.callBack = callBackInterface;
    }

    public void doCallback() {
        long id = Thread.currentThread().getId();
        Log.e("sy", "CallbackUtil类doCallback方法中的线程号:" + id);
        callBack.callbackMethod();
    }
}

3、界面

<Button
        android:text="执行回调"
        android:layout_width="match_parent"
        android:onClick="callBack"
        android:layout_height="wrap_content" />

4、使得MainActivity集成接口类,并且实现接口方法

public class MainActivity extends AppCompatActivity implements CallBackInterface{

    //工具类
    private CallbackUtil callbackUtil;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        callbackUtil = new CallbackUtil(this);
    }

    //实现接口,重写方法
    @Override
    public void callbackMethod() {
        long id = Thread.currentThread().getId();
        Log.e("sy", "MainActivity类callbackMethod方法中的线程号:" + id);
        String s = "回调运行在" + (isMainThread() ? "主线程" : "子线程") + "中";
        Log.e("sy", s);
    }

    //判断当前线程是否是主线程
    public boolean isMainThread() {
        return Looper.getMainLooper().getThread().getId() == Thread.currentThread().getId();
    }

    //按钮点击事件
    public void callBack(View view) {
        long id = Thread.currentThread().getId();
        Log.e("sy", "MainActivity类callBack方法中的线程号:" + id);
        callbackUtil.doCallback();
    }
}

5、测试

这里写图片描述


6、疑问

以上为测试结果,回调函数是运行在函数里的。这时候就有个问题了。

点击按钮,出发回调的这句话

callbackUtil.doCallback();

这句话调用是在主线程中,是不是这个导致的回调函数是在主线程里呢?
我们来试试。

在MainActivity中把这这句话改为在子线程中执行试一试

    public void callBack(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long id = Thread.currentThread().getId();
                Log.e("sy", "MainActivity类callBack方法中的线程号:" + id);
                callbackUtil.doCallback();
            }
        }).start();
    }

这里写图片描述

那如果我们把不修改这句话,而是在CallbackUtil类的doCallback中修改就是这样

class CallbackUtil {
    private CallBackInterface callBack;

    public CallbackUtil(CallBackInterface callBackInterface) {
        this.callBack = callBackInterface;
    }

    public void doCallback() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                long id = Thread.currentThread().getId();
                Log.e("sy", "CallbackUtil类doCallback方法中的线程号:" + id);
                callBack.callbackMethod();
            }
        }).start();
    }
}

这里写图片描述

结果一目了然


6、总结

这么看来。只要有开线程,那么后面的执行全部都是在线程中。

这让我想起来了当时写小程序的时候调用的时候可以把函数名当做参数扔到某个函数里去调用,和今天测试的这个又有什么区别呢?可能只是实现方式不同吧。


7、附加

那么问题来了,我们利用回调函数的时候,大多数情况下是子线程回调刷新UI页面的,子线程中又不能刷新,必须在主线程中完成这个操作,应该这么做呢?

我是这么做的:

在UI界面写一个handler内部类

class UIhandler extends Handler {
        WeakReference<MainActivity> weakReference;

        public UIhandler(MainActivity activity) {
            this.weakReference = new WeakReference<MainActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    break;
                default:
            }
        }
    }

新建内部类

    private UIhandler ihandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        callbackUtil = new CallbackUtil(this);
        ihandler = new UIhandler(this);

    }

在需要主线程执行的地方使用:

ihandler.post(new Runnable() {
            @Override
            public void run() {
                //刷新界面
            }
        });

//或者使用

ihandler.sendEmptyMessage()
ihandler.sendMessage()
等方法
在handleMessage中处理

以上。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值