我有一个从蓝牙设备接收值的Android应用程序。第一次打开Activity
时,一切都很顺畅。 Bluetooth
中的值显示在TextView
。
该应用包含两项活动 - > Main
和Details
(详情包括一些片段)。
在Main
活动中,用户输入ID并按下okay按钮。然后我启动蓝牙线程并使用MAC地址直接连接到蓝牙设备。然后我打开Details
活动。
在Details
活动中,我创建了一个Handler
类,用于将蓝牙设备的值放入文本视图。然后,当按下并且将他重定向回Main
活动时,用户具有是和没有按钮来保存数据库中的值(或不保存)。
第一次发生这种情况,一切都很好。但是第二次打开Details
活动时,句柄不会更新UI
。我无法理解为什么,如果我尝试调试,我可以看到它的工作原理应该 - >处理程序获取值并更新文本视图,但由于某种原因,我无法在UI
中看到它们。
有没有人知道问题可能是什么?
Handle
看起来像这样:
static class MyHandler extends Handler {
private final WeakReference<DetailsFragment> mFragment;
public MyHandler(DetailsFragment fragment) {
mFragment = new WeakReference<>(fragment);
}
@Override
public void handleMessage(Message msg) {
DetailsFragment fragment = mFragment.get();
if (fragment != null) {
String tempValue = (String) msg.obj;
if (tempValue != null && !tempValue.equals("")) {
fragment.updateTextViewValue(tempValue.trim());
}
}
}
}
这是Details
活动中的取消按钮点击:
public void cancelButtonClick() {
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
getActivity().finish();
}
这是蓝牙ConnectedThread
:
public class ConnectedThread extends Thread {
private final int INCOMMING = 1;
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
private final Handler mHandler;
public ConnectedThread(BluetoothSocket socket, Handler handler) {
mmSocket = socket;
mHandler = handler;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams using temp objects, because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
//log exception
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the streams
int bytes = 0; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
buffer[bytes] = (byte) mmInStream.read();
if ((buffer[bytes] == '\n') || (buffer[bytes] == '\r')) {
String value = new String(buffer, 0, bytes);
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(INCOMMING, value).sendToTarget();
bytes = 0;
} else
bytes++;
} catch (IOException ex) {
//log the exception
break;
}
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
// log the exception
}
}
}
我想知道是否可能在我第二次打开Details
活动时,ConnectedThread
和Handler
正在更新旧TextView
,但这是可能的,因为我使用的是WeakReference
?
答案 0 :(得分:1)
您的描述让我觉得您可能有泄漏的活动,然后您的线程会更新一个不再显示的片段。 您可以尝试启动以下命令行:
adb shell dumpsys meminfo <your.app.package>
您会找到结果here的一个很好的解释。 您可以在“对象”部分找到有趣的内容,您可以在其中找到“活动”编号。
您可以参加您的详细信息活动,返回主要活动,再转到详细信息等... 活动数量应保持稳定。如果它增加,您的活动可能会泄漏。
从那里,你应该寻找保留的视图/片段(我可以看到你的处理程序中有一个WeakReference,所以你知道如何修复它)
此处,Memory Monitor和Allocation Tracker等分析工具肯定会有所帮助,但需要一些时间才能理解。
答案 1 :(得分:1)
假设您实际上更新 Handler
的{{1}},问题不在于“为什么UI不会更新?”而是“如何 UI更新?”
您需要更新帖子的ConnectedThread
成员:
mHandler
然后添加
public void setHandler( MyHandler newHandler ) {
mHandler = newHandler;
}
到您的片段的connectedThread.setHandler( new MyHandler( this ) );
事件。
根据您遇到的流量,事件总线可能是更好的实施方式。
答案 2 :(得分:0)
好的,我认为我做对了,当我重定向回ConnectThread
时,我只需要取消ConnectedThread
和MainActivity
。这解决了我的问题。令人尴尬,但我仍然是初学者。
但是,我想我仍然有泄漏活动的问题。但这是我将继续与之抗争的另一个话题。