-
Постов
1 204 -
Зарегистрирован
-
Посещение
-
Победитель дней
26
Активность репутации
-
Rusland отреагировална Major в Что лучше: зашивать в ресурсы или Deployment? (Android)
я вот сейчас еще раз проверил. Всё, что кидалось в Deployment, - в apk-файле находится в папке assets. А то, что подключалось через ресурсы (brcc32), то находится в .so-файле.
Delphi 10.1 Berlin.
Можете сами проверить
-
Rusland отреагировална ENERGY в Странное поведение TThread
Еще мультипоточный вариант отсюда:
class procedure TFireMonkey.CachePictures(const aLV: TListView); begin Pool.SetMaxWorkerThreads(10); // TThreadPool.Default.MaxWorkerThreads TParallel.For(0, FMembersList.Count - 1, procedure(Idx: Integer) var AHTTP: TIdHTTP; begin if not FileExists(FMembersList[Idx].FileName) then begin AHTTP := TIdHTTP.Create(nil); try AHTTP.HandleRedirects := true; FStreamList[Idx].Clear; AHTTP.Get(FMembersList[Idx].URL, FStreamList[Idx]); finally FreeAndNil(AHTTP); end; TThread.Queue(TThread.CurrentThread, procedure var AItem: Integer; begin if FStreamList[Idx].Size > 0 then begin FStreamList[Idx].SaveToFile(FMembersList[Idx].FileName); AItem := Trunc(Idx / aLV.Columns); if AItem < aLV.Items.Count then aLV.Adapter.ResetView(aLV.Items[AItem]); end; Log.d('Current Thread = ' + inttostr(Idx)); end); end; end, Pool); end;
После загрузки ставьте boolean флаг в своем массиве, обозначающий что картинка загружена. Btw Boolean у Intel и ARM можно записывать и читать без синхронизации между потоками (Т.е. не нужно использовать TMonitor или AtomicExchange ), если он не в packed структуре (packed record).
-
Rusland отреагировална Равиль Зарипов (ZuBy) в Странное поведение TThread
procedure LoadBitmapFromURL(const aURL: string; aBitmap: TBitmap; const aSuccess: TThreadProcedure = nil; const aError: TThreadProcedure = nil); var thread: TThread; begin thread := TThread.CreateAnonymousThread( procedure var HTTP: THTTPClient; Result: TMemoryStream; begin Result := TMemoryStream.Create; HTTP := THTTPClient.Create; try try HTTP.Get(aURL, Result); TThread.Synchronize(TThread.CurrentThread, procedure var aSourceBmp: TBitmap; begin aSourceBmp := TBitmap.Create; try aSourceBmp.LoadFromStream(Result); if not aSourceBmp.IsEmpty then begin aBitmap.SetSize(aSourceBmp.Width, aSourceBmp.Height); aBitmap.CopyFromBitmap(aSourceBmp); if Assigned(aSuccess) then aSuccess; end; finally FreeAndNil(aSourceBmp); end; end); except TThread.Synchronize(TThread.CurrentThread, procedure begin if Assigned(aError) then aError; end); end; finally FreeAndNil(Result); FreeAndNil(HTTP); end; end); thread.FreeOnTerminate := true; thread.start; end; в последнее время пользуюсь такой конструкцией
-
Rusland отреагировална Равиль Зарипов (ZuBy) в Странное поведение TThread
само скачивание картинки HTTPClient.Get должен быть в потоке, а при успешном скачивании нужно делать синхронизацию с главным потоком и "вставлять" картинку в нужное место
-
Rusland отреагировална enatechno в Странное поведение TThread
Synchronize(LoadImage); Эта строка означает, что LoadImage выполняется в главном потоке (для каждой картинки!).
Для примера посмотрите эту тему:
-
Rusland отреагировална AngryOwl в Прозрачные контролы
Если не ошибаюсь, то у стандартного стиля для Panel - TRectangle - это и есть весь стиль ))) Потому и не может быть Visible=False )
Так уберите у него заливку, сделав ее прозрачной. И все.
-
Rusland отреагировална enatechno в Прозрачные контролы
Полностью согласен. panelstyle - это и есть только один TRectangle. StyleEditor не позволяет его сделать Visible=false. Но можно менять Opacity. Если нужна невидимая панель, то лучше использовать обычный TLayout, который вообще не использует стиль.
Работа с background в TGroupbox зависит от платформы. Посмотрите в редакторе стилей на дефолтный groupboxstyle:
- для платформы Windows: текст, используемый для заголовка группы, расположен на объекте background. Если Вы будете менять видимость или прозрачность background, то текст тоже будет невидимым/прозрачным.
- для платформы Android: текст расположен на отдельном layout. В этом случае изменение видимости/прозрачности background не влияет на отображение текста заголовка.
-
Rusland отреагировална AngryOwl в Прозрачные контролы
Согласен.
Я, например, делаю либо свой стиль для нужного компонента, либо делаю копию (например от стиля Android), если хочу чтобы выглядело абсолютно одинаково везде.
Можно оставить родной стиль для TPanel, сделав свой стиль, типа panelopacitystyle (и потом задав его вашим панелям, которым требуется именно прозрачность), в котором вы можете изголяться со стилем как вашей душе будет угодно. Заполнять панели чем угодно, хоть картинками... При этом, в чем прелесть, - можно программно менять стиль из приложения при необходимости (например, - реакция на какие-либо события).
-
Rusland отреагировална enatechno в Прозрачные контролы
Это решается редактированием стиля.
Например так:
1). Размещаете TGroupbox на форме
2). ПКМ на нем
3). в контекстном меню выбираете Edit Custom Style (или Edit Default style)
4). в открывшемся редакторе стиля указываете платформу (Android)
5). выбираете объект background (по умолчанию он белый).
6). задаете ему свойство Visible=false
-
Rusland отреагировална ENERGY в Реестр в Андроиде и Delphi
krapotkin
На мой взгляд формат ini наиболее удобный - Секция > Имя=значение.
1. Не нашел как делить настройки на секции - в этом основное преимущество ini.
2. Парсинг json требует больше времени чем ini. Если настроек много, то это будет в несколько раз медленнее варианта ini. Например в моем проекте кроме основных настроек, есть еще группы, профайлы, и кампании.
И очень удобно когда секции ссылаются друг на друга, причем втч. читать сам ini файл в текстовом редакторе.
К примеру :
[Group1]
Key=Value
[Profile2]
Key=Value
[Campaign1]
Groups=Group1, Group2
Profiles=Profile1, Profile2
[Campaign2]
[Campaign3]
-
Rusland отреагировална krapotkin в Реестр в Андроиде и Delphi
это немного вчерашний день
лучше
создавайте в приложении класс настроек и считывайте/записывайте его одной строкой
-
Rusland отреагировална Равиль Зарипов (ZuBy) в ColorComboBox произвольный список цветов
const aColorNames: array [0 .. 3] of string = ('Black', 'Red', 'Yellow', 'Green'); aColors: array [0 .. 3] of TAlphaColor = (TAlphaColorrec.Black, TAlphaColorrec.red, TAlphaColorrec.Yellow, TAlphaColorrec.Green); procedure TForm1.DoItemApplyStyleLookup(Sender: TObject); var ColorObj: TShape; begin if TListBoxItem(Sender).FindStyleResource<TShape>('color', ColorObj) then ColorObj.Fill.Color := aColors[TListBoxItem(Sender).Tag]; end; procedure TForm1.Button1Click(Sender: TObject); var aItem: TListBoxItem; I: Integer; begin ComboBox1.DropDownKind := TDropDownKind.Custom; // uses FMX.Pickers; for I := Low(aColorNames) to High(aColorNames) do begin aItem := TListBoxItem.Create(ComboBox1); aItem.Parent := ComboBox1; aItem.Text := aColorNames[I]; aItem.Width := aItem.DefaultSize.Width; aItem.Height := aItem.DefaultSize.Height; aItem.StyleLookup := 'colorlistboxitemstyle'; aItem.StylesData['color.Fill.Color'] := aColors[I]; aItem.OnApplyStyleLookup := DoItemApplyStyleLookup; aItem.Tag := I; end; end; как-то так
-
Rusland отреагировална Равиль Зарипов (ZuBy) в ColorComboBox произвольный список цветов
Внутри TComboBox используется TListBox
Cамый простой способ
кинуть на форму TListBox ПКМ Add TListBoxItem выбрать нужный стиль для Item (StyleLookup) ПКМ по Item Edit Custom Style меняем что нужно в стиле и сохраняем применяем новый стиль к Item -
Rusland отреагировална Brovin Yaroslav в Описание TfgRatingBar
Доработал компонент. Добавлено:
Поддержка Tint эффекта - TfgRatingBar.TintColor Автоматический размер - TfgRatingBar.AutoSize Режим только отображения - TfgRatingBar.ReadOnly Событие окончательного изменения рейтинга (отжатие пальца от экрана или кнопки мышки) - TfgRatingBar.OnChange Событие в процессе изменения рейтинга - TfgRatingBar.OnChanging
-
Rusland отреагировална Brovin Yaroslav в [Статья] Жизненный цикл объектов в Delphi. Часть 2. Android, iOS. Что же использовать Destroy, Free, FreeAndNil или DisposeOf?
Ссылка: http://yaroslavbrovin.ru/object_life_cycle_in_delphi_part_2_android_ios-ru/ Автор: Ярослав Бровин Продолжаем тему жизненного цикла объектов в мире Delphi, но в этой части рассматриваем эту тему в рамках мобильных платформ Android и iOS.
Delphi вводит новый подход к управлению памятью в мобильных платформах. Появляется автоматический подсчет ссылок, который с одной стороны облегчает код разработчика и должен помочь ему, а с другой стороны раскладывает равномерно грабли на пути освоения новых платформ в мире Delphi.
-
Rusland отреагировална SerhioUser в Как получить версию APK-файла под Win32?
Благодарю, Евгений Корепов!
Вот функция GetApkVersion() на C++ для получения версии APK-файла, и слегка подкорректированная вышеописанная функция запуска:
String __fastcall ShellExecutePipe(String CommandLine, String AWorkDir = "C:\\", UINT Flag = SW_HIDE) { TSecurityAttributes SA; TStartupInfo SI; TProcessInformation PI; HANDLE StdOutPipeRead, StdOutPipeWrite; bool WasOK; char Buffer[256]; unsigned long BytesRead; String WorkDir; bool Handle; String AOutputLine; String Result; SA.nLength = sizeof(SA); SA.bInheritHandle = true; SA.lpSecurityDescriptor = NULL; CreatePipe(&StdOutPipeRead, &StdOutPipeWrite, &SA, 0); try { setmem(&SI, sizeof(SI), 0); SI.cb = sizeof(SI); SI.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; SI.wShowWindow = Flag; SI.hStdInput = (unsigned)GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin SI.hStdOutput = (unsigned int)StdOutPipeWrite; SI.hStdError = (unsigned int)StdOutPipeWrite; WorkDir = AWorkDir; Handle = CreateProcess(NULL, CommandLine.c_str(), NULL, NULL, true, 0, NULL, WorkDir.c_str(), (STARTUPINFO*)&SI, &PI); } catch(Exception &e) { } CloseHandle(StdOutPipeWrite); if (Handle) { try { do { WasOK = ReadFile(StdOutPipeRead, Buffer, 50, &BytesRead, NULL); if(BytesRead > 0) { Buffer[BytesRead] = 0; AOutputLine = Buffer; Result = Result + AOutputLine; } }while(WasOK && (BytesRead != 0)); WaitForSingleObject(PI.hProcess, INFINITE); } __finally { CloseHandle(PI.hThread); CloseHandle(PI.hProcess); } } CloseHandle(StdOutPipeRead); return Result; } //--------------------------------------------------------------------------- String __fastcall GetShortName(String sLongName) { String ret; String sShortName; int nShortNameLen; sShortName.SetLength(MAX_PATH); nShortNameLen = GetShortPathName( sLongName.c_str(), sShortName.c_str(), MAX_PATH - 1); if (nShortNameLen != 0) { sShortName.SetLength(nShortNameLen); ret = sShortName; } return ret; } //--------------------------------------------------------------------------- String __fastcall GetApkVersion(String FileName) { String ret; String AppPath = GetShortName(ExtractFileDir(Application->ExeName)); FileName = GetShortName(FileName); if(FileName != "") { String cmd = (String)"cmd /c \""+ AppPath + "\\aapt.exe\"" + " dump badging " + FileName; String res = ShellExecutePipe(cmd, AppPath); TStringList *sl = new TStringList; sl->Delimiter = ' '; sl->DelimitedText = res; ret = AnsiDequotedStr(sl->Values["versionName"], '\''); if(ret != "") ret += "."; ret += AnsiDequotedStr(sl->Values["versionCode"], '\''); delete sl; } return ret; } //--------------------------------------------------------------------------- Всем спасибо за участие.
-
Rusland отреагировална ENERGY в Реестр в Андроиде и Delphi
SharedPreference удаляются при деинсталяции программы.
-
Rusland отреагировална Равиль Зарипов (ZuBy) в Как заполнить эллипс?
var MyRect: TRectF; begin MyRect := RectF(10, 10, 30, 30); if Canvas.BeginScene then try Canvas.Fill.Color := TAlphaColorRec.Red; Canvas.Stroke.Color := TAlphaColorRec.Black; Canvas.FillEllipse(MyRect, 1); Canvas.DrawEllipse(MyRect, 1); finally Canvas.EndScene; end; end; FillEllipse - заливка
DrawEllipse - обводка
-
Rusland отреагировална dante333 в Как убрать лишние уведомления в шторке при пуше?
Kitty,а вы попробуйте переустановить свое приложение.Удалить и заново поставить.Получите +1 к пушам. Было 3,станет 4.Больше переустановок,больше пушей. Когда работал с Kinvey была такая же история.В блогах на Embarcadero обсуждали даже.Если в кратце и по памяти,то при переустановке приложения,в Kinvey дублируется запись устройства на которое отправляется push.Что бы избежать этого,надо делать доп проверку на уже существующий токен для данного устройства.Повторюсь что это по памяти,но суть понятна.Можете поискать в блогах Sarina Dupont на Embarcadero.
Собственно после этого я и перешел на нативные пуши. Потому как написал многоуважаемый ZuBy:
Вот,нашел:
https://community.embarcadero.com/blogs/entry/remote-push-notifications-on-android-with-rad-studio-xe6-795
Второй коммент.
15 раз установил,15 пушей.
-
Rusland отреагировална Равиль Зарипов (ZuBy) в Принудительная остановка прокрутки ListView
На мобильных это делается с помощью TAniCalculations, в ModernLV есть метод getAniCalc
if ListView1.getAniCalc <> nil then ListView1.getAniCalc.Animation := false; в момент вызова этого кода скроллинг остановится
-
Rusland отреагировална Равиль Зарипов (ZuBy) в Рисование маршрута на MapView, Delphi, Android
Вас не смущает что это локальная переменная?
-
Rusland отреагировална kami в [ANDROID] Создание и удаление компонентов run-time
Поправка: это самый верный способ для FMX, вне зависимости от платформы.
Емнип, у TCircle нет наследников. Ну и - для использования Release не обязательно приводить тип к истинному классу объекта.
Поэтому сей код можно записать так (не проверял в IDE, но если скомпилируется - значит всё нормально):
for k:=Layout1.ChildrenCount-1 downto 0 do if Layout1.Children[k] is TCircle then Layout1.Children[k].Release;
-
Rusland отреагировална ENERGY в Утечка при использовании анонимного метода или анонимные методы, циклические ссылки и ARC
Это касается ARC компиляторов, Android, iOS и будущего Linux.
Если контейнер владелец, содержит классы, которые используют анонимный метод для общения с ним (классом владельцем), то такая конструкция порождает утечку памяти из-за появления циклической ссылки. Т.к. при присваивании анонимного метода инкрементируется счетчик ссылок и не меняется. Причем это не указано в хелпе.
А дело было так - при вызове MyCore.Free класс не уничтожался - не вызывался деструктор из за того, что после вызова Free, счетчик ссылок (reference Count) был равен 1. Приходилось пользоваться DisposeOf. Решил разобраться.
Для этого перекрыл виртуальные методы TObject отвечающие за изменения счетчика объекта (см. также полный пример ниже).
function __ObjAddRef: Integer; override;
function __ObjRelease: Integer; override;
Итак TCore содержит класс TTestClass - у которого есть событие OnMyEvent.
Прототип описан как анонимная процедура - TAnonymProc = reference to procedure;
При указании анонимной процедуры, т.е. :
procedure TCore.SetEvent; begin fTest.OnMyEvent := procedure () begin fSetFlag := true; end; end; счетчик ссылок TCore увеличивается на 1 и не изменяется при выходе из SetEvent.
Теперь при вызове Free TCore - не будет вызван деструктор, который должен уничтожит классы TCore и TTestClass и произойдет утечка памяти.
Решение :
1. Использовать слабые ссылки - weak, в нашем примере добавить атрибут [weak]:
TTestClass = class strict private [weak]fOnMyEvent:TAnonymProc; public property OnMyEvent: TAnonymProc read fOnMyEvent write fOnMyEvent; end; При присваивании объекта в переменную со слабой ссылкой не происходит увеличение счётчика ссылок объекта на единицу. Аналогично, при очистке слабой ссылки не происходит уменьшение счётчика объекта на единицу.
2. Не использовать анонимные методы, а использовать обычные указатели на метод:
Вместо TAnonymProc = reference to procedure; используем классический
TAnonymProc = procedure of object;
Демо пример, где можно отследить утечку прикрепил.
Полный код:
AnonMethodsCycle.zip
-
-
Rusland отреагировална enatechno в Запуск компилированного приложения.
Создал 2 тестовых проекта (один VCL, другой FMX). В обоих только форма с кнопкой.
Компилировал из 10 Seattle и 10 Berlin (конфигурация Debug).
Запускал на win 7 и 10.
Задержки в 1-2 сек не наблюдал. На глаз оба проекта запускаются с одинаковой скоростью.
Конфигурация компьютера аналогична Вашей.
https://www.youtube.com/watch?v=5q8ZKiYEWko