Страницы

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

понедельник, 6 января 2020 г.

Отказано в доступе при использовании Directory.GetFiles

#c_sharp #net #файлы

Я хочу получить список файлов, которые находятся во вложенных директориях и использую:

Directory.GetFiles(string,string,SearchOption)


Но через какое-то время я получаю ошибку: "Отказано в доступе".

Я посмотрел в дебагере и обнаружил, что Directory.GetFiles натыкается на какие-то
скрытые системные папки, которые мне в принципе не нужны.

Можно ли как-нибудь задать игнорирование подобных папок?

Если я оберну все в try/catch, то боюсь, что я не получу нужны мне список.
    


Ответы

Ответ 1



Взял отсюда private List GetFiles(string path, string pattern) { var files = new List(); try { files.AddRange(Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly)); foreach (var directory in Directory.GetDirectories(path)) files.AddRange(GetFiles(directory, pattern)); } catch (UnauthorizedAccessException) { } return files; } Функция рекурсивная. При составлении списка файлов будут учитываться обыкновенные папки, а системные не учитываться. Не должно быть такого, что из-за Eхception в конечный результат не войдут обыкновенные файлы. Console.WriteLine("Started: " + DateTime.Now.ToLongTimeString()); var fileList = GetFiles("c:\\", "*.*"); Console.WriteLine("Finished: " + DateTime.Now.ToLongTimeString()); Console.WriteLine("Files count: " + fileList.Count); // У меня так: // Started: 12:43:05 // Finished: 12:44:33 // Files count: 427083

Отправка команд на компьютер из Android приложения

#android #cpp #windows #приложение

Здравствуйте, у меня такой вопрос.
Возможно ли из своего Android приложения отправлять команды на компьютер (через Wi-Fi
или Bluetooth), на котором так же будет установлена программа принимающая данные команды
(на C++ к примеру) ?

Если имеет значение ОС на компе, то интересует Windows.

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

Я предполагаю что это возможно, но вот проблема в том что не могу найти как это реализовывается.
Могли бы вы подсказать в какую сторону копать что бы понять как такое можно сделать ?
В какую сторону искать что бы понять как с android приложения отправлять команды,
и в какую сторону искать что бы понять как их принимать на  С++ ?

Спасибо.
    


Ответы

Ответ 1



В случае если компьютер и девайс находятся в одной сети все предельно просто. На компьютере запускается приложение которое прослушивает определенный заранее выбранный порт, например по протоколу UDP. Порт можно выбрать любой от 1 до 65'535, обычно рекомендуют для домашнего использования больше 60'000, т.к. они обычно не заняты. Далее на девайсе посылаем бродкаст на выбранный порт с командой. В самом простом случае это может быть строка с кодовым словом или вообще JSON. Преимущество UDP в том что не обязательно указывать ip адрес получателя, сообщение разошлется по всей сети, но поймет его только тот кто слушает выбранный порт и знает формат команды.

Ответ 2



На C пишется Web-серверер (или используется готовый), на андроиде приложение отправляет ему GET/POST-запросами команды. Я, правда, сразу вижу проблему определения адреса сервера... Можно обойтись и без специального приложения на Android, если все действия будут в браузере выполняться.

Ответ 3



Такое можно написать на сокетах (использовать TCP/IP протокол). Android будет выступать сокет-клиентом, а сервер - сокет-сервером. В таком случае не только Andorid может посылать команды, но и сервер! Реализовать на Web-сервере (протокол HTTP). Кстати, например, вот бесплатный многопоточный веб-сервер: https://github.com/sitev/cjNetwork (сам писал ))) ). Можно взять другой бесплатный, более надёжный, например, мангуста: https://github.com/cesanta/mongoose CGI/FastCGI/SCGI

Ответ 4



Можно через Jabber ботов организовать, можно даже через email

Как добавить игнор лишних файлов в репозиторий github?

#git #github #gitignore

Я создал репозиторий под проект на Java, но не выбрал настройку файла gitignore под
Java-проект.
Как добавить игнор лишних файлов под проект Java в репозиторий github?
    


Ответы

Ответ 1



Создайте в корне файл .gitignore: *.class # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.ear # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* Java.gitignore .gitignore для остальных языков и фреймворков

Расчет количества слов в тексте

#cpp

Необходимо подсчитать количество вхождений каждого слова в тексте.


словом считается любая последовательность символов, каждый из которых не входит в
множество разделителей. Множество разделителей должно задаваться отдельно (строкой).
кодировка - символы однобайтовые
текст находится в файле, имя файла задается первым аргументом командной строки
пример:
test.exe war_and_peace.txt
выводить в stdout, формат <слово> - <сколько раз встретилось>, вывод должен быть
отсортирован по словам в лексикографическом порядке


Допустим есть строка и множество разделителей:

void main()
{
    string mySentense = "one. two three one, one two";
    string spacersЗlurality[] = { ",", "." };
}


Подскажите как хотя бы сделать 4 пункт?
    


Ответы

Ответ 1



Вот демонстрационная программа, которая показыывает один из возможных подходов к решению задания в соответствии с пунктом 4. #include #include #include #include int main() { std::string mySentense = "one. two three one, one two"; const char *delimiters = "., \t"; std::map frequencies; for ( std::string::size_type pos = 0; ( pos = mySentense.find_first_not_of( delimiters, pos ) ) != std::string::npos; ) { auto n = pos; pos = mySentense.find_first_of( delimiters, pos ); std::string word = mySentense.substr( n, pos == std::string::npos ? pos : pos - n ); for ( char &c : word ) c = std::toupper( ( unsigned char )c ); ++frequencies[word]; } for ( const auto &p : frequencies ) std::cout << p.first << ": " << p.second << std::endl; } Вывод программы на консоль: ONE: 3 THREE: 1 TWO: 2 Все, что вам еще нужно сделать, так это считывать файл строка за строкой, используя стандартную функцию std::getline

Грамотное кэширование в NodeJS проекте

#nodejs #кэширование #redis #highload

Планируется highload-проект с использованием NodeJS, MySQL, Redis, NGINX.
За основу взят nodejs фреймворк express, и для работы с сокетами (может это и не
хорошее решение) - socket.io. Проект представляет собой single page application, предполагается,
что сокет-соединение будет открыто повсеместно. Будет большое количество страниц, которые
являются статистично-информативными, и не щадят бд тяжелыми запросами.

Есть несколько вопросов о том, как построить кэширование данных, и где лучше применять
Redis, а где использовать другие способы. 


Например, есть запрос к БД, его результат мы можем сохранить в Redis в виде JSON,
при следующих обращениях уже будем брать его из Redis и, когда необходимо - делать
инвалидацию данного кэша. - Насколько правильно это? И стоит ли именно в JSON хранить
данные?
Нам иногда нужна закэшированная страница не только в JSON, а кусок или целиком HTML.
- Правильно ли хранить эти куски в Redis?
Есть идея реализовать session-storage в Redis, как это сделать правильно? например
ключом будет id сессии, а значением - массив данных о клиенте. - Это правильно или
нет? Как будет лучше?
В каких случаях стоит записывать кэш в файлы на диск?
Стоит ли вообще пихать все что выше описано в redis? 


Я не имею опыта в highload, поэтому мне интересно все, что вы скажете, очень нужны
грамотные советы в построении проекта на перечисленных компонентах. Может, есть какие-то
рекомендации по работе с сокетами в highload, либо еще что-то, что касается основ такого
проекта. 

Признателен за ваши полезные советы, благодарю за внимание!
    


Ответы

Ответ 1



