0

これはよくある質問であり、私はそれを処理するさまざまな方法を読みましたが、それぞれが私がやろうとしていることには不十分であるように見えます。これは本質的に良いOO市民です。

基本的にTCPソケットをポーリングしてデータを取得するCommunicationManagerを呼び出すアクティビティがあります。CommunicationManagerはデータを受信すると、アクティビティによって処理されるカスタムイベント(フェッチしたばかりの文字列を含む)をスローします。私はこれを行っています。A)他のクラスはアクティビティだけでなくそのデータに依存するため、B)ポーリングは非同期であり、結果を受け取ったときにイベントを発生させる必要があるためです。

私の問題は、それらの結果をUIのTextViewに表示する必要があることです。ポーリングメカニズムをすべて設定しました。これは1000ミリ秒ごとに起動し、アクティビティでイベントハンドラーを呼び出します。ただし、UIは更新されません。

おそらくこれはスレッドの問題であり、UIスレッドはTextViewに変更を加えるスレッドではありませんが、どうすればよいですか?ハンドラーを使用してみましたが、どこに配置すればよいかわからず、コンパイルしてもUIが更新されませんでした。

すべてがアクティビティ内で行われた場合、これは比較的些細なことのように見えますが、この他のクラス(CommunicationManager)とイベントを追加すると、非常に混乱します。

これが私がこれまでに持っているものです:

アクティビティ(UIのボタンをクリックするとポーリングが呼び出されます):

public void onClick(View v) {
    if (v.getId() == R.id.testUDPBtn) {
        statusText.setText("");

        commMgr = new CommunicationManager();
        commMgr.addEventListener(this);

        MediaPositionPollThread poller = new MediaPositionPollThread(commMgr);
        poller.startPolling();
    }
}

@Override
public void handleMediaPositionFoundEvent(MediaPositionFoundEvent e) {
    statusText.append(e.userData);
}

スレッド:

class MediaPositionPollThread extends Thread {
    private CommunicationManager commManager;
    private static final String TAG = "MediaPositionPollThread";
    private boolean isPolling = false;

    public MediaPositionPollThread(CommunicationManager cm) {
        commManager = cm;
    }

    public void startPolling() {
        isPolling = true;
        this.run();
    }

    public void stopPolling() {
        isPolling = false;
    }

    @Override
    public void run() {
        while (isPolling) {
            try {
                commManager.getCurrentMediaPosition();
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                Log.d(TAG, "EXCEPTION: " + e.getMessage());
            }
        }
    }
}

コミュニケーションマネージャー:

public void getCurrentMediaPosition() {
    PrintWriter outStream;
    BufferedReader inStream;
    String resultString = "";

    try {
        outStream = new PrintWriter(tcpSocket.getOutputStream(), true);
        outStream.println("GET?current_pts");

        inStream = new BufferedReader(new InputStreamReader(tcpSocket.getInputStream()));
        resultString = inStream.readLine();

        fireEventWithData(resultString);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public synchronized void addEventListener(MediaPositionFoundEventListener listener)  {
    _listeners.add(listener);
}

public synchronized void removeEventListener(MediaPositionFoundEventListener listener)   {
    _listeners.remove(listener);
}

private synchronized void fireEventWithData(String outputString) {
    MediaPositionFoundEvent evt = new MediaPositionFoundEvent(this);
    evt.userData = outputString;

    Iterator<MediaPositionFoundEventListener> i = _listeners.iterator();
    while(i.hasNext()) {
        ((MediaPositionFoundEventListener) i.next()).handleMediaPositionFoundEvent(evt);
    }
}

したがって、CommunicationManager >> getCurrentMediaPositionを呼び出して、毎秒実行されるスレッドを作成するアクティビティがあります。これにより、MediaPositionFoundEventが起動され、Activityによって処理され、画面上のTextView(statusText)が更新されます。

画面が更新されないことを除いて、すべてが機能します。runOnUiThreadとハンドラーを試しましたが、明らかに正しくありません。

洞察や解決策を事前に感謝します!

4

2 に答える 2

2

Activityクラスでプライベートを追加し、 ActivityメソッドでHandler _handler初期化します。onCreate

handleMediaPositionFoundEventメソッドをに変更します

@Override    public void handleMediaPositionFoundEvent(MediaPositionFoundEvent e) {  
          _handler.post(new Runnable(){  
             public void run(){  
               statusText.append(e.userData);  
           });  
          }  
        }
于 2012-06-06T21:41:58.063 に答える
1

カスタムでUIスレッドをブロックしているようThreadです。start()vsを呼び出すようにこのメソッドを更新してくださいrun()

public void startPolling() {
    isPolling = true;
    this.start();
}
于 2012-06-06T21:52:47.003 に答える