Android:创建新线程会调用 onResume?
我想这是一个更通用的问题,但我的 Android 程序似乎在这两个与线程创建相关的函数调用之间的主 UI 线程中调用 onResume 。这会导致我不希望发生的其他调用,到目前为止,我发现的唯一解决方法是设置全局标志(我不喜欢,并且在我看来这是不好的编程实践)。它看起来就像这样:
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
不知何故,在这些调用之间(由 BluetoothCommHandler 对象从 UI 线程进行),onResume 被调用。如果有人能给我指出何时触发 onResume 和其他活动生命周期事件的良好来源,我将非常感激。此外,我检查了这一点: http://developer.android.com/reference/android /app/Activity.html,它似乎没有任何我能找到的提示。
最后一点 - onResume 总是在这两个命令被调用之间被调用,这让我认为这并不是真正的线程切换问题。
我还刚刚注意到 onResume 被调用为一对早被调用的 onPause - 但仍然不知道为什么它恰好发生在这两个函数调用之间。
编辑:代码包含在下面。
蓝牙处理程序对象的调用:
mBComm = new BluetoothCommHandler(this, mHandler);
主 UI 线程中的 onResume 函数(mNoRestartFlag
是为了仅在我想要的时候调用该特定位。它不是我在上面提到的标志 - 它处理另一种情况,我在这里不讨论):
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent,
mFilters, mTechLists);
Log.i(TAG, "OnResume called.");
if(mBComm != null && !mNoRestartFlag) {
mBComm.start();
}
}
AndroidManifest 中的 Activity OptionsHandler (与 DeviceListActivity 相同)声明(请注意,它是一个 Theme.Dialog 样式的活动,弹出在UI 线程,导致我上面提到的 onPause):
activity android:name=".OptionsHandler"
android:label="@string/select_device"
android:theme="@android:style/Theme.Dialog"
android:configChanges="orientation|keyboardHidden" />
创建实际的 connectThread:
public synchronized void connect(BluetoothDevice bd) {
Log.i(TAG, "connect called from inside BluetoothCommHandler");
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
}
ConnectThread 的创建和运行(mDontKill
标志 IS 是我的标志上面提到我用来绕过 onResume 症状):
public ConnectThread(BluetoothDevice bd) {
Log.i(TAG, "created ConnectThread");
mBD = bd;
BluetoothSocket bs = null;
try {
bs = mBD.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.i(TAG, "Could not create an RFCOMM socket!", e);
}
mBS = bs;
if (mBS != null) Log.i(TAG, "BluetoothSocket acquired");
else Log.i(TAG, "BluetoothSocket null!");
mDontKillFlag = true;
}
public void run() {
Log.i(TAG, "BEGIN ConnectThread");
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
mDontKillFlag = false;
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mBS.connect();
Log.i(TAG, "Connected to BluetoothDevice");
} catch (IOException e) {
Log.i(TAG, e.toString());
// Close the socket
try {
mBS.close();
} catch (IOException e2) {
Log.i(TAG, "unable to close RFCOMM socket", e2);
}
Log.i(TAG, "About to call connectionFailed");
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommHandler.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mBS, mBD);
}
导致问题的实际 start() 函数:
public synchronized void start() {
if (D) Log.i(TAG, "start called from inside BluetoothCommHandler");
// Cancel any thread attempting to make a connection
if (mConnectThread != null && !mDontKillFlag)
{mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
if (mConnectedThread != null)
{mConnectedThread.cancel(); mConnectedThread = null;}
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
}
Legend: mBS
是一个成员变量,它是一个 BluetoothSocket 和 < code>mDB是一个成员变量,它是一个BluetoothDevice。
总结,我在 UI 线程上创建一个 BluetoothCommHandler 对象,它尝试创建一个 ConnectThread,然后在蓝牙套接字上调用accept() 命令时,它失败了,因为该对象的 cancel() 函数线程已被调用(它只是有一个关闭套接字的 try-catch)。此取消是从上面列出的 start() 函数调用的,该函数由 onResume 函数调用。 onResume 是 onPause 的补充,onPause 是由于主 UI 活动上出现选择器对话框而被调用的。这个 onResume 似乎总是在我提到的预编辑的前两行代码之间被调用。我试图弄清楚为什么它总是恰好发生在那里,这样我就可以在不关闭套接字的情况下发生accept()。
I guess this is a more generic question, but my Android program seems to call onResume in the main UI thread in between these two thread-creation-related function calls. This causes other invocations that I don't want to happen, and so far the only way around it that I've found is setting global flags (which I don't like, and is bad programming practice in my opinion). It looks rather like this:
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
Somehow, in between these calls (which are made from the UI thread by a BluetoothCommHandler object), onResume gets called. If anyone could point me to a good source of when onResume and other activity lifecycle events are triggered, I would be much obliged. Further, I checked this: http://developer.android.com/reference/android/app/Activity.html, and it didn't seem to have any hints that I could find.
A last note - the onResume ALWAYS gets called in between those two commands getting called, and that makes me think it's not really a thread-switching issue.
I've also just noticed that the onResume gets called as the pair of an onPause that gets called WAY earlier - still no idea why it happens precisely between these two function calls though.
EDIT: Code is included below.
Invocation of the bluetooth handler object:
mBComm = new BluetoothCommHandler(this, mHandler);
The onResume function in the main UI thread (the mNoRestartFlag
is so that this particular bit gets called only when I want it to. It's NOT the flag I'm referring to above - it handles another case that I'm not speaking about here):
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent,
mFilters, mTechLists);
Log.i(TAG, "OnResume called.");
if(mBComm != null && !mNoRestartFlag) {
mBComm.start();
}
}
Activity OptionsHandler (same as DeviceListActivity) declaration in the AndroidManifest (note that it's a Theme.Dialog styled activity, which pops on top of the UI thread, causing the onPause I've referred to above):
activity android:name=".OptionsHandler"
android:label="@string/select_device"
android:theme="@android:style/Theme.Dialog"
android:configChanges="orientation|keyboardHidden" />
The actual connectThread gets created:
public synchronized void connect(BluetoothDevice bd) {
Log.i(TAG, "connect called from inside BluetoothCommHandler");
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
mConnectThread = new ConnectThread(bd);
mConnectThread.start();
}
The creation and running of the ConnectThread (the mDontKill
flag IS the flag I am mentioning above that I use to bypass the onResume symptoms):
public ConnectThread(BluetoothDevice bd) {
Log.i(TAG, "created ConnectThread");
mBD = bd;
BluetoothSocket bs = null;
try {
bs = mBD.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.i(TAG, "Could not create an RFCOMM socket!", e);
}
mBS = bs;
if (mBS != null) Log.i(TAG, "BluetoothSocket acquired");
else Log.i(TAG, "BluetoothSocket null!");
mDontKillFlag = true;
}
public void run() {
Log.i(TAG, "BEGIN ConnectThread");
// Always cancel discovery because it will slow down a connection
mBluetoothAdapter.cancelDiscovery();
mDontKillFlag = false;
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mBS.connect();
Log.i(TAG, "Connected to BluetoothDevice");
} catch (IOException e) {
Log.i(TAG, e.toString());
// Close the socket
try {
mBS.close();
} catch (IOException e2) {
Log.i(TAG, "unable to close RFCOMM socket", e2);
}
Log.i(TAG, "About to call connectionFailed");
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothCommHandler.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mBS, mBD);
}
The actual start() function that causes the issues:
public synchronized void start() {
if (D) Log.i(TAG, "start called from inside BluetoothCommHandler");
// Cancel any thread attempting to make a connection
if (mConnectThread != null && !mDontKillFlag)
{mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
if (mConnectedThread != null)
{mConnectedThread.cancel(); mConnectedThread = null;}
if (mAcceptThread == null) {
Log.i(TAG, "Creating an AcceptThread");
mAcceptThread = new AcceptThread();
mAcceptThread.start();
}
}
Legend: mBS
is a member variable that is a BluetoothSocket and mDB
is a member variable that is a BluetoothDevice.
To summarize, I create a BluetoothCommHandler object on the UI Thread, this tries to create a ConnectThread and then while calling the accept() command on a bluetooth socket, it fails because the cancel() function for the thread has been called (that simply has a try-catch that closes the socket). This cancel is called from the start() function that is listed above, that is called by the onResume function. The onResume is the complement of the onPause that is getting called because of a selector dialog appearing over the main UI activity. This onResume seems to always get called in between the first two lines of code that I mentioned pre-EDIT. I'm trying to figure out why it always happens exactly THERE, so that I can have an accept() occur without the socket being closed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论