2016-06-30 1 views
0

RESTRequest.Execute을 여러 번 실행 한 후에 내 Android 애플리케이션이 무작위로 충돌합니다.Delphi 안드로이드 RESTRequest : 채널이 복구 불가능하게 깨져 버려 처분 될 것입니다.

Firemonkey으로 개발 중이지만 Android Studio의 DDMS logcat에서 확인하면 오류가 발생할 수 있습니다.

535-614 /? E/InputDispatcher : 채널 '221d0340 com.mycompany.myappname/com.embarcadero.firemonkey.FMXNativeActivity (server)'~ 채널을 복구 할 수 없게 처리하여 삭제합니다!

나는 그러나 나는이 발생하지 않도록하는 방법에 대한 우둔 해요, 그것은 일반적으로 응용 프로그램에서 메모리 누수 나타내는 것을 알아 냈다.

  • 델파이에서 디버깅을하면 전혀 충돌이 없습니다.

이 내가 주요 양식에 RESTRequest의 호출 방법은 다음과 같습니다

procedure TFormMain.ExecuteReadingThread(Sender: TObject); 
begin 

    aReadingThread := TThread.CreateAnonymousThread(
     procedure() 
     begin 

      try 
       json_data_response_object := DM_KVA.GetDeviceData(communication_token, genset_id); 
      except 
       on E: Exception do 
       begin 
        // Ignore 
       end; 
      end; 

      TThread.Queue(aReadingThread, 
      procedure() 
      begin 

      // Send UI Adjustments with a Thread-safe method 

      end); 


     end); 

    // Default Threading Settings 
    aReadingThread.FreeOnTerminate := true; 
    aReadingThread.OnTerminate  := TerminateRead; 
    aReadingThread.Start; 

end; 

procedure TFormMain.TerminateRead(Sender: TObject); 
begin 

     // Make Reading Thread take it's place 
     ExecuteReadingThread(Sender); 

end; 

을 그리고 이것은 DataModule에서 실행 어떻게입니다 : 나는이 무작위로 피할 수있는 방법

function TDM_KVA.GetDeviceData(ID_Token: string; ID_Device: string): TJSONObject; 
var 

    JSObj: TJSONObject; 

begin 

    // Set default RESTRequest parameters 
    RESTRequest_KVA.Resource  := 'api/v1/TServerMethods1'; 
    RESTRequest_KVA.Method   := REST.Types.TRESTRequestMethod.rmGET; 
    RESTRequest_KVA.ResourceSuffix := Format('DeviceData/%s', [ID_Device]); 

    try 
     // Execute command 
     RESTRequest_KVA.Execute; 

    except 
     on E: EIdHTTPProtocolException do 
     begin 
      // Ignore 
     end; 
     on E: TRESTResponse.EJSONValueError do 
     begin 
      // Ignore 
     end; 
     on E: EIdUnknownProtocol do 
     begin 
      // Ignore 
     end; 

    end; 

    // Verify response 
    case (RESTResponse_KVA.StatusCode) of 

     200: 
     begin 

      // Successful readz 
      JSObj := (RESTRequest_KVA.Response.JSONValue as TJSONObject); 
      Result := JSObj; 

     end; 

    end; 

end; 

메모리 누수가 내 Android 응용 프로그램을 고장 나게합니까?

+0

'json_data_response_object'는 절대로 처리되지 않습니다. StatusCode가> 200 인 경우'GetDeviceData'의 결과는 정의되지 않습니다. –

+0

'json_data_response_object'를 자유롭게 설정하지 않으면 메모리 누수가 발생합니다. – Machado

+1

N.B : 안드로이드는 ARC 모델로 객체를 관리하지만, json_data_response_object의 범위가 ExecuteReadingThread보다 넓기 때문에 호출 사이에 처리되지 않으므로 포인터가 덮어 쓰여 메모리 누수가 발생합니다. –

답변

2

코드가 작성된대로 json_data_response_object의 범위는 ExecuteReadingThread보다 넓습니다.

ARC 메모리 모델에서 개체는 범위를 벗어날 때 자동으로 삭제됩니다. 그러나 여기서 그것은 ExecuteReadingThread에 대한 호출 사이의 범위를 벗어나지 않습니다. 대신 객체에 대한 포인터는 메모리가 남아 있지 않을 때까지 계속 덮어 씁니다 (누수가 많음).

어떻게 이러한 임의 메모리 내 안드로이드 응용 프로그램 충돌에서 누수 방지 할 수 있습니다? 익명 스레드 외부에서 접근하기 때문에, json_data_response_object의 넓은 범위를 가지고있는 중심점이 없기

가 위험하다 (그것은 비록 OnTerminate 이벤트 핸들러에서 괜찮습니다). 익명 스레드 안에 개체를 선언하는 것이 좋습니다. 마찬가지로 aReadingThread은 혼동을 피하기 위해 ExecuteReadingThread에 더 잘 선언됩니다.


마지막 요점 : 유효한 값은 모든 상황에서 할당되는 것을 보장하기 위해 방법의 시작 부분에 전무로 GetDeviceDataResult 변수를 설정합니다.

+0

사실, 애플리케이션 크래시와 'JSONObject'사이에는 아무런 관련이 없습니다. 나는 당신의 대답을 읽음으로써 많은 것을 배웠다. 나는 여전히 ** RESTRequest 명령을 실행하는 응용 프로그램 충돌 **만을 받고있다. REST 구성 요소를 만들고 처리하려고했지만 여전히 충돌합니다. – Machado

+0

요청 스레드를 다시 사용하려면 [ExecuteAsync] (http://docwiki.embarcadero.com/Libraries/Berlin/en/REST.Client.TCustomRESTRequest.ExecuteAsync) 함수를 사용해보십시오. * iOS (및 Android)는 메인 스레드가 응답하지 않는 것으로 간주하는 경우, 즉 실행중인 요청이 반환되는 데 1 ~ 2 초 이상 걸린 경우 응용 프로그램을 종료합니다. 느린 동작 (메인 스레드 블로킹으로 인한)은 모바일 장치에서 용납되지 않는 것으로 간주됩니다. * –

+0

시도했습니다. 'rmGET' 명령이 실행되자 마자 응용 프로그램이 충돌합니다. 이상하게도'rmPUT'에서는 제대로 작동하지 않습니다. – Machado