蓝牙线程/处理程序无法更新用户界面

时间:2016-02-25 12:46:07

标签: android bluetooth android-handler

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

该应用包含两项活动 - > MainDetails(详情包括一些片段)。

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

3 个答案:

答案 0 :(得分:1)

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

adb shell dumpsys meminfo <your.app.package>

您会找到结果here的一个很好的解释。 您可以在“对象”部分找到有趣的内容,您可以在其中找到“活动”编号。

您可以参加您的详细信息活动,返回主要活动,再转到详细信息等... 活动数量应保持稳定。如果它增加,您的活动可能会泄漏。

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

此处,Memory MonitorAllocation Tracker等分析工具肯定会有所帮助,但需要一些时间才能理解。

答案 1 :(得分:1)

假设您实际上更新 Handler的{​​{1}},问题不在于“为什么UI不会更新?”而是“如何 UI更新?”

您需要更新帖子的ConnectedThread成员:

mHandler

然后添加

public void setHandler( MyHandler newHandler ) {
    mHandler = newHandler;
}

到您的片段的connectedThread.setHandler( new MyHandler( this ) ); 事件。

根据您遇到的流量,事件总线可能是更好的实施方式。

答案 2 :(得分:0)

好的,我认为我做对了,当我重定向回ConnectThread时,我只需要取消ConnectedThreadMainActivity。这解决了我的问题。令人尴尬,但我仍然是初学者。

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