Перейти к содержанию
  • 0
yooSee

Поток в Firemonkey Android для скачивания TXT

Вопросы

Доброе время суток .

Я только начал знакомится с потоками , не судите меня строго .

Вот код . Смысл которого через отдельный поток загружать текст с сервера и отображать в memo. Что я делаю? На сервере из вне имеется файлкоторый по api запросам пополняется. Его нужно в потоке постоянно выводить в memo. подгружать каждый раз. При использовании на win вес работает, на андроид не качает и не сздает файл в чем может быть проблема?

type
  ThreadHTTP = class(TThread)
  private

  public
    Stream: TMemoryStream;
    i: integer;

    procedure Execute; override;
    procedure ShowResult;
  end;

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Timer1.Enabled := true;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
var
  MyHTTP: ThreadHTTP;
begin
  ProgressBar1.Value := 0;
  MyHTTP := ThreadHTTP.Create(False);
end;

{ ThreadHTTP }

procedure ThreadHTTP.Execute;
var
  j: integer;
begin
  inherited;
  i := 0;
  j := 0;
  Stream := TMemoryStream.Create;
  Form1.IdHTTP1.Get('http://сайт/base.txt', Stream);
  Form1.ProgressBar1.Max := Stream.Size;
  while j <= Stream.Size do
  begin
    inc(i);
    Synchronize(ShowResult);
    inc(j);
    Form1.ProgressBar1.Value := Form1.ProgressBar1.Value + 1;
  end;

  Stream.SaveToFile(tpath.getdownloadspath + '/base.txt');


  Form1.Memo1.Lines.LoadFromFile(tpath.getdownloadspath + '/base.txt');
  Stream.Free;
end;

procedure ThreadHTTP.ShowResult;
begin
  Form1.Label1.Text := IntToStr(i) + ' kbs';
end;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендуемые сообщения

  • 1

во первых: синхронизация сделана не правильно

во вторых: в примерах студии есть демка с отображением индикатора загрузки

в третьих: создание TIdHTTP (лучше заменить на THTTPClient) нужно делать в потоке

 

код на коленке, без TThread

// uses System.Threading
TTask.Run(
procedure 
var 
  aHTPP: THTTPClient;
  aStream: TStringStream;
  aResult: String;
begin
  aResult := ''; 
  aHTPP := THTTPClient.Create;
  aStream := TStringStream.Create('', TEncoding.UTF8);
  try
	aHTTP.Get('урл://', aStream);
	aResult := aStream.DataString;
  finally
	FreeAndNil(aHTPP);
	FreeAndNil(aStream);
  end;
  
  TThread.Synchronize(TThread.CurrentThread, 
	procedure 
	begin 
	  Memo1.Text := aResult;
	end)
end)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
7 минут назад, Равиль Зарипов (ZuBy) сказал:

во первых: синхронизация сделана не правильно

 а можно пример как правильно?

8 минут назад, Равиль Зарипов (ZuBy) сказал:

во вторых: в примерах студии есть демка с отображением индикатора загрузки

если честно не особо важен в проекте индикатор загрузки. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
4 минуты назад, Роман Фил сказал:

а можно пример как правильно?

ответил в предыдущем сообщении

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
17 минут назад, Равиль Зарипов (ZuBy) сказал:

ответил в предыдущем сообщении

26 минут назад, Равиль Зарипов (ZuBy) сказал:

 


 
  TThread.Synchronize(TThread.CurrentThread, 
	procedure 
	begin 
	  Memo1.Text := aResult;
	end)
end)

 

это отдельная процедура? чет я туплю как она с потока вызвалась?

Подставляю ваш пример в поток , тишина.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

уберите свой поток, вставьте код (на кнопку например) который я написал изменив адрес урл на верный.

и посмотрите что произойдет

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
18 минут назад, Равиль Зарипов (ZuBy) сказал:

уберите свой поток, вставьте код (на кнопку например) который я написал изменив адрес урл на верный.

и посмотрите что произойдет

А будет ошибка - No mapping for the unicode character exist in the target multy byte code page

 

стоп , тупой проглядел 

TEncoding.UTF8 в 
TEncoding.ANsi
Отредактировал Роман Фил

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
45 минут назад, Равиль Зарипов (ZuBy) сказал:

уберите свой поток, вставьте код (на кнопку например) который я написал изменив адрес урл на верный.

и посмотрите что произойдет

Извиняюсь что не по теме чуть чуть, все работает отлично, спасибо!) На сервере есть index.php и base.txt при записи в него через get запрос 

var
  s: string;
begin
  s := utf8toansi(Edit1.Text);
  WebBrowser1.Navigate
    (('урл/?adstext=' + s));

то приходят иероглифы. файл base.txt в ansi отправляю в ansi читаю в ansi выводит . в index.php нет каких либо переводов в кодировки вот что там

<?PHP
$filename = "base.txt"; 
$name_var='adstext';

// проверка существования файла 
if (file_exists($filename)) { 
  $file = fopen($filename, "a"); 
} else { 
  $file = fopen($filename, "a"); 
} 
$text = $_GET[$name_var]."\n"; 

fwrite($file, $text); 

fclose($file); 

?>

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

есть два решения:

1) использовать base64

2) urlencode (сделать перед отправкой на сервер), urldecode (перед записью в файл)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 15.06.2017 в 09:15, Равиль Зарипов (ZuBy) сказал:

в третьих: создание TIdHTTP (лучше заменить на THTTPClient) нужно делать в потоке

 

а чем TIdHTTP не нравится?

Отредактировал Player

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

если я помню все правильно, то оф. ссылка гугл именно https

но экспериментально установлено, что http тоже работает. но никто не гарантировал, что всегда будет так

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 15.06.2017 в 09:15, Равиль Зарипов (ZuBy) сказал:

во первых: синхронизация сделана не правильно

во вторых: в примерах студии есть демка с отображением индикатора загрузки

в третьих: создание TIdHTTP (лучше заменить на THTTPClient) нужно делать в потоке

 

код на коленке, без TThread


// uses System.Threading
TTask.Run(
procedure 
var 
  aHTPP: THTTPClient;
  aStream: TStringStream;
  aResult: String;
begin
  aResult := ''; 
  aHTPP := THTTPClient.Create;
  aStream := TStringStream.Create('', TEncoding.UTF8);
  try
	aHTTP.Get('урл://', aStream);
	aResult := aStream.DataString;
  finally
	FreeAndNil(aHTPP);
	FreeAndNil(aStream);
  end;
  
  TThread.Synchronize(TThread.CurrentThread, 
	procedure 
	begin 
	  Memo1.Text := aResult;
	end)
end)

 

 

Подскажите пожалуйста, если нет связи или запрос шел слишком долго, то как получить информацию об этом? 

Сейчас при отключенном интернете, вллбще ни каких сообщений не выходит и код в секции  "TThread.Synchronize" не отрабатывает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

e THttpClient есть свойства в которых есть слово Timeout. Их можно установить, и запрос будет вываливаться по Exception

поэтому нужно добавить обработку Try Except  вместо или дополнительно к Try Finally

