2012-10-26 1 views
0

는 PHP 스크립트의 몇 가지 정보를 잡고, 내 전화에 표시하는 다음 코드를 참조하십시오 안드로이드 코드에 도입 된 모든 종류의 루프 :main.xml에가로드되지 때

package room.temperature; 

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.ArrayList; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.NameValuePair; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 

import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.TextView; 

public class RoomTemperatureActivity extends Activity { 

    String result = null; 
    StringBuilder sb=null; 

    TextView TemperatureText, DateText; 
    ArrayList<NameValuePair> nameValuePairs; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     TemperatureText = (TextView) findViewById(R.id.temperature); 
     DateText = (TextView) findViewById(R.id.date); 
     nameValuePairs = new ArrayList<NameValuePair>(); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     //setValues(); 

     for (int i = 0; i < 10; i++) { 
      setValues(); 
     } 
    } 

    public void setValues() { 

     InputStream is = null; 

     try { 
      HttpClient httpclient = new DefaultHttpClient(); 
      HttpPost httppost = new HttpPost("http://mywebsite.com/tempscript.php"); 
      httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
      HttpResponse response = httpclient.execute(httppost); 
      HttpEntity entity = response.getEntity(); 
      is = entity.getContent(); 
     } 

     catch(Exception e) { 
      Log.e("log_tag", "Error in http connection" + e.toString()); 
     } 

     try { 
      BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8); 
      sb = new StringBuilder(); 
      sb.append(reader.readLine()); 
      is.close(); 
      result=sb.toString(); 
     } 

     catch(Exception e) { 
      Log.e("log_tag", "Error converting result " + e.toString()); 
     } 

     System.out.println(result); 

     String[] values = result.split("&"); 

     TemperatureText.setText(values[0]); 
     DateText.setText(values[1]); 

    } 
} 

이 코드 for 루프를 주석 처리하고 setValues()을 한 번 호출하면 좋습니다. 그러나 루프를 도입하자마자 루프가 완료 될 때까지 main.xml (또는 화면의 모든 내용)이로드되지 않습니다. 활동 라이프 사이클과 관련이 있다고 생각했지만 어디에서 코드를 작성했는지에 상관없이 단순히 올바르게 작동하지 않습니다. 기본적으로 setValues()을 호출 할 때마다 값이 계속 업데이트되기를 원합니다. 10 반복 루프는 개념을 테스트하기위한 것입니다.

답변

4

루프가 완료 될 때까지 아무 것도 보이지 않는 이유를 이해하려면 UI 스레드가 어떻게 작동하는지 이해해야합니다. UI 스레드에는 메시지 루프가 포함되어 있습니다. 메시지 루프 (작은 코드 블록이라고 생각할 수 있음)는 순차적으로 푸시되고 실행됩니다 (한 번에 하나씩). UI 스레드가 코드를 실행하면 요청한 모든 작업을 수행하지만 화면의 값은 "게시"되거나 ​​메시지 루프로 보내져 실제로 사용 가능한 다음 시간에 화면에 표시됩니다. UI 스레드에서 장기 실행 연산을 수행하지 않아야합니다. 안드로이드 시스템이 장시간 실행되는 연산을 다루는 여러 가지 방법을 생각해 냈습니다. 가장 일반적인 시나리오는 AsyncTask를 사용하는 것입니다.

HTTP 스레드는 UI 스레드에서 실행해서는 안됩니다. 실제로는 honeycomb 이상을 실행하는 장치에서 오류가 발생합니다 (코드에 해킹을 도입하지 않는 한).

doInBackground 방법의 AsyncTask에 http 전화를 걸어야합니다. 그런 다음 UI 메서드 (.setText 메서드)를 호출 할 수있는 onPostExecute 메서드를 설정합니다. 모든 데이터를 doInBackground 메서드의 ArrayList와 같은 일종의 데이터 구조에 넣을 수 있습니다.

+0

http://www.vogella.com/articles/AndroidPerformance/article.html를 참조하지만 루프를 주석 때 왜 작동합니까? 루프가 상황을 어떻게 바꾸나요? 감사. – capcom

+0

예외는 무엇입니까? 또한 Log.e를 할 때 세 번째 매개 변수 인 예외 객체 자체를 전달하면 스택 추적을 얻을 수 있습니다 .. Log.e (TAG, e.getMessage(), e); –

+0

어디에도 예외는 아니며 루프가 완료 될 때까지 레이아웃이로드되지 않습니다. 감사. – capcom

0

매우 흥미로운 질문입니다. 내 연장자 중 한 사람에 따르면, UI를 변경하거나 다시 그려야 할 때 GPU에 전화를 걸어 변경을합니다. 그래서 한 줄을 실행하여 GPU를 변경하면 통보 및 변경이 이루어지고 컨트롤이 다음 줄로 돌아가는 경우 루프가 루프를 완결 (루프 내부 루프)하고 다시 칠하기 또는 다시 그리기를 기다리는 중입니다.

이것을 원한다면 루프에 배치하십시오.

setValues(); // 1st Time 
setValues(); // 2nd Time 
setValues(); // 3rd Time 
setValues(); // 4th Time 
setValues(); // 5th Time 
setValues(); // 6th Time 
setValues(); // 7th Time 
setValues(); // 8th Time 
setValues(); // 9th Time 
setValues(); // 10th Time 

변경 사항이 있는지 확인하십시오. 각 전화 (나는 이것이 당신의 해결책이 아니지만 목적을 이해하기위한 것임을 압니다.)

그리고 해결책을 제안한다면, 3.0 이후에 UI의 변경은 메인 스레드에서 수행 할 수 없습니다 벌집

비동기 작업

+1

이것은 중요하지 않습니다.실제 UI는 코드가 끝날 때까지 다시 그려지지 않습니다. 따라서 안드로이드의 TextView에서 setText를 호출하면 해당 텍스트 뷰의 내부 상태는 새 텍스트를 갖지만 현재 실행이 끝난 후 화면에 그려 질 때까지 UI는이를 반영하지 않습니다. 비록 당신의 활동이 openGl로 렌더링된다면 다른 것이 있는지 확실하지 않습니다. 필자는 ICS로 테스트했는데 화면이로드 된 후 for 루프의 버튼 텍스트를 업데이트하는 runnable을 게시했습니다. 텍스트는 이후까지 반영되지 않았습니다. –

+0

좋아, 좋은 +1, +1 –

+0

@MattWolfe 아니, 매트 맞아. 나는 별도의 스레드 (UI 메인 스레드를 제외하고)를 사용하여 필자가 필요로하는 작업을 수행하는 새로운 구현 작업을하고있다. 나는 애플 리케이션이 올바르게 작동한다는 것이 내 루프를 제거 할 때가 아니라는 것을 깨달았다. 'setValues ​​()'를 한 번 호출하고'main.xml '을로드하는 것 사이의 지연이 너무 작아 실제로 지연이없는 것처럼 보입니다. 나는 이것에 비틀 비아서 기쁘다. 그리고 Matt는 나를 바른 방향으로 가르쳤다. 이해하는 것이 중요한 개념입니다. – capcom

관련 문제