-
Постов
29 -
Зарегистрирован
-
Посещение
-
Победитель дней
1
Активность репутации
-
Виталий Иванов получил реакцию от Andrey Efimov в Скорость сборки / компиляции проекта
Я недавно или давно писал по поводу почему компилятор при разном наборе USES увеличивает время компиляции где-то от 4 до 10 раз. То есть проект может компилируются за 10 секунд, а при небольших манипуляциях с USES станет компилироваться 40 секунд и тд. Очень хорошо заметно на большом проекте у меня с 1 минуты 18 секунд выросло время компила до 1 часа 40 минут.
Ну хватит предыстории после анализа зависимостей и проверки логов обращения к файловой системе был выяснен интересный факт :)
У меня в проекте появился UNIT в котором глобальные методы для так сказать конфигурирования внешнего вида компонентов (компоненты тоже самописные) и получилось следующая ситуация:
1. В UNIT с формой лежит один из визуальных компонентов назовем его TXXX
2. соответственно в первом (interface секции) USES данного модуля прописывается автоматом модуль из зависимостей компонента
3. В нижнем (implementation секции) USES расположен UNIT с глобальными методами (назовем его UNIT XXX) для так сказать конфигурирования его (установка бордера и другой дичи)
4. В этом UNIT XXX (interface секции) USES также прописаны модули этих визуальных компонентов для передачи их в методы как параметры.
Так вот из-за такой ошибочной связи время компила увеличивается в разы и по анализу project dependency увеличивается с более менее приемлемых (по времени компиляции) 200 до 500.
Из сходя из этого начала рефакторинг всего кода и переводить компоненты на интерфейсы это сокращает project dependency проекта и неплохо так, перевод одного компонента который используется почти везде в проекте на интерфейс сократил с 200 до 190 и время компила начала сокращаться.
Сори за много букавок, но может кому будет интересно или кто с толкнулся с такой проблемой.
Так же в решении и анализе взаимосвязей помог эксперт MMX.
-
Виталий Иванов отреагировална Brovin Yaroslav в Как убить кнопку кликнув на нее саму
@kami все правильно написал. Используйте просто ForceQueue. А внутри либо отлинкуйте контрол от родителя и вызовите Free, либо брутально дергайте DisposeOf.
P.S. документация http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.ForceQueue
-
Виталий Иванов получил реакцию от IVGSoft в Audio Streaming
Теперь есть отправная точка как это должно, теперь буду дальше эксперементировать. Нужно сделать теперь ещё сервер для того что бы это работало через NAT и проверить работу на Android
-
Виталий Иванов отреагировална FREEFAR в DataSnap или API на php(Android)
мы прошли через боль с DATASNAP в итоге переехали на POSTGRES + PGBOUNCE + PHP + FIREMNKEY
PS
DataSnap очень течет особенно если начинаешь файлы таскать
-
Виталий Иванов отреагировална Alex7wrt в Audio Streaming
Методом проб и ошибок обнаружил, что для речи запись с частотой дискретизации 16000 выдает практически такое же качество, как и 44100, но ощутимо лучше, чем 8000. При этом используется одноканальная запись (моно), что с учетом 16 бит на семпл дает 32 кБ/с (256 кбит/с), что не сильно нагружает WiFi сеть. Потерь нет (и это в UDP протоколе).
Также, одна из причин, почему я не использую сжатие в данном приложении, это телефоны-приемники, которые у нас по большей части старые смартфоны с одноядерным процессорм. А в приложении кроме аудиочата есть и другие нагружающие фичи. Не хочется лишний раз нагружать проц и садить батарею, если и так все норм.
-
Виталий Иванов отреагировална Martifan в Audio Streaming
сам у Bass есть этот модуль разберусь и результат вылажу
-
Виталий Иванов отреагировална Alex7wrt в Audio Streaming
Под Android я тоже делал аудио чат родными средствами, но через Bass получилось лучше и проще. В частности, там буферизация из коробки, можно эффекты накладывать, например усиление голоса при записи через микрофон. Поэтому и предложил, ведь под Bass код, что под Android, что под iOS, один и тот же.
Поделиться не сложно. Ниже надергал основную схему из того приложения, о котором говорил выше.
uses FMX.Radio.Bass; var BLoaded: boolean; chanPlay, ChanMic: Dword; avail, freq: word; buffer: TIDBytes; procedure TForm1.OnCreate(Sender: TObject); begin //Создаем UDP сервер UDP_Rec:=TIDUDPServer.Create; with UDP_Rec do begin DefaultPort:=UDP_RecPort; BufferSize:=1600; BroadcastEnabled:=true; Active:=true; end; freq:=16000; //Частота дискретизации setlength(buffer,UDP_Rec.BufferSize); BLoaded:=BASS_Init(-1, 44100, 0, nil, nil); //Подключаем библиотеку BASS_RecordInit(-1); //Инициализируем запись end; //Захват звука с микрофона procedure TForm1.Recording(Sender: TObject; const Point: TPointF); begin isrecording:=not isrecording; if isrecording then begin UDP_Rec.OnUDPRead:=nil; chanMic:=BASS_RecordStart(freq, 1, 0, nil, nil); VoiceThread:=TVoiceThread.Create; //Создание потока для отправки по UDP end end; //Передача буффера в потоке procedure TVoiceThread.Execute; begin while isrecording do begin try avail:=BASS_ChannelGetData(chanMic, nil, BASS_DATA_AVAILABLE); if avail>=UDP_Rec.BufferSize then begin //Если в буффере собралось не меньше 1600 байт, отправляем try BASS_ChannelGetData(chanMic, buffer, UDP_Rec.BufferSize); UDP_Rec.Broadcast(Buffer,UDP_RecPort); except end; end; finally sleep(20); end; end; BASS_ChannelStop(chanmic); BASS_StreamFree(chanmic); end; //Создание канала для воспроизведения звука из буффера: procedure TForm1.receiving(Sender: TObject); begin chanPlay:= BASS_StreamCreate(freq, 1, 0, STREAMPROC_PUSH, nil); UDP_Rec.OnUDPRead:=UDP_RecRead; BASS_ChannelPlay(chanPlay, false); end; //Получаем буффер из UDP procedure TForm1.UDP_RecRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin try BASS_StreamPutData(chanPlay, AData,length(AData)) except end; end; Bass.zip
-
Виталий Иванов отреагировална Равиль Зарипов (ZuBy) в ListView - DynamicAppearance - header
проще использовать ModernLV, там это есть
-
-
-
Виталий Иванов отреагировална Равиль Зарипов (ZuBy) в Откуда произведена установка?
Можно если спросить у пользователя
-
Виталий Иванов отреагировална FREEFAR в Кнопка Done
Я сделал проще. Убрал эту кнопку и ее панель. Повесил над клавой свою панель и все
-
Виталий Иванов отреагировална Евгений Корепов в Загрузка в потоке возможно ли ?
Выполняйте oItem.Adapter.ResetView(oItem) в OnScrollViewChange по мере необходимости. Вначале для всех видимых + еще пару экранов вниз. При прокрутке повторяем.
-
Виталий Иванов получил реакцию от Равиль Зарипов (ZuBy) в Прозрачность TlistViewItem
Ок. Спасибо всем. ModernLV очень спас компонент во всём на данный момент устраивает, как прозрачный разделитель так и прозрачный фон и прозрачный Item, просто супер.
Есть ещё такой вопрос раз пошло тут про прозрачности.
Как можно нарисовать стиль для SearchBox хотелось бы что бы под Windows и Android выглядело одинаково, а не под платформу.
-
Виталий Иванов отреагировална Tumaso в Нужен нормальный JSON парсер
А меня System.JSON полностью устраивает. Ошибок парсинга валидных данных не было ни разу, скорость на нормальном уровне. Гигабайтные данные правда не парсирую, но мне это и не нужно
-
Виталий Иванов отреагировална Tumaso в Прозрачность TlistViewItem
Равиль, я так понимаю, что вы внесли изменения в стандартный ListView. Скажите плиз, в какой версии делфи взят исходник? берлин?
Я это к тому, что при переходе на токио ModernLV нужно будет заново сливать с оригинальным исходником, правильно?
Сорри за кучу знаков "вопрос"
-
Виталий Иванов отреагировална Andrey Efimov в Прозрачность TlistViewItem
Через стиль можно сделать, "itembackground.color" ставим Null. Ну и прозрачность у самого компонента включаем.
-
Виталий Иванов отреагировална Равиль Зарипов (ZuBy) в Прозрачность TlistViewItem
поиск по форуму ModernListView, ModernLV
-
Виталий Иванов отреагировална krapotkin в Маршалинг/ДеМаршалинг в System.JSON
X:=TSuperObject.Create(json);
myObj.AssignFromJSON(X);
ну и загрузка-выгрузка в класс это не совсем работа с JSON
если он заменится на любой другой формат, мы и не узнаем...
-
Виталий Иванов получил реакцию от Brovin Yaroslav в Маршалинг/ДеМаршалинг в System.JSON
Для Syste,.JSON необходимо использовать атрибуты по типу которые расположены в REST.Json.Types
[JSONNameAttribute('НАЗВАНИЕ')] -Так ваша переменная назвается в JSON
[JSONMarshalledAttribute(False)] - Так блокируется выгрузка (нащет загрузки не уверен) тоесть при TJsonObject(oJSON).ToString переменной с таким атрибутом не будет
TItems = class
private
[JSONNameAttribute('ERROR')]
FERROR: String;
[JSONNameAttribute('RESULT')]
FRESULT: String;
[JSONMarshalledAttribute(False)]
FOwner : TItems;
public
property ERROR : String read FERROR write FERROR;
property RESULT : String read FRESULT write FRESULT;
property Owner : TItems read FOwner write FOwner;
end;
-------------Результат TJsonObject().ToString---------------------
{"ERROR": "", "RESULT": ""}
==================================================================
TItems = class
private
FERROR: String;
FRESULT: String;
FOwner : TItems;
public
property ERROR : String read FERROR write FERROR;
property RESULT : String read FRESULT write FRESULT;
property Owner : TItems read FOwner write FOwner;
end;
-------------Результат TJsonObject().ToString---------------------
{"eRROR": "", "rESULT": "", "owner": ""}
Если честно то не знаю почему так все используют XSuperObject, встроенного инструмента "System.JSON, REST.Json, REST.Json.Types" с головой хватает на всё
-
Виталий Иванов получил реакцию от Brovin Yaroslav в Полноэкранный режим редактора
Извините совсем забыл, так же у меня строит вот такое дополнение DDevExtensions к IDE в нем как раз и настраиваться такое поведение, так же есть и super-zoom - который оставляет только поле редакторов как на сткриншоте ниже.
-
Виталий Иванов отреагировална ENERGY в [Статья]Как создать простой Android Broadcast Receiver. How to implement simplest Android Broadcast Receiver in Delphi
Мой вариант Broadcast Receiver, на мой взгляд наиболее оптимизирован и удачен. По сравнению с известным кодом от barisatalay .
Отличия -
исправлена утечка,
чуть быстрее работает, за счет того что создается один фильтр в него добавляется несколько Actions и одна регистрация на него,
нет лишних конвертирований с Jstring to string и обратно,
адаптирован под Delphi 10 (JFMXBroadcastReceiver) ,
упрощена работа с классом (не нужно помнить о регистрации и вызывать ее заранее) ,
и самое главное - может получать getResultCode текущего ресивера (к примеру он нужен при получении статуса смс сообщения и в других случаях.).
unit BroadcastReceiver; interface {$IFDEF ANDROID} uses Androidapi.JNI.Embarcadero, Androidapi.JNI.GraphicsContentViewText, Androidapi.helpers, Androidapi.JNIBridge, FMX.Helpers.Android, Androidapi.JNI.JavaTypes, System.Classes, System.SysUtils; type TBroadcastReceiver = class; TListener = class(TJavaLocal, JFMXBroadcastReceiverListener) private fOwner: TBroadcastReceiver; fReceiver: JFMXBroadcastReceiver; public constructor Create(aOwner: TBroadcastReceiver); destructor Destroy; override; procedure onReceive(context: JContext; intent: JIntent); cdecl; end; TOnReceive = procedure (aContext: JContext; aIntent: JIntent; aResultCode: integer) of object; TBroadcastReceiver = class private fListener : TListener; fRegistered: boolean; fOnReceive: TOnReceive; public constructor Create(aOnReceiveProc: TOnReceive); destructor Destroy; override; procedure AddActions(const Args: array of JString); procedure SendBroadcast(const aValue: string); end; {$ENDIF} implementation {$IFDEF ANDROID} { TBroadcastReceiver } constructor TBroadcastReceiver.Create(aOnReceiveProc: TOnReceive); begin inherited Create; fListener := TListener.Create(Self); fOnReceive := aOnReceiveProc; end; destructor TBroadcastReceiver.Destroy; begin fListener.Free; inherited; end; procedure TBroadcastReceiver.AddActions(const Args: array of JString); var vFilter: JIntentFilter; i: Integer; begin if fRegistered then TAndroidHelper.context.getApplicationContext.UnregisterReceiver(fListener.fReceiver); vFilter := TJIntentFilter.JavaClass.init; for i := 0 to High(Args) do vFilter.addAction(Args[i]); TAndroidHelper.context.getApplicationContext.registerReceiver(fListener.fReceiver, vFilter); fRegistered := true; end; procedure TBroadcastReceiver.SendBroadcast(const aValue: string); var Inx: JIntent; begin Inx := TJIntent.Create; Inx.setAction(StringToJString(aValue)); TAndroidHelper.Context.sendBroadcast(Inx); end; constructor TListener.Create(aOwner: TBroadcastReceiver); begin inherited Create; fOwner := aOwner; fReceiver := TJFMXBroadcastReceiver.JavaClass.init(Self); end; destructor TListener.Destroy; begin TAndroidHelper.context.getApplicationContext.unregisterReceiver(fReceiver); inherited; end; // usually android call it from "UI thread" - it's not main Delphi thread procedure TListener.onReceive(context: JContext; intent: JIntent); begin if Assigned(fOwner.fOnReceive) then fOwner.fOnReceive(Context, Intent, fReceiver.getResultCode); end; {$ENDIF} end.
Как использовать
// указывать нужно сразу все нужные вам Actions в Add через запятую, не по одной. fBroadcast := TBroadcastReceiver.Create(OnReceiveBroadcast); fBroadcast.AddActions([StringToJString(SENT_ACTION)]); << Custom action ------------- // или например сразу несколько Actions fBroadcast.AddActions([TJIntent.JavaClass.ACTION_SCREEN_OFF, TJIntent.JavaClass.ACTION_SCREEN_ON]);