我有我的主UI,我有一个AsyncTask运行。我想与AsyncTask通信,让它在非ui线程上运行一些东西。所以我试着做的是:
protected class WifiMon extends AsyncTask<Context, Integer, String>
{
Context parent;
CoexiSyst coexisyst;
private static final String WIMON_TAG = "WiFiMonitor";
private int PCAP_HDR_SIZE = 16;
private int _scan_pkts_left;
public Handler _handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// We invoke a scan, and then read in all of the packets
// captured from the scan.
if(msg.obj == ThreadMessages.WIFI_SCAN_START) {
Log.d(TAG, "Got message to start Wifi scan");
int start_rxpkts = getRxPacketCount();
runCommand("/data/data/com.gnychis.coexisyst/files/iw dev wlan0 scan");
_scan_pkts_left = getRxPacketCount() - start_rxpkts;
Log.d(TAG, "Finished Wifi scan");
}
}
};
...
}
然而,似乎当传入消息进来时,handleMessage()实际上在UI线程中运行。我知道这一点,因为runCommand()阻塞了5秒,我的UI最终无响应了5秒。
为什么handleMessage()不在非ui线程上运行?线程之间是否有其他更好的通信方式?
创建doInBackground()
方法中的处理程序对象。
或
如果处理程序独立于Aysnctask,则可以将其放在单独的线程中。
mHandlerThread = new HandlerThread("some_name");
mHandlerThread.start();
/* we need to wait to get the looper instance */
while(!mHandlerThread.isAlive()) {};
mHandler = new Handler(mHandlerThread.getLooper(), null);
下面的方法在UI线程
中工作onProgressUpdate
或者您可以创建一个接口并注册事件
它运行在UI线程上,因为处理程序总是在创建它的线程上执行。在这种情况下,它将是UI线程。
我认为在你的情况下,你并不真的需要handler。相反,只需在WifiMon
任务中设置一些标志或适当的数据结构。从现在调用处理程序的任何位置设置此标志和所需参数(当然,要使用适当的保护)。如果你想让它和任务本身在同一个线程中执行,你必须在某个时候中断doInBackground
的主逻辑,在这一点上,只要检查你的标志。
如果你想要另一个线程,只需引入一个方法来启动它。例如:
protected class WifiMon extends AsyncTask<Context, Integer, String>
{
public void startScan() {
Thread t = new Thread() {
public void run() {
// Scan here and read/update properties of WifiMon
}
};
t.start();
}
}
而不是
wifimon._handler.post(...);
使用wifimon.startScan();