Название: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июнь 27, 2011, 21:10 Всем привет!
В образовательных и практических целях пишу (точнее пытаюсь) программку, работающую по технологии Модель-представление через сеть. Но столкнулся с рядом проблем. С начала даже не знал, от чего отталкиваться. Потом подсказали... Написал простенький сервер, который в хранит список строк. Строки в список можно добавлять и удалять. Если клиент отсылает серверу строку "3. ", то сервер возвращает весь список. Задумка следующая: клиентская программа должна работать по технологии Модель-представление и отображать текущее состояние списка на сервере. Как это реализовать? Нужно переопределить метод data() в своём классе так, чтобы он запрашивал данные у сервера... но, сколько с ним просидел, ничего не получилось. Благодарю за внимание. Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июнь 28, 2011, 20:21 Судя по количеству просмотров, тема интересна не для меня одного.
Если у кого-нибудь есть опыт в написании таких программ, пожалуйста, поделитесь. Название: Re: Модель-представление, работа через сеть Отправлено: ieroglif от Июнь 28, 2011, 23:17 Судя по количеству просмотров, тема интересна не для меня одного. да ничего особо интеренсного/сложного нет.Если у кого-нибудь есть опыт в написании таких программ, пожалуйста, поделитесь. есть класс модели, если класс подгружения данных по сети в модель (сетевик). на какие события сетевик подгружает данные - дело индивидуальное. как только появляются обновления в данных - он сообщает об этом модели. всё. Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июнь 30, 2011, 16:52 В теории, действительно, особо сложного ничего нет, но давайте перейдём к практике.
Почитав документацию и провозившись целый день, некоторые моменты стали понятны, но я снова зашёл в тупик. Понял, что сервер написан не правильно, переписал так, как посоветовали: если серверу отправить строку "length", он вернёт общее количество хранимых у себя строк. Если отправить номер строки, сервер вернёт строку по этому номеру. Сервер работает правильно, 100%. Переписал модель: метод rowCount() отсылает серверу строку "length" и возвращает общее количество строк. Метод data() по идее должен отсылать серверу число, а по этому числу, сервер вернёт указанную строку. Но, если метод rowCount() вызывается и не однократно, то data() не вызывается вовсе. Сейчас приведу код. Прошу сильно не сердиться за кривой код. На данный момент, мне... "лишь бы заработало". Вот код метода rowCount() Код: int NetworkModelRO::rowCount(const QModelIndex &parent) const { Метод data(), вот с ним проблема Код: QVariant NetworkModelRO::data(const QModelIndex &index, int role) const { В чём проблема? Где я допустил ошибку? Название: Re: Модель-представление, работа через сеть Отправлено: BRE от Июнь 30, 2011, 16:56 А что возвращает columnCount?
Ноль? Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июнь 30, 2011, 17:21 columnCount() ?
Я его не переопределял. Согласно документации, по скольку у меня список, переопределять метод columnCount() нет необходимости, нужен лишь метод rowCount(). А...не ужели метод columnCount тоже нужен? Название: Re: Модель-представление, работа через сеть Отправлено: BRE от Июнь 30, 2011, 17:28 Просто пытаюсь понять, почему не вызывается data(). :)
А rowCount возвращает точно не 0? Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июнь 30, 2011, 17:48 вот отладочные данные от rowCount()
строк на сервере 3. Код: stringNetworkMessage.toInt() => 0 Название: Re: Модель-представление, работа через сеть Отправлено: Kolobok от Июнь 30, 2011, 22:29 Вот код метода rowCount() Код: int NetworkModelRO::rowCount(const QModelIndex &parent) const { покажи код слота получения ответа от сервера Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июнь 30, 2011, 22:46 Вот код слота получения ответа от сервера
Код: oid NetworkModelRO::slotReadyRead(){ Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июль 01, 2011, 14:35 Есть какие-нибудь идеи? ... ???
Название: Re: Модель-представление, работа через сеть Отправлено: BRE от Июль 01, 2011, 14:41 Попробуй жестко забить в rowCount, что бы он возвращал 3 и посмотри, будет ли вызываться data.
Название: Re: Модель-представление, работа через сеть Отправлено: ieroglif от Июль 01, 2011, 14:45 а я бы не стал так на прямую обращаться в сеть из методов модели.
отдельный класс висит, работает с серваком.. как оттуда обновления-изменения есть - он подкешировал инфу, и отдал модели.. модель тогда работает быстро и чётко. Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июль 01, 2011, 15:25 Переписал метод rowCount() так, чтобы он возвращал 3. И, действительно, обмен данными пошёл, в представлении отобразились строки. Но тут, к сожалению, тоже, не всё так гладко...
ieroglif, не могли бы Вы рассказать подробнее, желательно с практической точки зрения или предоставить информацию, для реализации описанного Вами метода ? (или пример). Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июль 01, 2011, 15:49 ieroglif, т.е. я правильно Вас понял?
Нужно написать отдельный класс, который возьмёт всё сетевое взаимодействие на себя. В этом "сетевом" классе должны быть методы для получения общего кол-ва строк и получения строки по номеру. Все полученные от сервера данные, сетевой класс хранит в своих полях. А модель лишь запрашивает эти данные через методы rowCount() и data() у сетевого класса. Тогда у меня ещё вопрос: каким образом подобный подход отразится на быстродействии модели? Название: Re: Модель-представление, работа через сеть Отправлено: BRE от Июль 01, 2011, 16:05 По скорости будет тоже самое. Весь код, который был бы в модели переноситься в другой класс "типа модели", который делает все тоже самое.
Кешировать данные на стороне клиента конечно придется, где это будет происходить в классе модели или в специальном отдельном классе псевдомодели не важно. Название: Re: Модель-представление, работа через сеть Отправлено: ieroglif от Июль 01, 2011, 17:58 Тогда у меня ещё вопрос: каким образом подобный подход отразится на быстродействии модели? с моей точки зрения это отразится только в лучшую сторону.если за работу с сетью отвечает сама модель, то тормоза в сети вызовут тормоза в модели и, опасаюсь (исходники не смотрел, так что 100% сказать не могу) что это может вызвать тормоза в гуе. если же за сетевое взаимодействие отвечает отдельный класс, то можно его вынести в отдельный поток, и даже если сеть будет тормозить - на гуе это никак не скажется. Название: Re: Модель-представление, работа через сеть Отправлено: Kolobok от Июль 01, 2011, 18:25 Вот код слота получения ответа от сервера Код: oid NetworkModelRO::slotReadyRead(){ Модель не знает, что число строк изменилось. Посмотри методы void QAbstractItemModel::beginInsertRows ( const QModelIndex & parent, int first, int last ) [protected] void QAbstractItemModel::endInsertRows () [protected] Название: Re: Модель-представление, работа через сеть Отправлено: BRE от Июль 01, 2011, 20:26 с моей точки зрения это отразится только в лучшую сторону. Если view нужно получить данные, которых нет в кеше модели и их нужно забирать с сервера, то совершенно не важно кто и в каком потоке их будет выкачивать. Модель на этот момент все равно должна быть заморожена, вместе с обслуживающим view ну и со всем gui.если за работу с сетью отвечает сама модель, то тормоза в сети вызовут тормоза в модели и, опасаюсь (исходники не смотрел, так что 100% сказать не могу) что это может вызвать тормоза в гуе. если же за сетевое взаимодействие отвечает отдельный класс, то можно его вынести в отдельный поток, и даже если сеть будет тормозить - на гуе это никак не скажется. Как вариант, можно вместо требуемых, но отсутствующих данных, возвращать строку "loading..." и грузить строку с сервера, но это все частности реализации. Название: Re: Модель-представление, работа через сеть Отправлено: ieroglif от Июль 02, 2011, 04:07 Как вариант, можно вместо требуемых, но отсутствующих данных, возвращать строку "loading..." и грузить строку с сервера, но это все частности реализации. ну лично я бы так и сделал - только возвращал бы пустой QVariant(), а "загрузка" писал бы в статус-бареНазвание: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июль 02, 2011, 19:29 Фуууууух, как я уже задолбался... Вожусь-вожусь с этим делом, а почти ничего не выходит...
Нет, нет, уведомлений о загрузке и всего прочего не надо. Я пишу не на показ, а для себя, из практических соображений. Чем проще, тем лучше...для начала... Но Ваша идея мне понравилась, возьму на заметку. Ну так в итоге, стоит ли использовать промежуточный "сетевой" класс? И, если "да", то сетевой класс должен работать на прямую, запрашивая данные у сервера и тут же передавать модели, или запрашивать данные, сохранять их у себя, а модели предоставлять уже сохранённые данные? Название: Re: Модель-представление, работа через сеть Отправлено: ieroglif от Июль 03, 2011, 10:06 Фуууууух, как я уже задолбался... Вожусь-вожусь с этим делом, а почти ничего не выходит... ну какой-то класс по любому должен заниматься кешированием полученых с сервера данных? =) я бы оставил это на сетевой класс.Нет, нет, уведомлений о загрузке и всего прочего не надо. Я пишу не на показ, а для себя, из практических соображений. Чем проще, тем лучше...для начала... Но Ваша идея мне понравилась, возьму на заметку. Ну так в итоге, стоит ли использовать промежуточный "сетевой" класс? И, если "да", то сетевой класс должен работать на прямую, запрашивая данные у сервера и тут же передавать модели, или запрашивать данные, сохранять их у себя, а модели предоставлять уже сохранённые данные? Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июль 03, 2011, 13:05 С классом модели более-менее понятно. А вот с сетевым классом трудности.
Пусть сетевой касс содержит поле Код: private: и методы Код: public: 1) Значит, если модель вызывает метод rowCount(), нужно вызвать метод getRowCount() сетевого класса и вернуть размер вектора, верно? В самом простом виде, получается так: Код: int NetworkModelRO::rowCount(const QModelIndex &parent) const { return networkClass->getRowCount(); } 2) Метод сетевого класса getData() возвращает модели (по вызову метода data()) строку из вектора по указанному индексу. В самом простом виде, без проверок, получается так: Код: QVariant NetworkModelRO::data(const QModelIndex &index, int role) const { return networkClass->getData(index.row()); } Но как быть с заполнением вектора? И как достичь синхронизации данных на сервере и в векторе? Если по каждому вызову метода data(), запрашивать указанную строку с сервера, помещать в вектор и возвращать модели, то в векторе будет полно дубликатов. Если по каждому вызову метода data(), полностью обновлять вектор... ну это тоже не дело. 3) Если модель вызывает метод rowCount() в тот момент, когда сетевой класс ещё не получил данные с сервера и вектор пуст, то метод вернёт 0. Чуть выше я написал отладочные данные от rowCount(). Как быть с этим? Название: Re: Модель-представление, работа через сеть Отправлено: ieroglif от Июль 03, 2011, 19:57 мда.. действительно..
значит однозначно, кешированные данные с сервера хранит модель. в таком случае сетевой класс на какие-то события производит запрос данных с сервера, и сигналит новыми данными модели, которая по этим сигналам уже меняет "кэш" и сообщает вьюхе об обновлении данных. Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июль 14, 2011, 11:30 Извиняюсь за долгое отсутствие.
Возвращаясь к теме обсуждения, хочу сказать, что вызов метода rowCount() в начале несколько раз возвращает 0, а за тем реальный размер. Эта проблема так и не была решена... Отладочные данные показали, что с начала модель несколько раз вызывает метод rowCount() и метод возвращает 0, а лишь ПОТОМ приходят реальные данные с сервера. Вот отладочные данные (в сокращённом виде): Модель вызывает свой метод rowCount(), который вызывает метод getRowCount() сетевого класса. Этот метод возвращает 0 и модель получает значение 0. getRowCount() n => 0 getRowCount() n => 0 Затем видно, что ПОСЛЕ того, как модель получила значение 0, от сервера пришли реальные данные. slotReadyRead() stringNetworkMessage => "3" slotReadyRead() stringNetworkMessage => "3" т.е. получается так, что метод rowCount() вызвался (пусть) 4 раза, 4 раза вернул значение 0, а уже после пришли 4 ответа от сервера... После этого модель делает очередной вызов метода rowCount() и на этот раз получает реальные данные. getRowCount() n => 3 getRowCount() n => 3 slotReadyRead() stringNetworkMessage => "3" slotReadyRead() stringNetworkMessage => "3" Подскажите, что здесь не правильно и как это исправить? Название: Re: Модель-представление, работа через сеть Отправлено: AlphaGh0St от Июль 17, 2011, 22:08 Стоооят все темы на одном месте, и народ оффлайн... вымер что-ли форум?... ???
Есть идеи по поводу метода rowCount() ? Скока вот с ним вожусь, ну ни как не могу понять, в чём дело... Название: Re: Модель-представление, работа через сеть Отправлено: Странник от Июль 18, 2011, 11:23 если для учебных целей, советую для начала написать синхронную реализацию. то есть отправили серверу запрос, дождались ответа с помощью waitForReadyRead, прочли данные и вернули результат. когда осмыслите такой вариант и прочувствуете его недостатки, можно подумать уже над асинхронной реализацией.
|