0

これの明確な例を見つけるためにウェブを精査しましたが、これまでのところ、自分のプロジェクトに適用できるものを見つけることができませんでした.

100ms ごとに実行されるワーカー スレッドを作成しようとしています。次に、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スレッドで実行されます。

だから私の質問は、私がここで間違っていることと、それを修正する方法です? または、100ms ごとにループを正しく動作させるにはどうすればよいですか? また、Activity 内とワーカー スレッド内にある例を見たので、Handler をどこに配置すればよいかもわかりません。

4

2 に答える 2

1

わかりました。満足していないので、これをチェックしないままにしておきますが、うまくいったと思います。

基本的に、TimerTask を使用して 100 ミリ秒ごとにコードを実行し、Handler を介して UI スレッドに通知することになりました。これが最良の選択であるかどうかはよくわかりませんが(タイマーはそれほど優れていないと聞きました)、うまくいくようです:

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

        }
于 2013-08-01T10:32:20.573 に答える
0

ハンドラーの目的を本当に理解していません。myActivity.runOnUIThread()updateContent() メソッドを実行するために使用するよりも、バックラウンド スレッドでデータを準備しないのはなぜですか? ネットワーク操作p.getOperationTime()と見なされる可能性があります。この値をバックグラウンド スレッドの変数に保存してから、UI スレッドで公開してみてください。

于 2013-08-01T10:33:19.887 に答える