Перейти к содержанию
Fire Monkey от А до Я
  • 0

[TidHTTP] Не удается скачать изображение в другом потоке. Работает в Windows, OSX, но не работает на Android и iOS


kidrock1

Вопрос

Всем привет, друзья. Столкнулся со следующей проблемой. Создаётся поток с целью загрузки картинок во время чтения статьи. Да так чтобы основная форма в момент загрузки не была заморожена. Вот код:

type
 ThreadHTTP1=class(TThread)
 private
  i:integer;
 public
  procedure Execute;override;
  procedure ShowResult1;
end;

procedure ThreadHTTP1.Execute;
var
 j:integer;
begin
  inherited;
  try
    lStream1 := TMemoryStream.Create;
    Form3.IdHTTP1.Get('http://totalmma.ru/newsupload/8306.jpg',lStream1);
  except
    // ShowMessage('no');
  end;
  Synchronize(ShowResult1);
end;

procedure ThreadHTTP1.ShowResult1;
begin
  ShowMessage(IntToStr(Form3.IDHTTP1.Response.ContentLength));
  Form3.Image1.Bitmap.LoadFromStream(lStream1);
  Form3.Image1.Visible := true;
  Form3.Caption:=IntToStr(i)+' kbs';
  Form3.IdHTTP1.Free;
  Stream.Free;
end;


procedure TForm3.Button1Click(Sender: TObject);
var
  MyHTTP1:ThreadHTTP1;
begin
  MyHTTP1 := ThreadHTTP1.Create(False);
end;

Так вот проблема в следующем. На винде всё работает. А вот когда компилируешь под андройд и переносишь на телефон, при нажатии на кнопке ничего не происходит. Очень прошу помочь, друзья.

Изменено пользователем Brovin Yaroslav
Ссылка на комментарий

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

  • 0
  • Администраторы

Все очень просто, ваш тред убивается быстрее, чем успевает запуститься.

Потому что на всех мобильных платформах работает ARC, вы объявили переменную треда в локальном скопе. В итоге, при выходе из процедуры, счетчик ссылок вышей переменной сбрасывается на 0 и ваш тред распускается.

 

Ваш код:

procedure TForm3.Button1Click(Sender: TObject);
var
  MyHTTP1:ThreadHTTP1;
begin
  MyHTTP1 := ThreadHTTP1.Create(False);
end;

Будет дополнен после компиляции дополнительными служебными командами:

procedure TForm8.Button1Click(Sender: TObject);
begin
  MyHTTP1 := ThreadHTTP1.Create(True);
  { MyHTTP1.__ObjAddRef; } <-- В момент присваивания потока в MyHTTP1. RefCount = 1.
  MyHTTP1.Start;
  { MyHTTP1.__ObjRelease; } <-- В момент выхода из метода. RefCount = 0 -> Вызов Деструктора
end;  

Частично ответ есть тут (Первые параграфы ответа): Как правильно удалять контролы в RunTime?

 

Соответственно, нужно обеспечить время жизни переменной такой же, как и у потока. Для этого можно просто оформить переменную, как поле класса.

Ссылка на комментарий
  • 0
  • Администраторы

  1. Да, при помощи потоков
  2. Переменную MyHTTP1 объявите в классе формы:

      TForm8 = class(TForm)
        IdHTTP1: TIdHTTP;
        Image1: TImage;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        MyHTTP1: ThreadHTTP1;
      public
        { Public declarations }
      end;
    
Ссылка на комментарий
  • 0
  • Администраторы

Да, кстати, в TThread есть специальный метод CreateAnonymousThread, который позволяет выполнить ваш код в другом потоке без создания отдельного класса потока:

class function TThread.CreateAnonymousThread(const ThreadProc: TProc): TThread; static;

Внутрь передается указатель на процедуру без параметров.

Ссылка на комментарий
  • 0

Я правильно понял, что должно быть вот так?

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,
  FMX.Objects, FMX.StdCtrls;

type
 ThreadHTTP1=class(TThread)
 private
  Stream:TMemoryStream;
  i:integer;


 public
  procedure Execute;override;
  procedure ShowResult1;
end;


type
  TForm3 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    IdHTTP1: TIdHTTP;
    procedure Button1Click(Sender: TObject);
  private
    MyHTTP1: ThreadHTTP1;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form3: TForm3;
  lStream1: TMemoryStream;
implementation

{$R *.fmx}








procedure ThreadHTTP1.Execute;
var
 j:integer;
begin
  inherited;
    try

      lStream1 := TMemoryStream.Create;
      Form3.IdHTTP1.Get('http://totalmma.ru/newsupload/8306.jpg',lStream1);



    except

      // ShowMessage('no');
      // InStream := TResourceStream.Create(HInstance, 'fighttime', RT_RCDATA);
      // InStream.SaveToFile(System.IOUtils.TPath.GetDocumentsPath + System.SysUtils.PathDelim + news_id +'.jpg');

    end;


   Synchronize(ShowResult1);

end;

procedure ThreadHTTP1.ShowResult1;
begin

    ShowMessage(IntToStr(Form3.IDHTTP1.Response.ContentLength));
    Form3.Image1.Bitmap.LoadFromStream(lStream1);
    form3.Image1.Visible := true;
    Form3.Caption:=IntToStr(i)+' kbs';

    Form3.IdHTTP1.Free;
    Stream.Free;

end;


procedure TForm3.Button1Click(Sender: TObject);
var
    MyHTTP1:ThreadHTTP1;
begin
          MyHTTP1:=ThreadHTTP1.Create(False);
end;

end.
Ссылка на комментарий
  • 0
  • Администраторы

У меня работает, а у вас нет?

  1. Ищите, где допустили ошибку. 
  2. Попробуйте загрузить другие картинки.
  3. Почистите ваш код от мусора.

Сделать за вас я это не смогу.

Ссылка на комментарий
  • 0

В том то и дело, что трудно найти ошибку, если по логике всё правильно и на одной платформе работает, а на другой нет. В любом случае большое вам спасибо и с наступающим, а я продолжу поиски решения)

Ссылка на комментарий
  • 0
  • Администраторы

У вас банальная ошибка. Вы объявили переменную, как поле формы. Но при этом локальную переменную MyHTTP1 не удалили!!!

Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...