简体   繁体   English

使用处理程序更新UI线程

[英]Updating UI-thread with handler

I have scoured the web to find definite examples of this but so far couldn't find one which I could have applied to my project. 我已经在网上搜寻了确定的示例,但到目前为止找不到我可以应用于我的项目的示例。

I'm trying to create a worker-thread which is run every 100ms. 我正在尝试创建每100毫秒运行一次的工作线程。 It then should update UI with results. 然后应使用结果更新UI。 After some research I decided that I probably should use Handlers to manage the UI-updating. 经过一些研究,我决定我可能应该使用Handlers来管理UI更新。 I came to this solution: 我来到这个解决方案:

My activity's Handler: 我的活动的处理程序:

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
        {

        }    

    }
};

My other class which has the worker-thread: 我的另一个具有工作线程的类:

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

When I run the program I get exception about running networking code in UI-thread. 当我运行程序时,我得到了关于在UI线程中运行网络代码的异常。 Now, the worker-thread should receive and process UDP-packets. 现在,工作线程应该接收并处理UDP数据包。 However, the code for that is inside of the portThread thread! 但是,该代码位于portThread线程内部! I suppose that handler.postDelayed(this, queryInterval); 我想那个handler.postDelayed(this,queryInterval); which I use to loop the thread in every 100ms somehow causes the next cycle to be run in UI-thread instead of my worker-thread. 我使用它每100毫秒循环一次线程,导致下一个周期在UI线程而不是工作线程中运行。

So my question is what I'm doing wrong here and how to fix it? 所以我的问题是我在这里做错了什么以及如何解决? Or alternatively, how to get the looping work correctly in every 100ms? 或者,如何每100毫秒正确地执行循环工作? I'm also not sure where to place the Handler, since I have seen examples where it is inside Activity and inside the worker-thread. 我也不确定在哪里放置处理程序,因为我已经看到了一些示例,它位于Activity内和worker线程内。

Ok, I think I got it working though I'm not satisfied with it and so leaving this unchecked. 好的,我认为它可以正常运行,尽管我对此不满意,因此请不要进行检查。

Basically I ended up using TimerTask to run my code every 100ms and notifying UI-thread via Handler. 基本上,我最终使用TimerTask每100毫秒运行一次代码,并通过Handler通知UI线程。 I'm not really sure if this is best choice (I have heard that Timers aren't that great) but seems to work: 我不确定这是否是最佳选择(我听说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();
                }
            }

        }

dont really understand purpose of handlers. 不太了解处理程序的目的。 Why you dont just prepare data on backround thread and than use myActivity.runOnUIThread() to run your updateContent() method? 为什么您不只是在myActivity.runOnUIThread()线程上准备数据,而不使用myActivity.runOnUIThread()运行updateContent()方法? Maybe p.getOperationTime() is considered network operation, try to save this value to some variable in background thread and than publish it by UI thread. 也许p.getOperationTime()被认为是网络操作,请尝试将此值保存到后台线程中的某个变量中,然后由UI线程发布。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM