안드로이드 Thread Handler AsyncTask ThreadTest 프로젝트를 만듭시다. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btn1" android:text="Toast"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btn2" android:text="Count"/> <TextView android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:text="0" android:id="@+id/txt"/> </LinearLayout> package com.example.threadtest; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private Button btn1,btn2; private TextView txt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button)findViewById(R.id.btn1); btn2 = (Button)findViewById(R.id.btn2); txt = (TextView)findViewById(R.id.txt); btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this,"Hello",Toast.LENGTH_LONG).show(); } }); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { for(int i=0;i<100;i++) { /** 오류가 생긴다. ANR(Anroid Not Responding 창이 뜨면서 응답하지 않음. 대기하면 이어서 작업진행*/ txt.setText(i+""); // ""은 문자열로 자동 형변환 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }); } } 내부적으로는 일하고 있으나, 디바이스 에서는 오류가 발생 Thread와 Handler와 Message를 이용하여 Code를 수정해봅시다. package com.example.threadtest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private Button btn1,btn2; private TextView txt; Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { // 데이터를 공유하려면 이벤트 시스템과 Queue가 필요함 int count = msg.arg1; txt.setText(count+""); }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn1 = (Button)findViewById(R.id.btn1); btn2 = (Button)findViewById(R.id.btn2); txt = (TextView)findViewById(R.id.txt); btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this,"Hello",Toast.LENGTH_LONG).show(); } }); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /** Thread Handler로 실행 한다. */ Thread t = new Thread() { public void run() { super.run(); for(int i=0;i<100;i++) { //txt.setText(i+""); // ""은 문자열로 자동 형변환 Message msg = Message.obtain(); // 재활용한다. msg.arg1 = i; handler.sendMessage(msg); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; }; t.start(); } }); } } 오류 없이 실행이 잘됩니다. Thread.sleep()을 사용하기 싫다면 다음과 같은 방법도 있습니다. handler.sendMessageDelayed(msg,500+i*100); 가독성을 높이기 위해 코드를 변경한다. public class MainActivity extends Activity { private int cnt; // 전역변수 설정 Handler handler = new Handler(); @Override public void onClick(View v) { /** Thread Handler로 실행 한다. */ Thread t = new Thread() { public void run() { super.run(); for(int i=0;i<10;i++) { cnt = i; // 전역변수 cnt handler.post(new Runnable() { @Override public void run() { txt.setText(cnt+""); // i는 핸들로러 접근이 불가능하므로 전역 변수가 필요하다 } }); } } } } 하지만 지금도 구조적으로 문제가 있다. AsyncTask 클래스를 이용해보자. 액티비티를 하나 더 생성합시다 package com.example.threadtest; import java.security.PublicKey; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class AsyncTaskActivity extends Activity { private Button btn1,btn2; private TextView txt; class MyTask extends AsyncTask<Void, Integer, Void> { // 첫째 Parameter params는 입력 // 둘째 Parameter Progress // 마지막 Parameter Result는 리턴값 @Override protected void onPreExecute() { super.onPreExecute(); } /** Thread의 Run과 같은 기능, Thread로 동작*/ public Void doInBackground(Void[] params) { for(int i=0;i<100;i++) { /** Handler 호출*/ publishProgress(i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; }; protected void onPostExecute(Void result) { }; /** Handler 전용*/ // Integer ... 은 가변 배여릉ㄹ 의미함 protected void onProgressUpdate(Integer ... values) { txt.setText(values[0]+""); } ; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_async_task); btn1 = (Button)findViewById(R.id.btn1); btn2 = (Button)findViewById(R.id.btn2); txt = (TextView)findViewById(R.id.txt); btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(AsyncTaskActivity.this,"Hello",Toast.LENGTH_LONG).show(); } }); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MyTask task = new MyTask(); task.execute(); } }); } } 똑같이 잘 동작 됩니다.activity_main.xml
MainActivity.java
Thread, Handler, Message
AsyncTask
AsyncTaskActivity.java
'Android' 카테고리의 다른 글
안드로이드 환경설정 SharedPreferences (0) | 2016.03.23 |
---|---|
안드로이드 브로드캐스트 리시버 (0) | 2016.03.23 |
구글 플레이 마켓 안드로이드 개발자 등록 (0) | 2016.03.22 |
Bing Maps API (0) | 2016.03.21 |
Google Map API 이용 라이딩(거리,속도)정보 SharedPreferences 저장 웹서버의 MySQL DB 전송 - 5. 최종 테스트 (4) | 2016.03.17 |