2017-12-19 9 views
0

Volley HTTP 라이브러리를 사용하여 Android 활동에서이 코드를 고려하십시오. HTTP 요청이 완료되지 않습니다. 정상 응답이나 오류 응답을 수신하지 않습니다. 그러나 while (!done) 블록을 주석 처리하면 모든 것이 정상적으로 완료됩니다. 이것은 Volley 이후 나는 완전히 별도의 스레드가 HTTP 요청을 수행하는 데 사용되는 스레드 풀을 포함하는 RequestQueue을 만들고 있습니다. 그렇다면이 스레드가 잠자고 있으면 요청이 끝나지 않는 이유는 무엇입니까?왜이 Android Volley 요청이 완료되지 않습니까?

코드 :

package com.adobe.instore.activities; 

import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.View; 

import com.adobe.instore.R; 
import com.adobe.instore.Urls; 
import com.android.volley.Request; 
import com.android.volley.RequestQueue; 
import com.android.volley.Response; 
import com.android.volley.VolleyError; 
import com.android.volley.toolbox.JsonObjectRequest; 
import com.android.volley.toolbox.Volley; 

import org.json.JSONObject; 

public class VolleyTestActivity extends AppCompatActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_volley_test); 
    } 

    private static boolean done = false; 
    protected void makeRequest(View v) { 
     Log.i(getLocalClassName(), "Request"); 

     RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); 
     queue.start(); 
     queue.add(new JsonObjectRequest(Request.Method.GET, Urls.STATIC_URL + "/profiles.json", null, new Response.Listener<JSONObject>() { 
      @Override 
      public void onResponse(JSONObject response) { 
       Log.i(getLocalClassName(), "Response"); 
       done = true; 
      } 
     }, new Response.ErrorListener() { 
      @Override 
      public void onErrorResponse(VolleyError error) { 
       Log.e(getLocalClassName(), "Error"); 
      } 
     })); 

     Log.i(getLocalClassName(), "Awaiting completion"); 
     while(!done) { 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     Log.i(getLocalClassName(), "Done"); 
    } 
} 
+0

왜 끝내지 않는다고 말합니까? – josedlujan

+0

@josedlujan logcat 콘솔에 예상 텍스트를 인쇄하지 않으면 응용 프로그램이 멈 춥니 다. –

+1

while 루프를 제거하면 주 스레드를 차단합니다. – Enzokie

답변

1

뷰는 메인 스레드 (UI 스레드라고도 함)에 렌더링됩니다. 당신이 만든 루프는 렌더링과 다른 코드를 차단합니다. 기술적으로 많은 것들이 영향을받을 것이므로이 스레드에서 Thread.sleep(...);으로 전화하는 것은 나쁜 생각입니다. Volley는 자신의 Thread를 명시 적으로 호출 할 필요가 없으므로보다 간단하게 사용할 수 있도록 설계된 http 라이브러리입니다.

Volley에서 모든 네트워킹 및 캐시 발송은 개별 스레드 (후드)에서 수행되며 응답은 주 스레드로 다시 전송됩니다. 즉, onResponseonError이 주 스레드에서 발생한다는 것입니다.

는 더 간단이 같이 할 수 있도록하려면

public class VolleyTestActivity extends AppCompatActivity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_volley_test); 
    } 

    public void makeRequest(View v) { 
     Log.i(getLocalClassName(), "Request"); 

     RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); 
     queue.start(); 
     queue.add(new JsonObjectRequest(Request.Method.GET, Urls.STATIC_URL + "/profiles.json", null, new Response.Listener<JSONObject>() { 
      @Override 
      public void onResponse(JSONObject response) { 
       Log.i(getLocalClassName(), "Response"); 
       Log.i(getLocalClassName(), "Done"); 
      } 
     }, new Response.ErrorListener() { 
      @Override 
      public void onErrorResponse(VolleyError error) { 
       Log.e(getLocalClassName(), "Error"); 
      } 
     })); 

     Log.i(getLocalClassName(), "Awaiting completion"); 
    } 
} 

또한, while()Thread.sleep 바쁜 스레드를 유지합니다. 따라서 루프가 완료 될 때까지 Main 스레드에 대기중인 모든 실행은 도달 할 수 없습니다 (그러나 발생하지는 않습니다). onResponse이 무한 루프를 우회 할 수 있다고 생각할 수도 있습니다. 내 대답은 아니오 야; 왜냐하면 onResponse은 백그라운드 스레드가 아니라 메인 스레드에 의해 대기되기 때문입니다. enter image description here

그림 1 : 아래 그림 참조 설명하기 위해 안드로이드 발리 내부 아키텍처 (이미지가 문서에서입니다)

당신은 분석 된 응답 착색 메인 스레드에 전달 말한다 상자를 보면 BLUE는 오렌지색 또는 초록색이 아닌 한 루프를 호출하는 주 스레드임을 의미합니다 (단순화하기 위해 onResponseonError이 주 스레드에 의해 호출 됨). 그렇지 않으면 루프가 부울에 의해 무시됩니다.

+0

예, 저는 스레드 풀 스레드가'onResponse' 및'onError' 코드를 실행하는 스레드가 될 것이라는 잘못된 인상을 받았습니다. 상황을 명확히 해 주셔서 감사합니다! –

1

발리 onResponse 및 onErrorResponse는 UI 스레드에서 호출된다. 따라서 메인 스레드가 잠자고 있다면 onResponse와 onErrorResponse는 호출되지 않습니다.

+0

기다리는 시간을 줄이기 위해'new Thread()'를 작성해야합니까? 아니면 안드로이드와 같은 일을하는 방법이 있습니까? –

+0

달성하고자하는 것은 무엇입니까? –

+0

내 응용 프로그램에서 무엇이 잘못되었는지 혼란스러워했습니다. 비동기 HTTP 호출로 뭔가 까다로운 일을 시도했지만 관련없는 버그가있었습니다. 감사합니다. –