Например, есть запрос к БД, его результат мы можем сохранить в Redis в виде JSON, при следующих обращениях уже будем брать его из Redis и, когда необходимо - делать инвалидацию данного кэша. - Насколько правильно это? На сто процентов, но своевременная инвалидация кэша - довольно большой челлендж. И стоит ли именно в JSON хранить данные? Вообще меня несколько коробит сохранять данные строкой, но особого выбора нет, и вообще это не должно влиять ни на что. Нам иногда нужна закэшированная страница не только в JSON, а кусок или целиком HTML. - Правильно ли хранить эти куски в Redis? Нет, у вас же SPA, весь рендеринг должен быть на клиенте. Есть идея реализовать session-storage в Redis, как это сделать правильно? например ключом будет id сессии, а значением - массив данных о клиенте. - Это правильно или нет? Как будет лучше? Если сессия у вас считается за постоянное хранилище, то неправильно, потому что Redis не предназначен для постоянного хранения данных (хоть и умеет время от времени скидывать данные на диск). Вместо этого лучше организовать двухуровневое (или даже трехуровневое) хранилище из связки Redis - БД (In-Memory - Redis - БД в случае трехуровневой связки). В каких случаях стоит записывать кэш в файлы на диск? Как правило, ни в каких, есть база данных. Туда можно скидывать результаты тяжелых запросов, чтобы все ноды их видели, но даже в этом случае я бы организовывал промежуточный Redis-слой. Стоит ли вообще пихать все что выше описано в redis? Чем больше будет висеть в кэше, тем лучше, но время от времени посматривайте на количество съедаемой оперативной памяти. Может, есть какие-то рекомендации по работе с сокетами в highload, либо еще что-то, что касается основ такого проекта. Помните про две вещи Проект обязан масштабироваться горизонтально, т.е. простым добавлением новых серверов. Из этого вытекает, что изменения на одном сервере должны быть видны для всех остальных (это достигается за счет использования одного Redis и БД) Существует такая штука, как dogpile effect, который означает кучу пользователей, одновременно запросивших один и тот же ресурс. В случае с вышеописанным трехуровневым хранилищем сто синхронно пришедших пользователей не обнаружат запись в кэше и ломанутся (все сто) к БД. В случае, если в БД 20 одновременных подключений, и каждый запрос занимает 30мс, то последний пользователь получит данные не раньше, чем через 150мс (это в идеальном случае, на самом деле там будет значительно большее число), что очень нехорошо.

