2013-07-23 4 views
0

첫째 그래서 나 : 안드로이드 아주 새로운 베어하시기 바랍니다하고안드로이드 스레드, 핸들러, handleMessage : 외부 클래스 파일 내에서 실행 가능한 스레드에서 UI 스레드를 업데이트

배경 : 나는 자바 (변환하려고 비 GUI) 프로그램을 Android에서 실행할 수 있습니다. , main() 메소드에서

DSGen.java, SInfer.java, Main.java

클래스 DSGen 및 SInfer 각각 초기화 및 전달을위한 객체 : 간단하게하기 위해이 프로그램이 다음과 같은 파일이 말할 수 새 스레드로 시작하여 시작했습니다. 또한 DSGen 및 SInfer 클래스 각각은 runnable을 public void run() 메서드로 구현하고 run 메서드는 둘 다 system.out.println()에 텍스트를 출력합니다.

쓰레드 1. 스레드 2. UI 스레드 모두 처리하는 생성 한 데이터 (100)의 값 (출력 100 개 결과) I 알고있는 프로그램의 안드로이드 버전에서

에 계산을 만든다 임의 데이터 (100 개) 값을 생성 UI가 업데이트됩니다. 그래서 내 MainActivity.java 파일에서 MainActivity UI 스레드의 TextView를 업데이트하는 데 사용할 수있는 "출력 데이터가있는 스레드 2"의 메시지를 수신하도록 처리기를 선언하려고합니다. Android UI에서 시작 버튼을 누르면 앱이 실행되기 시작합니다.

문제점 : 이 응용 프로그램을 실행할 때 처리가 끝날 때까지 TextView가 업데이트되지 않습니다. 또한 모든 출력이 내 TextView로 업데이트되는 것은 아니며 실제로는 40/100 계산만으로도 TextView에 출력됩니다.

실제 코드는 상당히 길어서 SInfer 클래스의 스레드, 처리기 및 실행 메서드와 관련된 부분 만 포함하는 것이 가장 좋습니다.

다른 사람이 2 개의 다른 클래스 파일 (MainActivity 내의 내부 클래스가 아님) 내에서 선언 된 여러 스레드를 처리하기위한 의사 코드 예제 또는 솔루션을 제공 할 수 있기를 바랍니다. 스레드 중 하나의 메시지를 다시 UI 스레드로 보냅니다.

미리 감사드립니다. 다음과 같이 SInfer 내에 정의

public class MainActivity extends Activity { 

    /* UI Elements */ 
    private TextView output; 

    /* Thread Handler */ 
    private Handler uiHandler; 

    /* Handle message override */ 
    public class UIHandler extends Handler { 

     @Override 
     public void handleMessage(Message msg) { 
      output.append(msg.obj.toString()); 
      super.handleMessage(msg); 
     } 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_run_fsi); 

     output = (TextView) findViewById(R.id.displayTextView); 
     uiHandler = new UIHandler(); 

     setStartButtonClickListener(); 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.activity_run_fsi, menu); 
     return true; 
    } 


    private void setStartButtonClickListener() { 
     Button startButton = (Button) findViewById(R.id.startButton); 
     startButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 

       runFSI(); 

      } 
     }); 
    } 

    private void runFSI() { 
     // initialize SInfer and pass uiHandler 

     SInfer inferer = SInfer.getInstance(/*other variables*/, uiHandler); 


     // initialize DSGen 
     DSGenerator dsGen; 

     Thread t1 = new Thread(dsGen); 
     Thread t2 = new Thread(inferer); 
     t1.start(); 
     t1.yield(); 
     t2.start(); 
     t2.yield(); 

     try { 
      Thread.sleep(10000); 
     } catch (Exception e) { 
     } 

     inferer.stop(); 
     dsGen.stop(); 

    } 

} 

실행 방법은

@Override 
public void run() { 

    // System.out.println("Inference: Thread started..."); 

    while (stopFlag == false) { 
     try { 
      // System.out.println("SInference: run........."); 
      Thread.sleep(200); 
      inferenceResult = doInference(); 

      /* Send result to UI thread */ 

      Message msg = Message.obtain(uiHandler); 
      msg.obj = inferenceResult.toString(); 
      uiHandler.sendMessage(msg); 

     } catch (InterruptedException e) { 
      // System.out.println(e.getMessage()); 
     } 
    } 
} 

답변

0

당신은에 Thread.sleep (10000)를 실행합니다 (System.out에 코드는 원래의 자바 코드에서 남은되는)된다 주 스레드 (OnClick은 UI 스레드에서 호출 됨)에서 10 초 동안 UI에서 아무 것도 업데이트되지 않습니다. runFSI 메소드를 별도의 스레드에서 호출 해보십시오. 스레드가 usingthe publishProgress() 메소드를 실행하는 동안 UI 스레드에 다시 이야기하기 위해 배경 계산을 모두 처리 할 수 ​​

재정의 onProgressUpdate를()를 AsyncTask

재정의 doInBackground()를 사용하여에

+0

감사합니다. 수면은 확실히 TextView를 업데이트하기 전에 10 초 동안 실속합니다!제안대로 FSI를위한 별도의 스레드 (이 스레드 0을 호출)를 작성하면 두 개의 스레드가 생성됩니다. 스레드 2는 스레드 1에 의해 생성 된 데이터에 의존합니다. 가장 좋은 방법은 무엇입니까? FSI를위한 내부 클래스를 만드시겠습니까? 또한 결과를 메시지로 보낼 수 있도록 스레드 2에 전달 될 수있는 uiHandler에 대한 참조를 전달합니까? 다시 한 번 감사드립니다! – iron3rd

0

봐.

그리고 UI 스레드에서 마지막 작업을 수행하려면 onPostExecute()를 재정의하십시오.