talk-android/app/src/main/java/com/nextcloud/talk/call/CallParticipantModelNotifier.java
Daniel Calviño Sánchez d72648379e Add model for (remote) call participants
Clients that modify the model would define the variables using the
mutable subclass, while clients that only need to access the model are
expected to use the read-only base class.

The read-only class provides an observer; as it is expected that the
model will be modified from background threads but observed from the
main thread the observer can be registered along a handler to be
notified on its thread, independently of on which thread the values were
set.

Currently there does not seem to be a need to observe each value on its
own, so the observer is notified in a coarse way when any value changes.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
2023-01-16 09:05:50 +00:00

87 lines
3.0 KiB
Java

/*
* Nextcloud Talk application
*
* @author Daniel Calviño Sánchez
* Copyright (C) 2022 Daniel Calviño Sánchez <danxuliu@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.call;
import android.os.Handler;
import android.os.Looper;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Helper class to register and notify CallParticipantModel.Observers.
*
* This class is only meant for internal use by CallParticipantModel; observers must register themselves against a
* CallParticipantModel rather than against a CallParticipantModelNotifier.
*/
class CallParticipantModelNotifier {
/**
* Helper class to associate a CallParticipantModel.Observer with a Handler.
*/
private static class CallParticipantModelObserverOn {
public final CallParticipantModel.Observer observer;
public final Handler handler;
private CallParticipantModelObserverOn(CallParticipantModel.Observer observer, Handler handler) {
this.observer = observer;
this.handler = handler;
}
}
private final List<CallParticipantModelObserverOn> callParticipantModelObserversOn = new ArrayList<>();
public synchronized void addObserver(CallParticipantModel.Observer observer, Handler handler) {
if (observer == null) {
throw new IllegalArgumentException("CallParticipantModel.Observer can not be null");
}
removeObserver(observer);
callParticipantModelObserversOn.add(new CallParticipantModelObserverOn(observer, handler));
}
public synchronized void removeObserver(CallParticipantModel.Observer observer) {
Iterator<CallParticipantModelObserverOn> it = callParticipantModelObserversOn.iterator();
while (it.hasNext()) {
CallParticipantModelObserverOn observerOn = it.next();
if (observerOn.observer == observer) {
it.remove();
return;
}
}
}
public synchronized void notifyChange() {
for (CallParticipantModelObserverOn observerOn : new ArrayList<>(callParticipantModelObserversOn)) {
if (observerOn.handler == null || observerOn.handler.getLooper() == Looper.myLooper()) {
observerOn.observer.onChange();
} else {
observerOn.handler.post(() -> {
observerOn.observer.onChange();
});
}
}
}
}