蓝牙线程/处理程序不更新 UI

Bluetooth thread / Handler doesn't update the UI

我有一个 android 应用程序可以从蓝牙设备接收值。我第一次打开 Activity 时,一切都运行顺畅。 Bluetooth 中的值显示在 TextView.

该应用程序包含两个活动 --> MainDetails(详细信息包括一些片段)。

Main activity 中,用户输入一个 ID 并按下确定按钮。然后我启动蓝牙线程并使用 MAC 地址直接连接到蓝牙设备。然后我打开Detailsactivity。

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());
            }
        }
    }
}

这是Detailsactivity中的取消按钮点击:

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 时,ConnectedThreadHandler 是否正在更新旧的 TextView,但这是可能的,因为我使用的是 WeakReference ?

你的描述让我觉得你可能有一个泄漏 activity,然后你的线程会更新一个不再显示的片段。 您可以尝试启动以下命令行:

adb shell dumpsys meminfo <your.app.package>

你会发现对结果的很好解释here。 您感兴趣的是 "Objects" 部分,您会在其中找到一个 "Activities" 数字。

你可以去你的细节activity,回到主要的,再去细节,等等...... 活动数量应保持稳定。如果它增加,您的 activity.

可能有泄漏

从那里,您应该寻找保留的视图/片段(我可以看到您的处理程序中有一个 WeakReference,所以您知道如何修复它)

这里,Memory Monitor and the Allocation Tracker 之类的分析工具肯定会有所帮助,但要理解它们需要一些时间。

假设您实际上没有更新 ConnectedThreadHandler,问题不是"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 时,我只需要取消 ConnectThreadConnectedThread。这解决了我的问题。尴尬,但我还是个初学者。

但是,我想我仍然对泄露的活动有疑问。但这是我将继续与之抗争的另一个话题。