Страницы

Поиск по вопросам

Показаны сообщения с ярлыком observer. Показать все сообщения
Показаны сообщения с ярлыком observer. Показать все сообщения

пятница, 27 декабря 2019 г.

Java шаблон Observer и многопоточность

#java #многопоточность #инспекция_кода #observer


Мне необходимо создать приложение, которое будет получать данные по сети и передавать
их другим классам для обработки. Я решила воспользоваться для этого шаблоном observer,
но столкнулась с проблемой. Одновременно может поступить несколько соединений, поэтому
для каждого я создаю новый экземпляр класса с принятием соединения и обработкой данных.
Но как тогда правильно привязать наблюдателей к классу сервера. Чтобы использовать
что-то в дополнительном потоке переменная должна быть статическая или финальная. Финальная
не подходит, потому что на каждое соединение новый экземпляр сервера. А статическая
меня смущает, я не совсем понимаю, как это работает. 

Внизу приведен код, подскажите, пожалуйста, как правильно это организовать, чтобы
во время эксплуатации никакая фигня не вылезла.

Это главный класс

public class Main {
    static Server server = new Server();

    public static void main(String[] args) {
    new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    int i = 0; // счётчик подключений
                    ServerSocket socket = new ServerSocket(3013);

                    while(true)// слушаем порт
                    {
                        server = new Server(i, socket.accept());
                        i++;
                    }
                }
                catch(Exception e){
                    System.out.println("init: " + e);                   
                }
            }
        }).start();

        ConcreteObserver observer = new ConcreteObserver(server);
    }
}


Это класс сервера

public class Server extends Thread implements Observable {
    Socket socket;
    int num;
    List string = null;

    private static List observers;

    public Server() {
        observers = new ArrayList();
    }

    public Server(int num, Socket s) {
        this.num = num;
        this.socket = s;
        start();
    }

    public void run() {
        // doing something
        notifyObservers();
    }

    public void addObserver(Observer o) {
         if (o != null) { 
             observers.add(o);
         }
    }

    public void deleteObserver(Observer o) {
        if (o != null) {
            observers.remove(o);
        }
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(listMettUnits);
        }
    }
}


И класс наблюдателя

public class ComputeAll implements Observer {
    private Server server =  null;

    public ComputeAll(Server server) {
        this.server = server;
        server.addObserver(this);
    }

    public void update(List list) {
        // doing something
    }
}

    


Ответы

Ответ 1



По данному коду у меня есть несколько замечаний. для observers не рекомендуется использовать LinkedList, лучше воспользоваться потокобезопасной реализацией, например java.util.concurrent.CopyOnWriteArrayList; регистрировать наблюдателей предпочтительнее до запуска сервера. Поля в классе Server и ComputeAll я бы сделал final Запуск потока в его конструкторе не очень хорошая идея, и вообще, явное создание потоков не есть хорошо, воспользуйтесь, как вариант, java.util.concurrent.ExecutorService И что касается не многопоточности, observers является статическим, что скорее всего не совсем верно.

вторник, 17 декабря 2019 г.

Получение только измененной части LiveData<List>

#android #observer #livedata


Активно изучаю LiveData в андроид и хотел бы разобраться со следующим вопросом.
Андроид устройство - клиент, через сокет цепляется к серверу. Сервер периодически
присылает какие-то сообщения, среди них есть события, которые необходимо отрисовывать
на вьюшке.
Я использую mvvm паттерн. На события, пришедшие от сокета, подписывается репозиторий:

class EventRepository : IEventRepositoty {

    private companion object {
        val MAX_EVENT = 20
    }
    private val mEventList = MutableLiveData>()
    val eventList : LiveData> = mEventList
    .....
}


В репозитории хранится mEventList, в который я складываю события, пришедшие от сервера.
Вопрос в том, что если ViewModel подпишется на eventList, то при записи нового события
во ViewModel сработает observer, аргументом которого будет весь новый список. Но на
вьюшке уже большая часть списка отрисована, и мне надо только вставить новый item.
Решение, которое пришло в голову: события записывать не в LiveData, а в обычный list,
а в LiveData держать только один EventModel
Но что-то мне не нравится данный вариант, ибо при старте я запрашиваю последние события
с сервера, и их придет список. Есть вариант держать LiveData>,
но писать туда только список новых элементов (если событие одно, то, соответственно,
список размера 1).

Может, есть какой-то более удобный способ получить только измененную часть списка?
    


Ответы

Ответ 1



Если речь идет о RecyclerView, рекомендую вам обратить внимание на новый адаптер ListAdapter из библиотеки поддержки v7. Он обязывает реализовать механизм DiffUtil, который позаботится о вычислении изменений между новыми данными и уже имеющимися в адаптере и автоматически произведет нужные манипуляции (добавит, удалит, изменит соответствующие айтемы). Таким образом вы отдаете адаптеру актуальный список целиком (а не в ручную отбираете новые элементы), он же позаботится о остальном. При этом работать будет все полностью автоматически - при изменении данных в репозитории они будут изменяться и в виджете без каких либо действий с вашей стороны. Пример

четверг, 21 марта 2019 г.

Получение только измененной части LiveData

Активно изучаю LiveData в андроид и хотел бы разобраться со следующим вопросом. Андроид устройство - клиент, через сокет цепляется к серверу. Сервер периодически присылает какие-то сообщения, среди них есть события, которые необходимо отрисовывать на вьюшке. Я использую mvvm паттерн. На события, пришедшие от сокета, подписывается репозиторий:
class EventRepository : IEventRepositoty {
private companion object { val MAX_EVENT = 20 } private val mEventList = MutableLiveData>() val eventList : LiveData> = mEventList ..... }
В репозитории хранится mEventList, в который я складываю события, пришедшие от сервера. Вопрос в том, что если ViewModel подпишется на eventList, то при записи нового события во ViewModel сработает observer, аргументом которого будет весь новый список. Но на вьюшке уже большая часть списка отрисована, и мне надо только вставить новый item. Решение, которое пришло в голову: события записывать не в LiveData, а в обычный list, а в LiveData держать только один EventModel Но что-то мне не нравится данный вариант, ибо при старте я запрашиваю последние события с сервера, и их придет список. Есть вариант держать LiveData>, но писать туда только список новых элементов (если событие одно, то, соответственно, список размера 1).
Может, есть какой-то более удобный способ получить только измененную часть списка?


Ответ

Если речь идет о RecyclerView, рекомендую вам обратить внимание на новый адаптер ListAdapter из библиотеки поддержки v7. Он обязывает реализовать механизм DiffUtil, который позаботится о вычислении изменений между новыми данными и уже имеющимися в адаптере и автоматически произведет нужные манипуляции (добавит, удалит, изменит соответствующие айтемы). Таким образом вы отдаете адаптеру актуальный список целиком (а не в ручную отбираете новые элементы), он же позаботится о остальном.
При этом работать будет все полностью автоматически - при изменении данных в репозитории они будут изменяться и в виджете без каких либо действий с вашей стороны.
Пример