в обработчике Except можно куда-то записывать результат или так же через синхронизацию например выводить сообщение на экран

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


  • Похожий контент

    • От Евгений Корепов
      Класс для работы с FastCGI серверами, такими как php-fpm.
      Для тех кто не в теме : веб-сервер, к примеру nginx, получает запросы и отправляет их на исполнение FastCGI серверу, к примеру php-fpm, php-fpm получает имя скрипта, параметры, выполняет все и возвращает результат в nginx, который в свою очередь возвращает этот результат запросившему клиенту.
      С помощью класса вы можете так же, выполнять php скрипты на локальном или удаленном сервере.
      Исходники https://github.com/EvgeniyKorepov/FastCGIClient
      Пример delphi
      var FFastCGI : TFastCGI; ... procedure TFormMain.FormCreate(Sender: TObject); var AHost : String; APort : Word; AScriptFileName, ARequest, AContent : String; begin AHost := '10.0.0.4'; APort := 9000; FFastCGI := TFastCGI.Create(AHost, APort); FFastCGI.KeepAlive := True; AScriptFileName := '/opt/xxx.php'; ARequest := 'request=1234567890'; if FFastCGI.Get(AScriptFileName, ARequest, AContent) then Memo.Text := AContent else Memo.Text := FFastCGI.StatusCode.ToString + ' ' + FFastCGI.StatusText; end; пример php 
      <?php header('Content-Type: text/html; charset=utf-8'); if (isset($_REQUEST["request"])) if ($_REQUEST["request"] == "1234567890") { header("Status: 200"); echo 'OK'; } else { http_response_code(400); echo "ERROR"; }  
    • От Евгений Корепов
      Я написал класс для демонизации приложения в linux. Класс форкает процесс, обрабатывает поступающие сигналы и передает их в основной поток через потокобезопасную очередь.
      Исходники https://github.com/EvgeniyKorepov/LinuxDaemon
      Для использования просто подключите модуль UnitDaemon в свое консольное приложение:
      program DaemonTest; {$APPTYPE CONSOLE} uses System.SysUtils, System.IOUtils, System.SyncObjs, Posix.Stdlib, Posix.SysStat, Posix.SysTypes, Posix.Unistd, Posix.Signal, Posix.Fcntl, Posix.Syslog in 'Posix.Syslog.pas', UnitDaemon in 'UnitDaemon.pas'; var AEventType : TEventType; begin syslog(LOG_NOTICE, 'main START'); while True do begin syslog(LOG_NOTICE, 'main LOOP'); if UnitDaemon.QueueEvent.PopItem(AEventType) = System.SyncObjs.TWaitResult.wrSignaled then begin syslog(LOG_NOTICE, 'main UnitDaemon.QueueEvent.PopItem'); case AEventType of TEventType.StopProcess : begin syslog(LOG_NOTICE, 'main Event StopProcess'); ExitCode := EXIT_SUCCESS; exit; end; TEventType.Start : begin syslog(LOG_NOTICE, 'main Event START'); end; TEventType.Reload : begin // Reload config syslog(LOG_NOTICE, 'main Event RELOAD'); end; TEventType.Stop : begin syslog(LOG_NOTICE, 'main Event STOP'); ExitCode := EXIT_SUCCESS; exit; end; end; end; Sleep(50); end; end. Так же поддерживается systemd - для этого положите  DaemonTest.service в /etc/systemd/system/ и используйте :
      systemctl start DaemonTest.service systemctl reload DaemonTest.service systemctl stop DaemonTest.service  
    • От Виталий Иванов
      Я недавно или давно писал по поводу почему компилятор при разном наборе 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. 
    • От Дмитрий Потапов
      Приветствую. Имеется необходимость получить список всех видимых (GUI) компонентов, установленных в Delphi. Я видел где-то, что можно как-то попробовать через ToolsAPI это сделать, но ничего толкового на эту тему так и не нашел. Может есть у кого мысли по этому поводу?
      Если возникнет вопрос: для чего тебе это?
      Ответ: Для приложения LivePreview, которое идет вместе со студией для того, чтобы видеть то, что размещаю на форме непосредственно на устройстве.

      Спасибо!
    • От Светлана
      Ну всё в принципе как всегда, либо я барашка, либо лыжи не едут)
      А всё просто - я хочу, чтобы пока данные с сервера загружались по клику кнопки, пользователю элементарно был отклик в виде крутящейся какой нибудь фигни и он видел, что процесс идёт и что прога не зависла и никуда лишний раз не тыкал.
      Пока что для тестов сделала элементарно кнопку Update (speedbutton с image), данные элементарно грузятся и отображаются в GridPanel, а поверх него, чтоб пользователь и не смог куда либо тыкнуть, замостила панелькой с Image, вращаемой по таймеру (всё это дело наверху Visible:=false). И когда клацаем по кнопке Update, то панельку сверху грида делаю отображаемой и запускаю таймер, потом этот же обработчик/процедура грузит данные, а по окончанию останавливаем таймер и скрываем полупрозрачну, еще кстати, панельку. Аля вот так:
      procedure TForm1.SB_DataUpdateClick(Sender: TObject); begin //отображаем лого загрузки P_showLoad.Visible := true; Timer_load_rotate.Enabled := true; //с запуском таймера GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется //и скрывае лого загрузки Timer_load_rotate.Enabled := false; //уже в обратном порядке P_showLoad.Visible := false; end; иии... ни черта не происходит как я хочу(
      Это лого вообще в итоге не отображается, а если убрать его скрытие, то оно у нас отобразится уже только тогда, когда всё загрузится. Логика мне стала подсказывать, что следовало его как то отобразить выполнив в параллельном асинхронном потоке аля так:
      procedure TForm1.SB_DataUpdateClick(Sender: TObject); begin TThread.Queue(TThread.Current, //TThread.Queue TThread.Synchronize ForceQueue procedure() begin P_showLoad.Visible := true; Timer_load_rotate.Enabled := true; end); GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется end; И опять оно отображается только после того, как всё загрузится и проработает вся процедура. И уже чего только не пробовала и Synchronize и ForceQueue; и через TTask.Run и |task := TTask.Create(procedure () ... и т.д.| ничего не подходит, вот хоть убейся это всё дело будет отображаться только после полной отработки процедуры клика. Может я не в том направлении вообще рою и это как то по другому делается? Может я еще пока отлаживаю на Win32, а не всё на android, а там вот пара вариантов и норм на нём работают? Но чтот я никак не могу понять, что к чему... должно же быть как то просто, а я чтот никак не могу понять как(
    • От ComAlex
      Goоgle Play перестает поддерживать 32-bit Android-приложения c 01.08.2019.
      А выкладывать в Goоgle Play новые УЖЕ нельзя.
      Последние же Delphi XE не позволяют создать 64-bit Android-приложения.
      Кто знает, когда появится новая версия с поддержкой 64 - bit? Говорили, что в конце лета, но лето кончилось
    • От slav_z
      Показать/скрыть сенсорную клавиатуру Windows.
      unit Lib.Keyboard; interface uses Winapi.Windows, Winapi.ActiveX, System.Win.ComObj, FMX.Forms, FMX.Platform.Win; procedure ToggleSensorKeyboard(Form: TCommonCustomForm); implementation const CLSID_UIHostNoLaunch: TGUID = '{4CE576FA-83DC-4F88-951C-9D0782B4E376}'; type ITipInvocation = interface ['{37C994E7-432B-4834-A2F7-DCE1F13B834B}'] procedure Toggle(WND: HWND); safecall; end; procedure ToggleSensorKeyboard(Form: TCommonCustomForm); var TipInvocation: ITipInvocation; begin OleCheck(CoCreateInstance( CLSID_UIHostNoLaunch,nil,CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, ITipInvocation,TipInvocation)); TipInvocation.Toggle(FormToHWND(Form)); end; end. C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe - Сенсорная клавиатура Windows. В Windows 10 простой запуск уже не работает.
      Кто как делал? Очень интересны примеры кода.
       
    • От genakust
      добрый день,
      у меня есть несколько TabItems in FMX- TabControl (как на вложенной картинке) один из которых заполняется динамически:
      FindAndDeleteItemContext; frameIndex:= GetFrameIndexByText(item); {factory} FFramesFactory:= TFramesFactory.DefaultFactory; {Index-> Frame} aktFrame:= FFramesFactory.GetFrame(frameIndex); {add to layout} aktFrame.Parent:= LyContent; aktFrame.Align:= TAlignLayout.Client; LyContent.AddObject(aktFrame); {open tab} ActionToContentTabExecute(Sender); я пытаюсь найти фрейм и удалить его только из TabItem но не как Object обследующим способом:
      procedure Txxx.FindAndDeleteItemContext; var   i: Integer; begin   for i:= 0 to Pred(LyContent.ComponentCount) do   begin     if LyContent.Controls.Items[i] is TFrame then       LyContent.RemoveObject(i);   end; end но почему- то LyContent.ComponentCount всегда равен 0.
      Подскажите пожалуйста что неправильно?
      Спасибо.

    • От genakust
      Здравствуйте,
      я создал свой ListBoxItem (FMX) который выглядит следующим образом:

      затем я добавил Items динамически в ListBox и получилось следующее:

      Когда я запускаю программу на Windows 10 и выбираю мышкой Item он селектируется, а если запускаю на Андроид- таблете, то я не могу выбрать (селектировать) Item.
      Подскажите пожалуйста, какие могут быть причины длы такого поведения.
      Заранее спасибо.
       
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...