【问题标题】:Updating UI-thread with handler使用处理程序更新 UI 线程
【发布时间】:2013-08-02 04:25:54
【问题描述】:

我在网上搜索了这方面的明确示例,但到目前为止还没有找到可以应用于我的项目的示例。

我正在尝试创建一个每 100 毫秒运行一次的工作线程。然后它应该用结果更新 UI。经过一些研究,我决定我可能应该使用处理程序来管理 UI 更新。我来到了这个解决方案:

我的活动处理程序:

private  final Handler handler = new Handler() {

        public void handleMessage(Message msg) {

        String aResponse = msg.getData().getString("message");

        if ((null != aResponse)) {

            // ALERT MESSAGE
            Log.v("udppacket", "UDP message!");
            if (msg.obj != null)
            {
                ManagerUdpPacket p = (ManagerUdpPacket) msg.obj;
                operatorListFragment.updateContent((int) p.getOperationTime());
            }
        }
        else
        {

        }    

    }
};

我的另一个有工作线程的类:

public class ManagerUdpReceiver 
{
    private int minPort = 1234;
    private int maxPort = 1240;
    private ArrayList<PortListener> portList;
    private Handler handler;
    private Thread portThread;
    private int queryInterval = 100;
    private boolean stop = false;


    public ManagerUdpReceiver(int minport, int maxport, Handler handler, int queryInterval)
    {
        minPort = minport;
        maxPort = maxport;
        this.handler = handler;
        this.queryInterval = queryInterval;

        //create port listeners from given range and start their threads


    start();
}

private void start()
{
    stop = false;
    // Create Inner Thread Class
    portThread = new Thread(new Runnable() 
    {
        // After call for background.start this run method call
        public void run() 
        {

            if (portList == null)
            {
                portList = new ArrayList<PortListener>();
                for (int i = minPort; i < maxPort; i++)
                {
                    portList.add(new PortListener(i));
                }
            }

            if (!stop)
            {
                ManagerUdpPacket p = portList.get(0).receive();
                threadMsg("moi", p);
                //mHandler.postDelayed(this, queryInterval);

            }
            else
            {
                //stop execution and close ports
                for (int i = 0; i < portList.size(); i++)
                {
                    portList.get(i).close();
                }
            }


        }

        //send message to the handler
        private void threadMsg(String msg, ManagerUdpPacket p) 
        {
             if (!msg.equals(null) && !msg.equals("")) 
             {
                 Message msgObj = handler.obtainMessage();
                 //msgObj.obj = p;
                 Bundle b = new Bundle();
                 b.putString("message", msg);
                 msgObj.setData(b);
                 handler.sendMessage(msgObj);
             }               
        }
    });

    // Start Thread
    portThread.start();
}



public void close()
    {   
        stop = true;
    }
}

当我运行程序时,我得到关于在 UI 线程中运行网络代码的异常。现在,工作线程应该接收和处理 UDP 数据包。但是,它的代码在 portThread 线程中!我想那个 handler.postDelayed(this, queryInterval);我用它每 100 毫秒循环一次线程,以某种方式导致下一个循环在 UI 线程而不是我的工作线程中运行。

所以我的问题是我在这里做错了什么以及如何解决它?或者,如何让循环在每 100 毫秒内正常工作?我也不确定将处理程序放在哪里,因为我已经看到了它在活动内部和工作线程内部的示例。

【问题讨论】:

标签: java android multithreading user-interface handler


【解决方案1】:

不太了解处理程序的目的。为什么你不只是在后台线程上准备数据而不是使用myActivity.runOnUIThread() 来运行你的 updateContent() 方法?可能p.getOperationTime()被认为是网络操作,尝试将此值保存到后台线程中的某个变量中,而不是通过UI线程发布。

【讨论】:

    【解决方案2】:

    好的,虽然我对它不满意,但我想我已经成功了,所以不要选中它。

    基本上,我最终使用 TimerTask 每 100 毫秒运行一次我的代码,并通过 Handler 通知 UI 线程。我不确定这是否是最佳选择(我听说 Timers 不是那么好),但似乎有效:

    dataStreamTimer = new Timer();
        dataStreamTask = new TimerTask()
        {
            public void run() 
            {
    
                if (portList == null)
                {
                    portList = new ArrayList<PortListener>();
                    for (int i = minPort; i < maxPort; i++)
                    {
                        portList.add(new PortListener(i));
                    }
                }
    
                if (!stop)
                {
    
                    ManagerUdpPacket p = portList.get(0).receive();
                    threadMsg("moi", p);
                    //handler.postDelayed(this, queryInterval);
    
                    //stop thread until next query
                    try {
                        synchronized(this){
                            this.wait(queryInterval);
                        }
                    } catch (InterruptedException e) {
                        Log.e("ERR", "InterruptedException in TimerTask.run");
                    }
                }
                else
                {
                    //execution has been stopped, clear data:
                    //stop execution and close ports
                    for (int i = 0; i < portList.size(); i++)
                    {
                        portList.get(i).close();
                    }
                }
    
            }
    

    【讨论】:

    • 您也可以在后台线程中循环运行您的代码,并在每个循环后休眠 100 毫秒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 2014-02-21
    • 1970-01-01
    相关资源
    最近更新 更多