蓝牙线程/处理程序不更新 UI
Bluetooth thread / Handler doesn't update the UI
我有一个 android 应用程序可以从蓝牙设备接收值。我第一次打开 Activity
时,一切都运行顺畅。 Bluetooth
中的值显示在 TextView
.
中
该应用程序包含两个活动 --> Main
和 Details
(详细信息包括一些片段)。
在 Main
activity 中,用户输入一个 ID 并按下确定按钮。然后我启动蓝牙线程并使用 MAC 地址直接连接到蓝牙设备。然后我打开Details
activity。
在 Details
activity 中,我制作了一个 Handler
class 将值从蓝牙设备放入文本视图。然后用户有是和没有按钮在数据库中保存值(或不保存),按下时他被重定向回 Main
activity.
第一次出现这种情况时,一切正常。但是 Details
activity 第二次打开时,句柄不会更新 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
activity中的取消按钮点击:
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
activity 时,ConnectedThread
和 Handler
是否正在更新旧的 TextView
,但这是可能的,因为我使用的是 WeakReference
?
你的描述让我觉得你可能有一个泄漏 activity,然后你的线程会更新一个不再显示的片段。
您可以尝试启动以下命令行:
adb shell dumpsys meminfo <your.app.package>
你会发现对结果的很好解释here。
您感兴趣的是 "Objects" 部分,您会在其中找到一个 "Activities" 数字。
你可以去你的细节activity,回到主要的,再去细节,等等......
活动数量应保持稳定。如果它增加,您的 activity.
可能有泄漏
从那里,您应该寻找保留的视图/片段(我可以看到您的处理程序中有一个 WeakReference,所以您知道如何修复它)
这里,Memory Monitor and the Allocation Tracker 之类的分析工具肯定会有所帮助,但要理解它们需要一些时间。
假设您实际上没有更新 ConnectedThread
的Handler
,问题不是"why doesn't the UI update?",而是, "how could the UI update?"
您需要更新话题的 mHandler
成员:
public void setHandler( MyHandler newHandler ) {
mHandler = newHandler;
}
然后添加
connectedThread.setHandler( new MyHandler( this ) );
到您片段的 onActivityCreated()
事件。
根据您遇到的流量,事件总线可能是更好的实现方式。
好的,我想我做对了,当我重定向回 MainActivity
时,我只需要取消 ConnectThread
和 ConnectedThread
。这解决了我的问题。尴尬,但我还是个初学者。
但是,我想我仍然对泄露的活动有疑问。但这是我将继续与之抗争的另一个话题。
我有一个 android 应用程序可以从蓝牙设备接收值。我第一次打开 Activity
时,一切都运行顺畅。 Bluetooth
中的值显示在 TextView
.
该应用程序包含两个活动 --> Main
和 Details
(详细信息包括一些片段)。
在 Main
activity 中,用户输入一个 ID 并按下确定按钮。然后我启动蓝牙线程并使用 MAC 地址直接连接到蓝牙设备。然后我打开Details
activity。
在 Details
activity 中,我制作了一个 Handler
class 将值从蓝牙设备放入文本视图。然后用户有是和没有按钮在数据库中保存值(或不保存),按下时他被重定向回 Main
activity.
第一次出现这种情况时,一切正常。但是 Details
activity 第二次打开时,句柄不会更新 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
activity中的取消按钮点击:
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
activity 时,ConnectedThread
和 Handler
是否正在更新旧的 TextView
,但这是可能的,因为我使用的是 WeakReference
?
你的描述让我觉得你可能有一个泄漏 activity,然后你的线程会更新一个不再显示的片段。 您可以尝试启动以下命令行:
adb shell dumpsys meminfo <your.app.package>
你会发现对结果的很好解释here。 您感兴趣的是 "Objects" 部分,您会在其中找到一个 "Activities" 数字。
你可以去你的细节activity,回到主要的,再去细节,等等...... 活动数量应保持稳定。如果它增加,您的 activity.
可能有泄漏从那里,您应该寻找保留的视图/片段(我可以看到您的处理程序中有一个 WeakReference,所以您知道如何修复它)
这里,Memory Monitor and the Allocation Tracker 之类的分析工具肯定会有所帮助,但要理解它们需要一些时间。
假设您实际上没有更新 ConnectedThread
的Handler
,问题不是"why doesn't the UI update?",而是, "how could the UI update?"
您需要更新话题的 mHandler
成员:
public void setHandler( MyHandler newHandler ) {
mHandler = newHandler;
}
然后添加
connectedThread.setHandler( new MyHandler( this ) );
到您片段的 onActivityCreated()
事件。
根据您遇到的流量,事件总线可能是更好的实现方式。
好的,我想我做对了,当我重定向回 MainActivity
时,我只需要取消 ConnectThread
和 ConnectedThread
。这解决了我的问题。尴尬,但我还是个初学者。
但是,我想我仍然对泄露的活动有疑问。但这是我将继续与之抗争的另一个话题。