从队列更新活动的最佳方法

时间:2012-02-13 23:58:56

标签: android queue android-activity

我的“Producer-Mediator-Consumer”模型中的Mediator中有一个LinkedBlockingQueue。 Producer首先更新Mediator添加到activityQueue。接下来,Consumer / Activity会等待/侦听队列并抓取下一个项目。

我想让一个Activity看到队列大小已经改变并抓住下一个项目。 调解员无法查看活动,只有活动才能看到调解员。那么如何创建我想要的侦听器机制呢?

这是我的mediator类,它包含Queue,Activity会以某种方式查看队列,并在需要更新时获取通知。进入队列的数据有时可能是不稳定和随机的,因此轮询机制将无法工作。

public class MediatorData {

    /** Queue for the Activity */
    LinkedBlockingQueue <byte[]> queueConsumer = new LinkedBlockingQueue <byte[]>();

    /**
     * Add data to a queue(s) for consumption
     */
    public void put(byte[] data) throws InterruptedException {
        queueConsumer.add(data);
    }

    /**
     * Return data from the queue for the Feature calculations
     */
    public byte[] getFeatureData() throws InterruptedException {
        return queueConsumer.poll(100, TimeUnit.MILLISECONDS);
    }

}

我的活动类的示例,它是一个图形类,因此队列侦听器必须高效且快速。

public class DisplayGraph extends Activity {

    // populated from Application Class where its created
    pirvate MediatorData md;

    public void onCreate(Bundle savedInstanceState) {
        md = getMediator();  // This comes from the custom Application class

        ... some type of listener to queue 
    }

    private void getQueueData() {
        byte[] tv = md.queueConsumer.poll();
        // can't update textview  get exception CalledFromWrongThreadException
        ((TextView) DisplayGraph.this.findViewById(R.id.tv)).setText("TV " + tv[0]);
    }
}

2 个答案:

答案 0 :(得分:1)

如何使用ObserverObservable

可能是这样的:

public class MediatorData extends Observable {

    /** Queue for the Activity */
    LinkedBlockingQueue <byte[]> queueConsumer = new LinkedBlockingQueue <byte[]>();

    /**
     * Add data to a queue(s) for consumption
     */
    public void put(byte[] data) throws InterruptedException {
        queueConsumer.add(data);
        setChanged();
        notifyObservers();
    }

    /**
     * Return data from the queue for the Feature calculations
     */
    public byte[] getFeatureData() throws InterruptedException {
        return queueConsumer.poll(100, TimeUnit.MILLISECONDS);
    }
}

而且:

public class DisplayGraph extends Activity implements Observer {

    // populated from Application Class where its created
    private MediatorData md;

    public void onCreate(Bundle savedInstanceState) {
        md = getMediator();  // This comes from the custom Application class
        md.addObserver(this);
    }

    private void getQueueData() {
        byte[] tv = md.queueConsumer.poll();
        // can't update textview  get exception CalledFromWrongThreadException
        ((TextView) DisplayGraph.this.findViewById(R.id.tv)).setText("TV " + tv[0]);
    }

    public void update(Observable arg0, Object arg1) {
        getQueueData();
    }
}

答案 1 :(得分:1)

处理这种情况的最佳方法是:先前的答案中有错误。

public class MediatorData extends Observable {

    /** Queue for the Activity */
    LinkedBlockingQueue <byte[]> queueConsumer = new LinkedBlockingQueue <byte[]>();

    /**
     * Add data to a queue(s) for consumption
     */
    public void put(byte[] data) throws InterruptedException {
        queueConsumer.add(data);
        notifyObservers();
    }

    /**
     * Return data from the queue for the Feature calculations
     */
    public byte[] getFeatureData() throws InterruptedException {
        return queueConsumer.poll(100, TimeUnit.MILLISECONDS);
    }
}

显示活动需要在UI线程上运行更新,因此请使用runOnUiThread方法。

public class DisplayGraph extends Activity implements Observer {

    // populated from Application Class where its created
    private MediatorData md;

    byte[] tv;

    public void onCreate(Bundle savedInstanceState) {
        md = getMediator();  // This comes from the custom Application class
        md.addObserver(this);
    }

    private void getQueueData() {
        tv = md.queueConsumer.poll();
        runOnUiThread(setRunnable);
    }

    public void update(Observable arg0, Object arg1) {
        getQueueData();
    }

    // Need to do this to update the data to the UI.
    final Runnable setImageRunnable = new Runnable() {
        public void run() {
            ((TextView) DisplayGraph.this.findViewById(R.id.tv)).setText("TV " + tv[0]);
        }
    };
}