【问题标题】:Calling Method w/ Argument on Main Thread from Secondary Thread从辅助线程在主线程上调用带参数的方法
【发布时间】:2014-03-02 20:13:06
【问题描述】:

就像标题一样,我有一个带有 MainActivity 类的 android 项目,该类有一个 TextView,我想在收到消息后设置它的文本。我还有一个在单独线程上运行 ServerSocket 的类,该线程接收我要显示的字符串消息。

我的 MainActivity 的一部分看起来像这样,

private Handler UIHandler = new Handler();
private RemoteControlServer remoteConnection;
public static final int controlPort = 9090;
public class MainActivity extends Activity implements SensorEventListener
{
    ...

    remoteConnection = new RemoteControlServer(controlPort, UIHandler);

    ...

    private class RemoteControlServer extends RemoteControl
    {
        RemoteControlServer(int port, Handler ui)
        {
            super(port, ui);
        }

        @Override
        public void onReceive(String[] msg)
        {
            //updates messages textview
        }

        @Override
        public void onNotify(String[] msg)
        {
            //updates notification textview
        }
    }
}

调用 onReceive(String[] msg) 并处理在不同线程上接收消息的代码的 RemoteControlServer 实现如下所示,

...

public abstract void onReceive(String[] msg);
public abstract void onNotify(String[] msg);

...

controlListener = new Thread(new Runnable()
{
    boolean running = true;
    public void run()
    {
        String line = null;
        while(running)
        {
            try
            {
                //Handle incoming messages

                ...

                onReceive(messages);    
            }
            catch (final Exception e)
            {
                UIHandler.post(new Runnable()
                {
                    public void run()
                    {
                        onNotify("Wifi Receive Failed " + e.toString() + "\n");
                    }
                });
            }
        }
    }
});

...

我收到错误消息“只有创建视图层次结构的原始线程才能接触其视图。”当 onReceive() 被调用并抛出异常并使用异常描述调用 onNotify() 时。为什么 onNotify() 有效,而另一个无效?如何正确调用 TextView 的侦听器并更新其文本?谢谢

【问题讨论】:

    标签: java android multithreading


    【解决方案1】:
    private class RemoteControlServer extends RemoteControl
    {
    
        ...
    
        public class BridgeThread implements Runnable
        {
            String[] msgArray = null;
            public BridgeThread(String[] msg)
            {
                msgArray = msg;
            }
    
            public void run()
            {
                runOnUiThread(new Runnable()
                {   
                    @Override
                    public void run()
                    {
                        TextView zValue = (TextView) findViewById(R.id.connectionStatus);
                        zValue.setText(msgArray[0]);
                    }
                });
            }
        }
    
        @Override
        public void onReceive(String[] msg)
        {
            BridgeThread bridgeTest = new BridgeThread(msg);
            bridgeTest.run();
        }
    
        ...
    }
    

    【讨论】:

    • 这会取代我当前的新 Thread() 代码吗?如果我错了,请纠正我,但这不会在 UI 线程上运行我的 ServerSocket(我不想这样做)吗?
    • 当你收到一个你想在 TextView 中显示的字符串时......只需复制该代码并在 textview 上使用该字符串调用 setText(在我上面的代码中是 //set your text).. .问题是您将从您为接收消息而实现的另一个线程调用UI线程(UI线程可以与用户界面一起使用,这就是您想要的)......这对您来说有什么意义吗? :) 我的英语不太好:/
    • 好的,感谢 Matej 的建议,我过会试一试
    • 如何在您提供的代码中传递“String[] msg”对象,以便将文本设置为 msg? run() 方法不应该有任何参数。
    • 附言。您的建议确实适用于设置文本,我只需要将文本设置为我收到的内容,因此除非我可以将参数传递给该 run() 方法,否则它将不起作用
    猜你喜欢
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多