我有我的主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线程上运行?线程之间是否还有其他一些首选的通信方式?
答案 0 :(得分:2)
在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);
答案 1 :(得分:0)
以下方法适用于UI线程
onProgressUpdate
或者您可以创建一个界面并注册活动
答案 2 :(得分:0)
它在UI线程上运行,因为处理程序总是在创建它的线程上执行。在这种情况下,它将是UI线程。
我认为在你的情况下,你真的不需要处理程序。相反,只需在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();