写程序多了,发现回调函数用的越来越多,但是不知道到底回调函数执行在那个线程。
这算我的一个知识死角,写个回调去试试。
下面动手!
首先,我新建了个项目,然后开始写,emmmm…..这也得想想。我水平太差了吧也。
public interface CallBackInterface {
void callbackMethod();
}
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();
}
}
<Button
android:text="执行回调"
android:layout_width="match_parent"
android:onClick="callBack"
android:layout_height="wrap_content" />
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();
}
}
以上为测试结果,回调函数是运行在函数里的。这时候就有个问题了。
点击按钮,出发回调的这句话
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();
}
}
结果一目了然
这么看来。只要有开线程,那么后面的执行全部都是在线程中。
这让我想起来了当时写小程序的时候调用的时候可以把函数名当做参数扔到某个函数里去调用,和今天测试的这个又有什么区别呢?可能只是实现方式不同吧。
那么问题来了,我们利用回调函数的时候,大多数情况下是子线程回调刷新UI页面的,子线程中又不能刷新,必须在主线程中完成这个操作,应该这么做呢?
我是这么做的:
在UI界面写一个handler内部类
class UIhandler extends Handler {
WeakReference weakReference;
public UIhandler(MainActivity activity) {
this.weakReference = new WeakReference(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中处理
以上。