我刚刚开始使用RxJava2,并想知道如何正确实现UDP observable 我已经有了一些工作代码,但我认为可能存在一些问题:请参阅下面源代码的注释中的4个问题。
我还在GitHub RxJava2_Udp上发布了代码:欢迎提出意见,问题和请求。
class UdpObservable {
private static class UdpThread extends Thread {
private final int portNo;
private final int bufferSizeInBytes;
private final ObservableEmitter<DatagramPacket> emitter;
private DatagramSocket udpSocket;
private UdpThread(@NonNull ObservableEmitter<DatagramPacket> emitter
, int portNo, int bufferSizeInBytes) {
this.emitter = emitter;
this.portNo = portNo;
this.bufferSizeInBytes = bufferSizeInBytes;
}
@Override
public void run() {
try {
// we don't want to create the DatagramSocket in the constructor, because this
// might raise an Exception that the observer wants to handle
udpSocket = new DatagramSocket(portNo);
try {
/* QUESTION 1:
Do I really need to check isInterrupted() and emitter.isDisposed()?
When the thread is interrupted an interrupted exception will
be raised anyway and the emitter is being disposed (this is what
caused the interruption)
*/
while (!isInterrupted() && !emitter.isDisposed()) {
byte[] rcvBuffer = new byte[bufferSizeInBytes];
DatagramPacket datagramPacket = new DatagramPacket(rcvBuffer, rcvBuffer.length);
udpSocket.receive(datagramPacket);
// QUESTION 1a: same as QUESTION 1 above
if (!isInterrupted() && !emitter.isDisposed()) {
emitter.onNext(datagramPacket);
}
}
} finally {
closeUdpSocket();
}
} catch (Throwable th) {
// the thread will only be interrupted when the observer has unsubscribed:
// so we need not report it
if (!isInterrupted()) {
if (!emitter.isDisposed()) {
emitter.onError(th);
} else {
// QUESTION 2: is this the correct way to handle errors, when the emitter
// is already disposed?
RxJavaPlugins.onError(th);
}
}
}
}
private void closeUdpSocket() {
if (!udpSocket.isClosed()) {
udpSocket.close();
}
}
@Override
public void interrupt() {
super.interrupt();
// QUESTION 3: this is called from an external thread, right, so
// how can we correctly synchronize the access to udpSocket?
closeUdpSocket();
}
}
/**
* creates an Observable that will emit all UDP datagrams of a UDP port.
* <p>
* This will be an infinite stream that ends when the observer unsubscribes, or when an error
* occurs. The observer does not handle backpressure.
* </p>
*/
public static Observable<DatagramPacket> create(final int portNo, final int bufferSizeInBytes) {
return Observable.create(
new ObservableOnSubscribe<DatagramPacket>() {
@Override
public void subscribe(ObservableEmitter<DatagramPacket> emitter) throws Exception {
final UdpThread udpThread = new UdpThread(emitter, portNo, bufferSizeInBytes);
/* QUESTION 4: Is this the right way to handle unsubscription?
*/
emitter.setCancellable(new Cancellable() {
@Override
public void cancel() throws Exception {
udpThread.interrupt();
}
});
udpThread.start();
}
}
);
}
}
答案 0 :(得分:3)
Schedulers
应该为你做。ObservableOnSubscribe
处执行的代码代码将根据您的Scheduler
策略在某个主题上运行,因此您不需要自己构建它。只需在create中执行ude while循环。Thread.interrupt()
方法,当您处置(取消订阅)Observable
时,RxJava会为您执行此操作。 (当然,在while循环之前设置cancelable
)关于你的问题:
您不需要检查被中断的异常情况
如果您等待io操作,请加薪,您也不需要
检查处理,因为onNext()
会为你做,并且会
没有取消订阅。
您可以再次致电onError
,发射器将负责检查Observable
是否已取消订阅。
emitter.setCancellable
方法。 (关闭流),这发生在代码运行的同一个线程上。emitter.setCancellable
方法