Что делает данный кусок кода? $(“#table”,$(“.someth”))

#javascript #jquery

Попался возник вопрос в собеседовании: что делает этот кусок кода

$("#table",$(".someth"))


На мой взгляд - это бред, с помощью поиска и документации так же не смог найти.
    


Ответы

Ответ 1



Согласно документации второй параметр - контекст селектора. То есть выполняется как бы подзапрос. Этот вызов аналогичен $(".someth").find("#table"); Соответсвенно будут найдены все элементы с классом someth и, затем, внутри них элементы c id равным table. Страница документации (по-английски); Описание по-русски.

Ответ 2



Пример группового селектора, возвращает набор из элементов, которые удовлетворяют одному из селекторов

Dispatcher не запускает метод в нужном потоке

#c_sharp #wpf #многопоточность

У меня есть WPF окно, по событию которого вызывается комманда ViewModel. Она в свою
очередь вызывает метод из BAL, запускающий дочерний поток(может жить от 10 сек до бесконечности).
Данный поток генерирует события по мере выполнения и еще одно событие в самом конце,
извещающее о конце работы. Тк события происходят не основном потоке, то ViewModel использует
Dispatcher для синхронизации. Если я что-то на проектировал не так, буду рад узнать.
Для выполнения кода в нужном потоке я использую следующий код

Dispatcher.CurrentDispatcher.BeginInvoke(new Action(SomeMethod));


Но этот код не вызывает мне нужный метод в обще. Далее я попробовал вызвать следующий код

Dispatcher.CurrentDispatcher.Invoke(new Action(SomeMethod));


В итоге я все равно получил ошибку, тк выполнение не в главном потоке.
Тестирования ради я объявил поле _dispatcher и инициализировал его в конструкторе
в время работы главного потока. Данный диспетчер мне уже все спокойно вызывал.
С чем это связано и как мне быть? Если я вдруг создам ViewModel не в главном потоке,
то у меня опять работать ничего не будет.
    


Ответы

Ответ 1



Смотрите. Dispatcher.CurrentDispatcher возвращает вам диспетчер для данного потока. Поэтому у вас нету альтернативы хранению ссылки на диспетчер. Затем, VM-объекты обязаны бежать в UI-потоке (иначе вы не сможете биндить к ним View), так что они должны конструироваться тоже в UI-потоке. А значит, вы вполне можете рассчитывать на то, что уж в конструкторе у вас будет правильный Dispatcher.CurrentDispatcher. Почему не работает диспетчер, созданный в фоновом потоке? Диспетчер — это абстракция над циклом сообщений. Если в данном потоке бежит цикл сообщений, то Dispatcher.CurrentDispatcher его вам и возвращает. Если же для данного потока диспетчера нету, создаётся новый и прикрепляется к данному потоку. Но этот диспетчер ещё не запущен! Команда лежит в очереди и дожидается. Если вы запустите диспетчер в фоновом потоке, то все команды, отосланные ему, будут выполнены. Однако, не пытайтесь сделать это в потоке из пула потоков: для работы диспетчера поток должен быть STA, а потоки из пула — не STA (и это нельзя поменять). Ну и по-хорошему обычно вам должно хватать диспетчера в UI-потоке.

MySQL обрезает текст на сложном символе-картинке

#php #mysql #кодировка

Столкнулся со следующей проблемой. Имеем текст

Текст Текст Текст Текст 💲

При вставке в базу MySQL текст обрезается по символ 💲, то есть остается

Текст Текст Текст Текст 


Вставка происходит в коде php:

$text = PHP_slashes($text); // экранируем кавычки
$sql = table}` (`text`) VALUE ('$text')"; $this->db->execute($sql); Попробовал вставить вручную в базу это сообщение - все сработало, только 💲 заменился на ?. Такое поведение вполне устраивает, можно бы и вовсе удалить такие символы из сообщения. Аналогичная проблема на символах 👍 🚑 🎁 и т.д. Можно ли как-то поправить настройки базы или что-то сделать в коде php, чтобы такие символы переводились в ? или удалялись ? P.S.: Больше интересует не конкретное решение замены символов в строке, а настройки на все случаи - чтобы база не резала текст, а как-то его сохраняла, заменяя непонятные ей символы. Update: строка запроса INSERT INTO `mails` (`text`) VALUE ('

Текст Текст Текст Текст \"💲\"

') Только вместо 💲 в текстовом файле отображается квадратик с вопросом


Ответы

Ответ 1



Ваша база сейчас работает в кодировке utf-8 в которой на 1 символ максимум выделяется 3 байта. Из-за этого ваши фигурные символы (а так же символы китайского и японского языков) не могут быть записаны в базу, так как имеют размер 4 байта. Следует перевести базу данных на работу в кодировке utf-8 с поддержкой символов размером до 4 байт. Если MySQL имеет версию ниже 5.5.3, его следует обновить. Сделать полный бекап базы данных. Для перевода базы на 4-x байтный utf-8 нужно выполнить команду ALTER DATABASE название_базы CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci; Для каждой таблицы базы нужно выполнить команду такого вида ALTER TABLE название_таблицы CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; Для каждого поля содержащего текстовую информацию в каждой таблице нужно выполнить команду (примерный вид, зависит от структуры поля) ALTER TABLE название_таблицы CHANGE название_столбца название_столбца VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; Пункты 3-5 можно выполнить например через phpmyadmin. В код php нужно добавить сразу после коннекта к базе выполнение запроса вида SET NAMES 'utf8mb4' COLLATE 'utf8mb4_general_ci' P.S. Про установку кодировки соединения https://ru.stackoverflow.com/a/726863/186083

Ответ 2



Насколько я понимаю Вам вместо знака 💲 и других подобных необходимо использовать его код в html, если html код приходит извне то парсить регуляркой так же по коду...

Ответ 3



Нашел решение. Не совсем то, что хотелось, но пока что работает, хотя я буду ждать более нормальные варианты. function clearText($text) { $text = iconv('utf-8', 'windows-1251//IGNORE', $text); $text = iconv('windows-1251', 'utf-8//IGNORE', $text); return $text; } Эта функция убирает все "фигурные" символы из текста. Решение типа $text = iconv('utf-8', 'utf-8//IGNORE', $text); не работает.

Контроль версий для файлов MS Office, Libre Office и других XML-based

#git #git_config

Хочу хранить в репозитории Git файлы из офисных пакетов вроде MS Office или Libre Office.


Возможны ли какие-то проблемы?
Как правильно организовать хранение? 
Можно ли производить слияние (merge) этих файлов средствами Git? 

    


Ответы

Ответ 1



Возможны ли какие-то проблемы? Есть ряд форматов данных, которые внутри себя устроены как папки/архивы, содержащие текст (xml) и бинарные данные. Список XML-based форматов просто огромен, приведу одни из самых популярных: OpenDocument: .odt, .ods, .odp и прочие. OpenOffice.org XML: .sxw, .sxc, .sxi и прочие. Open Packaging Conventions .docx, .xlsx, .pptx и прочие. Git может распознавать такие файлы как текст. Тогда он Начнет приводить к общему виду окончания строк, При слиянии ветвей соберет один документ из двух, рассчитывая на дальнейшую ручную правку. То и другое испортит файл почти необратимым образом. Из документации Git: gitattributes, "Marking files as binary". Git usually guesses correctly whether a blob contains text or binary data by examining the beginning of the contents. However, sometimes you may want to override its decision, either because a blob contains binary data later in the file, or because the content, while technically composed of text characters, is opaque to a human reader. Как правильно организовать хранение? В корневой директории проекта нужно создать файл .gitattributes (или отредактировать, если уже есть). В него добавить следущую строку — для каждого расширения файлов, которое там будет храниться: *.<расширение> binary Пример: *.docx binary *.xlsx binary *.odt binary Таким образом вы явно отмечаете, что файлы с данным расширением необходимо обрабатывать как бинарные. В бинарном файле Git никогда не будет заменять окончания строк (т.к. для него это теперь не CR и LF, а просто байты). Можно ли производить слияние (merge) этих файлов средствами Git? Если .gitattributes настроен правильно, то можно производить слияние веток, содержащих такие файлы. При слиянии документ не будет испорчен, но и объединить содержимое двух файлов в один автоматически не получится. Однако, PashaPash подсказывает, что в MS Office есть специальный инструмент для слияния файлов. После того, как вы вручную собрали из двух документов один (или выбрали одну из версий), нужно проиндексировать изменения и подтвердить их коммитом, чтобы завершить слияние.

Как узнать какой тип Fragmenta в Android?

#java #android

Всем привет.

Есть три вида Фрагментов.

    ArtistFragment artistFragment = new ArtistFragment();
    AlbumFragment albumFragment = new AlbumFragment();
    SongFragment songFragment = new SongFragment();


Fragment один из трех выше предложенный возвращается с помощью функции.

Fragment fragment = pagerAdapter.getItem(position);


Как узнать какой Fragment вернулся? Смутно помню в Java была такая функция instanceOF?
    


Ответы

Ответ 1



Есть два способа узнать класс фрагмента. Можно, как вы сами уже сказали, методом instanceof: Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container); if (f instanceof CustomFragmentClass) //что-то сделать с f А можно прикреплять к фрагменту специальный тэг, который будет уникальным для фрагмента каждого типа: fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT"); В последствие, по этому тэгу вы сможете понять тип фрагмента: MyFragment f = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT"); if (f!= null && f.isVisible()) //что-то сделать с f

Ответ 2



Да, можно с помощью instanceof. Например Fragment fragment = pagerAdapter.getItem(position); if(fragment instanceof SongFragment) { //SongFragment } else { //другой фрагмент} Ещё можно имя класса получить так: Fragment fragment = pagerAdapter.getItem(position); String className=fragment.getClass().getSimpleName();

Ответ 3



ну да можно: Fragment fr = pagerAdapter.getItem(position); if ( fr instanceof ArtistFragment) { // } else if ( fr instanceof AlbumFragment) { // } else if ( fr instanceof SongFragment) { // } а можно простой проверкой класса: Fragment fr = pagerAdapter.getItem(position); if ( fr.getClass() == ArtistFragment.class) { // } else if ( fr.getClass() == AlbumFragment.class) { // } else if ( fr.getClass() == SongFragment.class) { // }

Ответ 4



Да конечно можно проверить с помощью instanceof, получится что то вроде Fragment fragment = pagerAdapter.getItem(position); if (fragment instanceof ArtistFragment) { ...; } else if (fragment instanceof AlbumFragment){...} Но вроде как использование instanceof не есть хорошо. Как вариант можно у фрагментов устанавливать тэг, и по нему уже узнавать какого типа фрагмент.

Ответ 5



Можно так: if (fragment instanceof ArtistFragment) { //some actions for ArtistFragment } else if (fragment instanceof AlbumFragment) { //some actions for AlbumFragment } else if (fragment instanceof SongFragment ) { //some actions for SongFragment }

Как часто стоит просчитывать путь от мобов к игроку? Поделитесь идеями

#javascript #разработка_игр

  http://smartcook.info/testgame/test2.html


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


Ответы

Ответ 1



Когда-то писал игру вроде пакмана, поделюсь соображениями. Максимальная частота пересчета ограничена тем, насколько часто мобы могут поворачивать. Насколько я понимаю, пока они идут из одной клетки в другую, смена марштута невозможна. Значит, пересчитывать путь нужно не чаще, чем тогда, когда моб полностью пришел в клетку, т.е. находится в её центре. Максимальная частота также ограничена производительностью устройства, как верно отметил php5engineer в соседнем ответе. Минимальная частота пересчета задает «агрессивность» мобов и определяет геймплей. Это может быть, например: На каждой клетке — очень злой преследователь На каждой 10й клетке — довольно-таки инертный преследователь, как бык в корриде. На каждой 5й и только если персонаж игрока находится в радиусе R клеток. Раз в 2 секунды вне зависимости от скорости моба

Ответ 2



как часто стоит просчитывать путь к игроку, потому как ресурсозатратно До полного исчерпания этих ресурсов? Или до определенного процента. Например, не более 70% CPU. Или по времени - не более 1/24 секунды. Но это всё общие советы. Как это делается на JavaScript, описано здесь

Ответ 3



Лови две сносные идеи: 1) Если поле небольшое, стенки во время игры не создаются и мобы респаунятся в одной точке можно вообще всего 1 раз при загрузке просчитать путь в каждую точку поля. Тогда в худшем случае придется искать маленький путь до следующего пути в списке. 2) Можно гонять их по графу из вейпоинтов тем же А*, а А* для реального поля просчитывать только если расстояние до игрока критически уменьшилось.

Не идёт поиск если искомая строка начинается с не входящих в регексп

#javascript #регулярные_выражения #exec

Здравствуйте!

Моя задача состоит в поиске 2х групп в строке:


+
последовательность # и 0




var regex = /(\+?)((?:#*\s?)*(?:0*\s?)*(?:[.,])?(?:0*\s?)*(?:#*\s?)*)/;

var goodStr = '+#####0.00#######)';
var badStr = '(+#####0.00#######)';

console.log(regex.exec(goodStr));
console.log(regex.exec(badStr));




Проблема состоит в том, что если в строке содержится искомое значение и после него
идут символы, я получаю результыты по обоим группам, но если символы перед искомой
строкой, не получаю никаких результатов.

Почему такое поведение, ведь я не указываю ему поиск с начала строки?

Заметил, что такая ситуция лишь при использовании группировки.
    


Ответы

Ответ 1



Пустая строка подходит под твою регулярку, поэтому она и выбирается. Поиск делается с самого левого из вхождений. Самое левое - это пустая строка в нулевой позиции - её ты и получаешь. Рекомендую как-то переделать регулярку, чтобы пустая строка не являлась корректным вариантом.

Как реализовать вывод списка статей

#java #android

Добрый вечер!
Каким образом реализовать вывод списка статей? Приложение получает JSON ответ от
сервера вида:

{"id":1,"message":"Тут статейка","rating":"0"}
{"id":2,"message":"Тут статейка 2","rating":"0"}
{"id":3,"message":"Тут статейка 3","rating":"0"}


Всего статей в базе около 500шт. 
Мне нужно чтобы на страницу в приложении выводились 10 статей, при нажатии кнопки,
эти 10 статей заменялись следующими 10-тью, и так далее.

Я думая для этого использовать ListView, но не совсем понимаю как заменять статьи
при нажатии кнопки, ведь чтобы загрузить следующие 10 статей, приложение должно получить
ответ от сервера с id следующих 10-ти статей. 

Прошу помочь идеей реализации подобного. Или может каким нибудь другим способом это
сделать.

P.S. Я не прошу код писать, а лишь идею реализации подобного!
    


Ответы

Ответ 1



Кроме текста статей обычно в json есть и названия. Их и показывают в списке. А сами тексты в другой Activity. ListView уже немного устарел. Вместо него сейчас используют RecyclerView. Следующая партия материалов обычно загружается, когда последний из имеющихся элементов списка появляется в области видимости. Новые элементы при этом не заменяют старые, а добавляются в конец списка.

delete [] и перемещения

#cpp #language_lawyer

int* a = new int[4];
++a;
--a;
delete [] a;


Будет валидным такой код?

А вот такой:

int* a = new int[4];
++a;
delete [] a;


Необходимо просто что бы какой нибудь указатель указывал на начало динамического
выделенного массива? И как распознается длинна массива которую нужно уничтожить? 

Может быть по типу? Но указатель указывает только на первый элемент в массиве, int*,
а не ( * a)[4]. И как можно привести во втором коде int* к (*a)[4]? Почему нет неявного
приведения?
    


Ответы

Ответ 1



Данный фрагмент кода совершенно корректный, так как оператор delete использует значение, хранящееся в указателе, которое равно значению, ранее полученному с использованием оператора new. int* a = new int[4]; ++a; --a; delete [] a; Для оператора совершенно неважно, какое до этого в указателе было значение, и как оно изменялось. Чтобы это сделать еще более наглядным то вы можете написать, например, int x; int *px = &x; int* a = new int[4]; px = a; a = &x; delete [] px; Однако данный фрагмент кода int* a = new int[4]; ++a; delete [] a; некорректный, так как указатель a не содержит адрес выделенной динамически памяти. delete и free должны применятся к значению указателя полученому по new или malloc: это требование стандарта. Обычно "под капотом" оператора new делается следующее. К запрашиваемому размеру памяти, который вы хотите выделить, добавляется к началу блока префикс, который будет хранить этот размер блока памяти. И адрес этого префикса просто вычисляется как смещение на размер слова (обычно sizeof( int) ) от начала участка памяти, адрес которой возвращается пользователю оператора new. Это значение используется, чтобы при удалении памяти правильно оценить ее размер. Что касается вашего второго вопроса, то вы можете написать, например, int* a = new int[4]; int ( *p )[4] = reinterpret_cast( a );

Ограничение на установку android-приложения

#android_sdk #android

Имеются следующие вопросы:
1. Можно ли как-то ограничить установку на, например, телефоны с API ниже 15?
Вопрос заключается не в том, чтобы запретить вывод в поиске по Маркету, а именно
запрет на установку. То есть, имея установочный файл, user не сможет установить его
из-за низкой версии.
2. Можно ли ограничить установку по разрешению экрана? Например, пользователям с
mdpi  и ldpi запретить установку уже имеющегося apk-файла? 
    


Ответы

Ответ 1



Да, можно. Для ограничения по уровню API в манифесте есть тег uses-sdk с атрибутом android:minSdkVersion (документация) Для ограничения по разрешению экрана (документация): ... ...

ignoring option MaxPermSize=512m при запуске Scala

#java #jvm #scala

Установил Play фрэймворк, и при запуске проекта выдается ошибка:


  Java HotSpot(TM) 64-Bit Server VM warning:
  ignoring option MaxPermSize=512m; support was removed in 8.0


Как исправить?


  [error]Server access Error: Connection timed out: connect url=http://repo.scala-sbt.org/scalasbt/sbt-plugin-releases/com.typesafe.sbt/sbt-native-packager/scala_2.10/sbt_0.13/0.6.4/ivys/ivy.xml


Я так понял, он пытается что-то скачать, но доступа нет из-за этой ошибки?

ОС: Windows 8
Версия Play: play-2.2.6
Версия Java: 1.8.

Нельзя ли по-другому это обойти?
    


Ответы

Ответ 1



Первое - это не ошибка, а предупреждение. Второе. Установить прокси в браузере недостаточно, его нужно установить на уровне операционной системы. Вы не указали какую используете ОС и версию Play, поэтому могу предложить воспользоваться общим решением через activator. Запустите его так: activator -Dhttp.proxyHost="your proxyname" -Dhttp.proxyPort="your port" -Dhttps.proxyHost="your proxyname" -Dhttps.proxyPort="your port" Дополнительно может потребоваться установить параметры proxyUser и proxyPassword Обновление Для Windows 8 и Play 2.2.6 можно решить проблему воспользовавшись этой инструкцией в документации, а именно: Еслы вы находитесь за прокси, убедитеcь что установлено для Windows set HTTP_PROXY=http://<логин>:<пароль>@<хост>:<порт> От себя отмечу, что логин и пароль может и не нужен, если прокси его не требует.

Ответ 2



Вы можете попробовать установить offline := true в файле build.sbt. Во многих случаях так работает.

Ответ 3



Все просто, хоть я и сам потратил какое-то время на решение этой задачи: 1-перейти в каталог cd opt/glassfish4/bin/ 2-запустить с ROOT правами sudo ./asadmin start-domain 3-остановка сервера тоже с ROOT правами sudo ./asadmin stop-domain В вашем случае все должно заработать.

Не обновляется ListView

#c_sharp #wpf

Есть ObservableCollection, и есть ListView, который бандит элементы из
этой самой коллекции. Дальше, есть метод, в котором происходит следующая штука:

Resistances = new ObservableCollection(newList);


где Resistances - это объект ObservableCollection, связанный с ListView.
Так вот проблема: ListView не хочет обновляться после этого, хотя, вроди-как, произошла
замена коллекции и ListView должен был бы перерисоваться.

P.S. Вот так, например, работает. ListView корректно обновляется:

Resistances.Clear();
foreach (Quantity q in newList)
{
    Resistances.Add(q);
}


Так почему же не работает первый вариант - при замене всего списка? Разве не происходит
событие CollectionChanged?
    


Ответы

Ответ 1



Вероятно, ваше свойство Resistances не бросает событие PropertyChanged. Для того, чтобы обновление данных сработало нужно, чтобы ваше свойство выглядело примерно так: public ObservableCollection Items { get { return _items; } set { if (_items != value) { _items = value; OnPropertyChanged("Items"); } } } private ObservableCollection _items; XAML: UPDATE Да, вы верно поняли. У Вас получается примерно следующее: Вы создаете свойство-коллекцю и привязываете его к ListView Вы создаете новую коллекцию и присваиваете ее свойству, однако привязка не обновляется, т.к. формально ваше свойство не изменилось (не было брошено PropertyChanged). Я предпочитаю использовать ленивую инициализацию коллекций без setter'ов (возможно, вам такой подход будет интересен): public ObservableCollection Items { get { return _items ?? (_items = new ObservableCollection()); } } private ObservableCollection _items; А потом очищать и заполнять ее данными.

Ответ 2



ListView не знает о том, что коллекция заменена. Нужно вызвать OnPropertyChanged('Resistances') или другой способ дернуть событие PropertyChanged.

Delphi XE2: «Лишние» строки в исполняемом файле

#delphi #exe #delphi_xe2 #executable

Скомпилировал программу в режиме Release. Вся отладочная информация при компиляции
отключена.
Запустил программу, открыл ее свойства в Process Explorer
На закладке Strings вижу, что Process Explorer нашел много строк, которые являются
названиями модулей Delphi, названиями классов, названиями процедур и функций.

Подскажите пожалуйста, как можно удалить из релизного exe-шника все лишние данные???
    


Ответы

Ответ 1



1) В dpr файле между ключевым словом program и разделом uses напишите: program XXX; {$WEAKLINKRTTI ON} // если вам не нужны новые возможности RTTI! {$RTTI EXPLICIT METHODS([]) FIELDS([]) PROPERTIES([])} // если вам не нужны новые возможности RTTI! uses ... 2) В dpr файле после раздела uses можно еще добавить: {$IFNDEF DEBUG} {$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED} // Удаление из exe таблицы релокаций. {$SetPEFlags IMAGE_FILE_DEBUG_STRIPPED} // Удаление из ехе Debug информации {$SetPEFlags IMAGE_FILE_LINE_NUMS_STRIPPED} // Удаление из exe информации о номерах строк {$SetPEFlags IMAGE_FILE_LOCAL_SYMS_STRIPPED} // Удаление local symbols {$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP} //При запуске exe с компакта, флэшки, других извлекаемых устройств, считать exe в свап и запустить оттуда. Полезно, если нужно запустить программу с компакта, а потом попросить вставить другой... {$SetPEFlags IMAGE_FILE_NET_RUN_FROM_SWAP} // Аналогично предыдущей, только для сетевых дисков {$ENDIF} При этом в uses должен присутствовать модуль Windows. Это значительно уменьшит размер исполняемого файла и уберет "лишнюю" информацию из него.

Ответ 2



Сомневаюсь, что эти данные лишние. Delphi при сборке обычно прикомпилирует некоторые "свои" модули к программе. Это можно отключить в настройках компилятора. Но, тогда придётся всегда "таскать" с программой все необходимые компоненты в виде .bpl включая те же кнопки и т.д. (смотря какие модули отключите) Вообще, релиз - это максимум что может дать компилятор. Большей экономии размера можно достичь, например, как уже говорилось, вынеся всё из экзешника ("таская" .bpl) или отказавшись от VCL (FireMonkey) в пользу чистого WinAPI (если это действительно оправдано).

Как сохранить архив с acl ntfs из под linux?

#linux #windows #файлы #ntfs #archive

Как скопировать файл/папку на разделе ntfs в архив с сохранением всех атрибутов?

При условии, что раздел смонтирован из-под linux. Аналог tar -cvf --same-permissions.

С разделами проблем нет - нужно копировать именно отдельные папки и файлы.
    


Ответы

Ответ 1



Это невозможно, так как драйвер NTFS под Linux не поддерживает виндовозные ACL.

Ответ 2



ответ из комментария: Под Windows rar и 7z умеют сохранять права и альтстримы NTFS (при указании соответствующего ключа). Под linux же этот функционал, естественно, вырезан за ненадобностью. Возможно, в самбе есть какой-то аналог ключей /save и /restore утилиты icacls, позволяющей сохранять/восстанавливать ntfs-атрибуты в отдельный файл - тогда архивировать вместе с правами не будет проблемой.

Определение координат мыши в canvas

#javascript #html #canvas

Как определить значения x, y при нажатии мыши на ? И чтобы эти значения были
у переменой сразу.



var example = document.getElementById("example"),
        ctx = example.getContext('2d');
example.width = 300; //высота
example.height = 300; //ширина
for (x = 0; x < 300; x += 100) { //поле крестиков ноликов
    for (y = 0; y < 300; y += 100) {
        ctx.strokeRect(x, y, 100, 100);
    }
}
pic = new Image();
pic.src = "нолик.png";
//pic.onload = function() {
    //example.onmouseup = ctx.drawImage(pic, 101, 1);
//}
//нужна функция
Обновите браузер



    


Ответы

Ответ 1



example.addEventListener('mouseup', function (e) { var x = e.pageX - e.target.offsetLeft, y = e.pageY - e.target.offsetTop; ⁄⁄....... });

Ответ 2



Решением из принятого ответа следует пользоваться с осторожностью, если масштаб элемента (css zoom не работает в последних firefox) не 100%, то положение мыши относительно логических пикселей в canvas сбивается, точнее так же масштабируется, как и элемент: [...document.querySelectorAll('canvas')].forEach(canvas => { var ctx = canvas.getContext('2d'); canvas.addEventListener('mousemove', function (e) { var x = e.pageX - e.target.offsetLeft, y = e.pageY - e.target.offsetTop; ctx.clearRect(0,0,100,100); ctx.beginPath(); ctx.arc(x,y,5,0,Math.PI*2,true); ctx.stroke(); }); }); canvas { border: 1px solid black; } Бороться с этим можно вот так: let z = window.getComputedStyle(canvas).zoom; var x = e.pageX/z - e.target.offsetLeft, y = e.pageY/z - e.target.offsetTop; [...document.querySelectorAll('canvas')].forEach(canvas => { var ctx = canvas.getContext('2d'); canvas.addEventListener('mousemove', function (e) { let z = window.getComputedStyle(canvas).zoom || 1; var x = e.pageX/z - e.target.offsetLeft, y = e.pageY/z - e.target.offsetTop; ctx.clearRect(0,0,100,100); ctx.beginPath(); ctx.arc(x,y,5,0,Math.PI*2,true); ctx.stroke(); }); }); canvas { border: 1px solid black; }

JpaRepository + Hibernate + OneToMany вылетает LazyInitializationException

#java #spring #hibernate #jpa #spring_data

реализую отношение one-to-many по этому туториалу а также этому спринговому туториалу.
Я НЕ использую сессии и прочий hibernate напрямую, я использую JpaRepository и аннотации
JPA. Есть объекты Owner (one) & Book (many):

первая таблица:

@Entity
@Table(name = "owners")
public class Owner implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "owner_id", nullable = false, unique = true)
    private Long id;

    @Column(name = "owner_name", nullable = false)
    private String name;

    @OneToMany(fetch = FetchType.LAZY,mappedBy = "owner")
    private Set books= new HashSet<>(0);

    public Worker() {
    }
}


вторая таблица: 

@Entity
@Table(name = "books")
public class Book implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_id", unique = true, nullable = false)
    private Long id;

    @Column(name = "book_name", nullable = false, unique = true)
    private String name;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "owner_id")
    private Owner owner;

    public Task() {
    }
}


слой репозиториев стандартный, без реализации:

public  interface OwnerRepository extends JpaRepository {}

public  interface BookRepository extends JpaRepository {}


Owner service: (book service такой же)

@Service
@Transactional
public class OwnerServiceImpl implements OwnerService {

    @Autowired
    private OwnerRepository ownerRepository;

    @Override
    public Owner create(Owner owner) {return ownerRepository.save(owner);}

    @Override
    public Owner read(Long id) {return ownerRepository.findOne(id);}

    @Override
    public List readAll() {return ownerRepository.findAll();}

    @Override
    public void delete(Owner owner) {ownerRepository.delete(owner);}

}


Создав два класса service, я захотел протестить их. Создал несколько Owner,Book ну
и пытаюсь связать их как указано здесь, т.е. добавляю в объектe Owner в Set новую книжку,
а в объект Book обновляю ссылку на Owner. Сохраняю в репозиторий сначала Owner, затем
Book. Затем пытаюсь прочитать Owner из репозитория, а во время обращения к полю выдаёт 


  unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException'
exception.


может я вообще неправильно работаю с репозиторием и JPA? как нужно сохранять/обновлять
ссылки в сущностях?

===UPDATE===

мне кажется я решил проблему, использовав @NamedEntityGraph & @EntityGraph.
Я аннотировал Owner 

@NamedEntityGraph(name = "Owner.books",
    attributeNodes = @NamedAttributeNode("books"))


Но в интерфейсе репозитория пришлось переопределить стандартные методы:

@Override
@EntityGraph(value = "Owner.books", type = EntityGraph.EntityGraphType.LOAD)
List findAll();


@Override
@EntityGraph(value = "Owner.books", type = EntityGraph.EntityGraphType.LOAD)
OwnerfindOne(Long aLong);


Тоже самое сделал с Book. Когда я делаю запрос из репозитория Owner на считывание
объекта, всё загружается нормально - ссылки в Set ссылаются на объекты Book. 
Но когда я делаю запрос к Book репозиторию - объект Book имеет ссылку на Owner, НО
в этом внутреннем Owner ссылки на дополнительные книги бросают LazyInitException. Почему?
ссылки просматриваю в Idea на брек поинте.
    


Ответы

Ответ 1



У вас стоит fetch = FetchType.LAZY это значит, что хибернейт не будет инициализировать эти поля пока вы к ним не обратитесь. Но т.к. вы обращаетесь к этим полям за пределами транзакционных методов, он не может это сделать и выкидывает ошибку. Чтобы этого избежать надо, что метод, который обращается к этим полям был с аннотацей Transactional. В вашем случае это EntitiesServicesTest.ooops(). Либо можно немного изменить реализацию OwnerServiceImpl.read(). Сделать такое: @Override public Owner read(Long id) { Owner owner = ownerRepository.findOne(id); owner.getBooks().iterator(); return owner; } Или как предложили в комментариях: Hibernate.initialize(owner.getBooks()); Это хак, но он заставит хибернейт инициировать коллекцию. НО! Возможно это не всегда надо и тогда надо выбрать первый вариант и отталкиваться от здравого смысла, смотреть, где надо навешивать аннотацию, а где нет.

Ответ 2



Стоит также упомянуть, что fetch type по дефолту как раз LAZY. Я для решения проблемы поставил fetch = FetchType.EAGER и всё заработало.

IDEA сгенерировала equals помогите разобраться

#java #intellij_idea

IDEA сгенерировала код, мог бы кто-то построчно его прокомментировать. Не понимаю,
как он работает. 

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Pair pair = (Pair) o;

    if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
    return !(second != null ? !second.equals(pair.second) : pair.second != null);

}

    


Ответы

Ответ 1



@Override public boolean equals(Object o) { //Если объект, с которым происходит сравнение, этим же объектом и является, то они равны. Сравнивает ссылки текущего объекта и принятого как аргумент. if (this == o) return true; //Если принятый объект null или другого класса, то возвращает false, не равны. При o == null они не равны, т.к. у null не может быть метода equals. Следовательно основной объект не null. if (o == null || getClass() != o.getClass()) return false; //кастует 'o' в Pair pair, чтобы иметь доступ к методам. Pair pair = (Pair) o; //Проверяет что свойство first текущего объекта не равен null. Если не равен, то сравнивает first текущего объекта, с pair.first. В случае, если они не равны, то ! инвертирует в true и условие if выполняется. Выполнится return false. Объекты не равны. //Если first равен null, то проверяет pair.first. Если pair.first не равен null, то объекты не равны, возвращает false. if (first != null ? !first.equals(pair.first) : pair.first != null) return false; //Проверяет, что second не равен null. //Если не равен, то сравнивает second с pair.second. //Если second == pair.second, то сначала первый ! в "!second.equals(pair.second)" инвертирует его в его в false, а второй !, который идет сразу после return, инвертирует в true. Значит вернет true, объекты равны. //Если second == null, то проверяет второе условие. Если pair.second != null, то вернет true, который инвертируется в false. return !(second != null ? !second.equals(pair.second) : pair.second != null); } В общем, почитайте про тернарный оператор ?:. Это короткий вариант if-else. Обновление В Java все, кроме примитивов (int, char и т.п.), является объектом и наследуется от класса Object, т. е. объект любого класса можно привести к Object, будь то String, ArrayList, Integer или MyClass. На предыдущей строке идет проверка, что оба сравниваемых объекта принадлежат 1 классу getClass() != o.getClass(). Если программа проходит эту строку, значит они одного класса, соответственно имеют одинаковые свойства и методы. Для того, чтобы привести объект класса Object к другому классу, используется кастование(cast). String str = (String) object; Читайте про наследование.

как восстановить состояние после git rebase [дубликат]

#git

        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Git откатить rebase [дубликат]
                                
                                    (2 ответа)
                                
                        
                                Закрыт 3 года назад.
            
                    
Предиcтория фейла:

В origin master было 10 нормальных коммитов. Понадобилось 3 коммита извлечь из истории,
а потом перенести в отдельный баранч

Вот мои действия

git checkout master
git branch test
git rebase -i HEAD~10 //удалил 3,9 и 10 коммит (условно hash: aaaaa,bbbbb,ccccc)
git push -f origin master
git checkout test
git rebase -i HEAD~10 //удалил 4,5,6,7,8 тоесть промежуточные


В это время мастер пошел вперед. Решив что пора вылить ветку test в origin, но что
бы потом сливать ветку было проще решил подлить в нее мастер но ребейсом

git checkout test
git pull --rebase origin master


Расчитывал что мои три коммита просто перетянуться вверх истории, так как предок-коммит
был. Но после кучу странных конфликтов в истории отсуствует один коммит (aaaa)

Два вопроса


В чем я ошибся и почему все так сломалось?
Что делать, как востановить утерянный коммит?

    


Ответы

Ответ 1



Ответ для второго пункта: все просто git reflog, находим состояние проекта до пула (например 3 шага назад) и делаем git reset --hard HEAD@{3}. Можно так же и бранч временный создать, чтобы поразбираться.

Как в объекте типа data.frame отобрать переменные только одного типа?

#r #dataframe

Например, имеется большой массив данных >100 переменных. А мне необходимо отобрать
 лишь количественные. Как можно сделать подобное?
    


Ответы

Ответ 1



Предварительно стоит изучить структуру данных с помощью функции str(). Выполнить поставленную Вами задачу можно следующим образом: sapply(DF, is) # классы столбцов DF[, sapply(DF, is.numeric)] # все столбцы класса numeric DF[, sapply(DF, is.factor)] # все столбцы класса factor DF[, sapply(DF, is.character)] # все столбцы класса character Можно также использовать комбинацию sapply + which: DF[, which(sapply(DF, is.numeric))]. В некоторых случаях данный вариант показывает более высокую производительность. Также стоит отметить, что для числовых переменных могут применяться разные классы: integer (целые числа), double (числа с плавающей запятой) или numeric (включает в себя два предыдущих типа). Это может пригодиться, если, например, необходимо отфильтровать только столбцы, содержащие целые числа.

Ответ 2



df_numeric <- df[ , sapply(df, is.numeric)] Создание нового дата фрейма df_numeric только с количественными данными из исходного df. is.numeric проверяет столбцы на предмет того, являются ли они количественными

Правила для определения четных/нечетных с игнорированием определенных блоков

#css #html5

Имеем такую разметку:

...
...
...
...
...
...
...
...
Необходимо стилизовать классы list по принципу четности/нечетности, но игнорируя класс ignore, т.е. так:
...
...
-- нечетный
...
...
...
-- четный
...
...
-- нечетный
...
-- четный
Простые event/oddдля .list:nth-child не подходят, т.к после .ignore отсчет начинается сначала.


Ответы

Ответ 1



Альтернативный вариант, если не брать за основу классы - использовать :nth-of-type, который в принципе аналогичен :nth-child, только применяет правило дополнительно привязываясь к тегу(типу), а не всем дочерним элементам. Собственно чтобы этим воспользоваться, все игнорируемые элементы должны быть заключены в тег, отличный от основного тега для подствечиваемых элементов. Например HTML:

...

...

...

...

...

...

...
...
Стили, где у всех div.list цвет будет чередоваться независимо от их позиции в родителе: .list { background: red; } .list:nth-of-type(odd) { background: green; } Пример на JSBin

Ответ 2



на css наверное только так Fiddle .container { width: 200px; } .list, .list ~ .list ~ .list, .list ~ .list ~ .list ~ .list ~ .list, .list ~ .list ~ .list ~ .list ~ .list ~ .list ~ .list { background: #00f; } .list ~ .list, .list ~ .list ~ .list ~ .list, .list ~ .list ~ .list ~ .list ~ .list ~ .list, .list ~ .list ~ .list ~ .list ~ .list ~ .list ~ .list ~ .list{ background: #f00; }
Ignore
Odd
Ignore
Ignore.
Even
Ignore
Odd
Even


Ответ 3



С JS это можно, например, сделать следующим образом Odd-even
Ignore
Odd
Ignore
Ignore.
Even
Ignore
Odd
Even


Почему reactjs setState возвращает предыдущее значение?

#javascript #reactjs

Мне нужно изменять state по клику. У меня есть такой код:

var Component = React.createClass({
   getInitialState : function() {
      return {value : 0}
   }
   changeState : function(event) {
      this.setState({value : event.target.id}) ;
   }
   render : function() {
      Change
   }
}) ;


Но изменение срабатывает только после первого клика, первый клик я получаю 0, второй
клик, я получаю 1.

Я перечитал доку где сказано не использовать setState напрямую, поэтому я использовал
replaceState, но и он по прежнему возвращает предыдущее значение. Как с этим бороться?
    


Ответы

Ответ 1



У setState есть довольно редко упоминаемый второй параметр, который является обычной callback функцией. Вы можете отлавливать новое состояние компонента уже там this.setState({/* new state */}, callback). var Component = React.createClass({ getInitialState : function() { return {value : 0} } changeState : function(event) { this.setState({value : event.target.id}, function() { /* Получаем измененное значение state */ console.log(this.state.value); }) ; } render : function() { return Change } }) ; Либо формируем новый объект state, а только потом записываем его: var Component = React.createClass({ getInitialState : function() { return {value : 0} } changeState : function(event) { /* формируем новый state */ let nextState = Object.assign({}, this.state, { value: event.target.id }); /* получаем будущее значение state */ console.log(nextState.value); /* записываем новый state */ this.setState(newState); } render : function() { return Change } }) ; Недавно делал небольшой перевод про работу state. Возможно пригодится

Ответ 2



Судя по всему, вы столкнулись с тем, что значение this.state меняется не мгновенно после вызова this.setState(). В тоже время, такое поведение является штатным (см. документацию): setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. Есть у меня такое чувство, что вы неправильно используете состояние компонента. К сожалению, без нормального описания исходной проблемы давать какие-то советы бессмысленно.

Лучший и быстрый вариант проверить наличие текста в массиве

#java #производительность

Здравствуйте, не стану объяснять в чём смысл всего этого кода, и сразу приступлю
к проблеме.

Если bar - ArrayList, то операция завершается за 22 секунд, С LinkedList >30 сек.
Есть ли другие варианты проверять наличие значения в массиве?
Производительность для меня очень важна :)

Есть код:

    final long time = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        foo("test");
    }
    final long endTime = System.currentTimeMillis();
    System.out.println("Time: " + (endTime - time) + " ms");


Метод foo:

public static boolean foo(String s){
    /*Всякий код*/
    return bar.contains(s);
}

    


Ответы

Ответ 1



Используйте HashSet. ArrayList: 14475 ms HashSet: 43 ms Sorted ArrayList: 540 ms Код: long time = 0; ArrayList strings = new ArrayList(); Random rand = new Random(); for (int i = 0; i < 1000; i++) { strings.add(String.valueOf(rand.nextInt())); } time = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { strings.contains("test"); } long endTime = System.currentTimeMillis(); System.out.println("ArrayList: " + (endTime - time) + " ms"); HashSet hashSet = new HashSet(strings); time = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { hashSet.contains("test"); } endTime = System.currentTimeMillis(); System.out.println( "HashSet:" + (endTime - time) + " ms"); Collections.sort(strings); time = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { Collections.binarySearch(strings,"test"); } endTime = System.currentTimeMillis(); System.out.println("Sorted ArrayList:" + (endTime - time) + " ms");

Как изменить размер CardView с анимацией?

#android #android_sdk #material_design #android_ui

У меня есть layout в котором есть CardView внутри которого лежит, скажем, картинка.

Я хочу увеличить высоту и ширину этой CardView вместе с анимацией так как это делают
в Material Design Guidelines

Я пробовал 2 способа:


cardView.animate().scaleX().scaleY() - этот способ изменяет размер CardView но вместе
с ним и изменяется размер всего, что внутри его даже если у содержимого выставлена
специфичная ширина и высота;
можно сделать cardView.getLayoutParams() и потом изменить height и width или можно
добавить margin - это действительно меняет размер, но непонятно как это анимировать.


Весьма странно, но я не нашел никаких стоящих рецептов в гугле.
    


Ответы

Ответ 1



Можно воспользоваться вот этим способом с gitHub-а: Создаём анимацию изменения параметров View: public class ResizeAnimation extends Animation { final int startWidth; final int targetWidth; View view; public ResizeAnimation(View view, int targetWidth) { this.view = view; this.targetWidth = targetWidth; startWidth = view.getWidth(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { int newWidth = (int) (startWidth + (targetWidth - startWidth) * interpolatedTime); view.getLayoutParams().width = newWidth; view.requestLayout(); } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); } @Override public boolean willChangeBounds() { return true; } } Применяем её: ResizeAnimation resizeAnimation = new ResizeAnimation(view, targetSize); resizeAnimation.setDuration(600); view.startAnimation(resizeAnimation);

Поставить третью систему

#linux #windows #grub

Есть Windows 7 и Linix. Хочу дополнительно к ним поставить Windows 10.

Вопрос, надо ли что-то делать с grub'ом переду установкой Win10? Или можно по стандартной
схеме просто поставить Win10, затем загрузиться с LiveUSB, откуда установить и настройть
grub? Или же следует сначала откатиться от grub'а до виндового загрузчика, чтобы Win10
при установке смог его определить?

Повторю, что в итоге я хочу получить Win7 + Linux + Win10.
    


Ответы

Ответ 1



После того, как вы установите Windows 10 (не повреждая файлы других ОС) нужно будет загрузиться с Linux и выполнить boot-repair в терминале. Не зависимо от того, увидит десятка семёрку или нет (хотя по идее должна увидеть), GRUB восстановит доступ ко всем трём ОС.

Ответ 2



Я думаю что надо поставить 10, а потом с флешки запилить grub и настроить его. Мне кажется так будет лучше.

Объявление двумерного массива java

#java #массивы

Друзья, помогите, пожалуйста, с таким вопросом. Встретил такой кусок кода в Java

public String saveComputingResult(int firstNumber, int secondNumber, String operation) {
    String[][] arr = new String[2][0]; //**
    arr[0] = new String[1]; //**
    arr[1] = new String[1]; //**
    arr[0][0] = getOperation(operation);
    arr[1][0] = Integer.toString(getComputingResult(firstNumber, secondNumber, operation));
    return arr[0][0] + " - " + arr[1][0];


Кто может пояснить выделенные комментарием //** строки? Объявляется двумерный массив
типа String, имеет две строки и....0!!! столбцов. Это как? Что это означает? В Шилдте
и Эккеле таких примеров нету, есть только примеры где размер массива указывается для
первого массива, так как это обязательно, а второй [] просто остается пустым, но что
означает если там 0 внутри? 
И что означают эти строки при этом?? 

arr[0] = new String[1];
arr[1] = new String[1];

    


Ответы

Ответ 1



Объявляется массив состоящий из двух массивов нулевой длины. То есть каждый элемент массива имеет указатель на физический адрес, где хранится массив нулевой длины. При объявлении: String[][] arr = new String[2][]; каждому элементу массива присвоено значение null вместо указателя на адрес, то есть: arr[0]=null; arr[1]=null; В вашем же случае: String[][] arr = new String[2][0]; тоже самое что: String[][] arr = new String[2][]; arr[0] = new String[0]; arr[1] = new String[0]; Массивы нулевой длины объявлены и хранятся в памяти, а arr[0] и arr[1] присвоены указатели на адреса в памяти.

Ответ 2



Согласно en-SO и здравому смыслу при записи String[][] arr = new String[2][0]; мы получаем массив из 2 массивов типа String с нулевой длинной. Далее в приведённом вами коде ячейки массива заполняются новыми массивами с одной ячейкой в каждой: arr[0] = new String[1]; arr[1] = new String[1]; При этом, т.к. ячейки не инициализированы, то if(arr[1][0]==null) System.out.println("NULL!!!111one"); выведет NULL!!!111one Таким образом, при последующем присваивании ячейкам элементов массива arr других массивов ставить им длину равную 0 (или любой другой цифре) смысла, в общем, не имеет.

Неровный круг при использовании onDraw

#android

Слева рисунок это круг используя onDraw и рисовал в Canvas через drawCircle.

А справа круг который создал через drawable circle.xml.

Можно ли сделать так чтобы круг слева был таким же как справа?

Если что могу код скинуть
    


Ответы

Ответ 1



Вот так, добавить флаг к paint, с помощью которой рисуете: Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); Или так: paint.setAntiAlias(true);

Окно редактирования настроек

#c_sharp #wpf #mvvm

public class Setting
{
    public string Setting1 {get;set;}
}
public class SettinngViewModel: ViewModelBase
{
    public SettingViewModel(Setting settings)
    {
        _settings = settings;
    }

    Setting _settings {get; private set;}

    public string Setting1
    {
        get {return setting1;}
        set {setting1=value; OnPropertyChanged("Setting1")}
    }
}


собственно вопрос в следующем: есть главная форма из которой вызывается данное окно
редактирования настроек

public MainViewModel
{
    public MainViewModel()
    {
        SettingsCommand = new RelayCommand(x=>SettingsMethod());
    }

    var currentSettings = //здесь хранятся текущие настройки

    public ICommand SettingsCommand {get; private set;}

    private void SettingsMethod()
    {
        var view = new SettingsView();
        view.DataContext = new SettingsViewModel(currentSettings);
        view.Show();
    }
}


ввиду того что settings это ссылочный тип то при изменении в окне настроек изменения
сразу отражаются в главной форме, а я бы хотел что бы это было только после подтверждения(например
пользователь нажимает кнопку Применить)

помогите реализовать соответствующую команду
    


Ответы

Ответ 1



Смотрите. Если вы редактируете настройки, вы редактируете, понятно, копию настроек, а не оригинал. В WinForms это скрывалось за тем фактом, что применение изменений происходило во View, но с WPF/MVVM правильный подход такой. Рассмотрим случай, когда у вас нет VM-объекта, отвечающего за настройки, который поддерживает свои поля в актуальном состоянии. Тогда вам нужен VM-объект «редактируемые настройки» (SettingsEditorVM), который при старте считывает свои свойства из модельного объекта, но не синхронизирует их с моделью при изменениях. Он также выставляет команду «окончить редактирование», по приходу которой проверяет настройки на правильность, и если они в порядке, записывает результат в модельный объект. Для случая, когда у вас уже есть VM-объект, отвечающий за настройки (SettingsVM), который поддерживает свои поля в актуальном состоянии, вам нужно всё равно завести ещё один VM-объект «редактируемые настройки» (SettingsEditorVM), который сможет загрузить данные (например, в конструкторе) из SettingsVM, и по команде закончить редактирование. Этим можно пользоваться так: public class SettinngEditorVM : ViewModelBase { public SettinngEditorVM(SettingVM settingsVM) { FinishedEditing = new AwaitableCommand(); CancelledEditing = new AwaitableCommand(); Setting1 = settingsVM.Setting1; } string setting1; public string Setting1 { get { return setting1; } set { setting1 = value; OnPropertyChanged("Setting1"); CheckCorrectness(); } } void CheckCorrectness() { bool ok = Setting1 != null; FinishedEditing.CanExecuteInternal = ok; } public AwaitableCommand FinishEditing { get; private set; } public AwaitableCommand CancelledEditing { get; private set; } public async Task Edit() { using (var cts = new CancellationTokenSource()) { var finished = FinishEditing.TillActivation(CancellationToke.None); var cancelled = CancelledEditing.TillActivation(CancellationToke.None); var winner = await Task.WhenAny(finished, cancelled); cts.Cancel(); await winner; return winner == finished; } } } с таким вызовом: var editorVM = new SettingsEditorVM(editorVM); var task = editorVM.Edit(); var editorWindow = new EditorWindow() { DataContext = editorVM }; editorWindow.Show(); var succeeded = await task; if (succeeded) settingsVM.LoadFrom(editorVM); Заметьте, что код у SettingsEditorVM и SettingsVM практически одинаков, так что эти два класса стоит объединить в один. Вот код AwaitableCommand: class AwaitableCommand : ICommand { bool canExecute; // не придумал названия получше public bool CanExecuteInternal { get { return canExecute; } set { if (canExecute == value) return; canExecute = value; if (CanExecuteChanged != null) CanExecuteChanged(this, new EventArgs()); } } public bool CanExecute(object parameter) { return canExecute; } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { foreach (var tcs in subscribers) tcs.TrySetResult(true); subscribers.Clear(); } List> subscribers = new List>(); public async Task TillActivation(CancellationToken ct) { var tcs = new TaskCompletionSource(); subscribers.Add(tcs); using (ct.Register(() => tcs.TrySetCanceled())) await tcs.Task; } }

Добавление метода к объекту через прототип

#javascript #prototype

Приведённый ниже код должен назначить объекту типа Image с помощью прототипа три
новых метода: protocol(), host() и pathname().
В браузере FireFox всё проходит нормально. Chrome выдаёт следующую ошибку:


  Uncaught TypeError: document.i1.protocol is not a function


Соответственно, и остальные функции document.i1.host и document.i1.path не выполняются.  

В чём заключается проблема, и как её решить?

function pr() {
    a = this.src.split(':');
    return a[0] + ':';
}

function ho() {
    a = this.src.split(':');
    path = a[1].split('/');
    return path[2];
}

function pa() {
    path = this.src.split('/');
    path[0] = '';
    path[2] = '';
    return path.join('/').split('///').join('/');
}

Image.prototype.protocol = pr;
Image.prototype.host = ho;
Image.prototype.pathname = pa;

document.write("
"); document.write(document.i1.src + "
"); document.write(document.i1.protocol() + "
"); document.write(document.i1.host() + "
"); document.write(document.i1.pathname() + "
");


Ответы

Ответ 1



Полученный (например, с помощью document.getElementById('img') или new Image()) имеет тип HTMLImageElement. Соответственно, добавлять новые методы нужно именно в его прототип. Пример: function log(info) { document.body.innerHTML += info + "
"; } HTMLImageElement.prototype.protocol = function() { log("Protocol is called"); }; var img = document.getElementById('img'); log("Got image: " + img.constructor.name); img.protocol(); var newImage = new Image(); log("New image: " + newImage.constructor.name); newImage.protocol();


Ответ 2



function pr() { a = this.src.split(':'); return a[0] + ':'; } function ho() { a = this.src.split(':'); path = a[1].split('/'); return path[2]; } function pa() { path = this.src.split('/'); path[0] = ''; path[2] = ''; return path.join('/').split('///').join('/'); } Image.prototype.protocol = pr; Image.prototype.host = ho; Image.prototype.pathname = pa; var out = document.getElementById("out"), i1, html; out.innerHTML = "
"; i1 = document.getElementById('i1'); html = out.innerHTML; html += "src: " + i1.src + "
"; html += "protocol: " + i1.protocol() + "
"; html += "host: " + i1.host() + "
"; html += "pathname: " + i1.pathname() + "
"; out.innerHTML = html;
Вероятно, вы несколько раз выполнили скрипт на странице, и появилось несколько элементов с именем "i1", поэтому в последующи разы нужно было бы обращаться к document.i1[0].protocol(). Лучше сделать так: document.write("
"); var i1 = document.getElementById('i1'); document.write(i1.src+"
"); document.write(i1.protocol()+"
"); ...

Ответ 3



Вот рабочий вариант. Спасибо @Regent и @Sergiks и @Grundy
Got image: HTMLImageElement
: