싱글쓰레드를 사용하면 UI 갱신이 안되서 멀티쓰레드를 써야하는데
Thread를 직접 생성해서 사용할 수 있지만
AsyncTask 라는 쓰기 좋은 녀석이 있다는 사실.
아래는 공식 레퍼런스
http://developer.android.com/intl/ko/reference/android/os/AsyncTask.html
http://developer.android.com/intl/ko/reference/android/app/ProgressDialog.html
이번 예제는 버튼을 누르면 AsyncTask를 사용하여
ProgressDialog를 띄우고 진행 중인 작업 정보를 갱신해주면서
작업 종료시에 Dialog 닫고 Toast 메시지 하나 띄우는 예제임.
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO0wrqknL45aMSYWbuZBqM0a3tUyFmeBCMBgrOL6TtY7e0RDSUVZp8MIrNxcW4O0xLMIHkkplZSj9P50ncv832WnmfkRFFnZ3aqr4nOZC6qwJnfyGkw1WzIrRmZUx17fUjfzD9ZdFQcU0/s320/Screenshot_2013-05-26-02-55-15.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivLDz4tvMIQXP6Yd7pHS0CepB-LTACkYfjIbgVaqoHUaej4ThFf80zhZXALkXGJGDGgkphFQN0_MCmgnuCOBYb7L02Oi7f4OxqgNAJloVXWPqO-QqsafUv_C4aSYE3BsJ_b9kCVPQ4sOw/s320/Screenshot_2013-05-26-02-55-20.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3x1gZUR91rSCnQBeU9RtdeNX4pBlLUEs-baLNSpyMBLqpyHCJkM54MfUHmJ9iaupJ_EBmVb_XzaStSx2-lLs6o1d-teMBn9X0nPPrV-uQV4XcNF6uO-ZE9OJ4-55UPxuHQ3mQrzR2uVg/s320/Screenshot_2013-05-26-02-55-26.png)
ProgressDlgTest.java
import android.app.ProgressDialog; import android.content.Context; import android.os.AsyncTask; import android.widget.Toast; public class ProgressDlgTest extends AsyncTask< Integer//excute()실행시 넘겨줄 데이터타입 , String//진행정보 데이터 타입 publishProgress(), onProgressUpdate()의 인수 , Integer//doInBackground() 종료시 리턴될 데이터 타입 onPostExecute()의 인수 > { //ProgressDialog를 멤버로 하나 넣어줌 private ProgressDialog mDlg; private Context mContext; public ProgressDlgTest(Context context) { mContext = context; } //onPreExecute 함수는 이름대로 excute()로 실행 시 doInBackground() 실행 전에 호출되는 함수 //여기서 ProgressDialog 생성 및 기본 세팅하고 show() @Override protected void onPreExecute() { mDlg = new ProgressDialog(mContext); mDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mDlg.setMessage("작업 시작"); mDlg.show(); super.onPreExecute(); } //doInBackground 함수는 excute() 실행시 실행됨 //여기서 인수로는 작업개수를 넘겨주었다. @Override protected Integer doInBackground(Integer... params) { final int taskCnt = params[0]; //넘겨받은 작업개수를 ProgressDialog의 맥스값으로 세팅하기 위해 publishProgress()로 데이터를 넘겨준다. //publishProgress()로 넘기면 onProgressUpdate()함수가 실행된다. publishProgress("max", Integer.toString(taskCnt)); //작업 진행, 여기선 넘겨준 작업개수 * 100 만큼 sleep() 걸어줌 for (int i = 0; i < taskCnt; ++i) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //작업 진행 마다 진행률을 갱신하기 위해 진행된 개수와 설명을 publishProgress() 로 넘겨줌. publishProgress("progress", Integer.toString(i), "작업 번호 " + Integer.toString(i) + "번 수행중"); } //작업이 끝나고 작업된 개수를 리턴 . onPostExecute()함수의 인수가 됨 return taskCnt; } //onProgressUpdate() 함수는 publishProgress() 함수로 넘겨준 데이터들을 받아옴 @Override protected void onProgressUpdate(String... progress) { if (progress[0].equals("progress")) { mDlg.setProgress(Integer.parseInt(progress[1])); mDlg.setMessage(progress[2]); } else if (progress[0].equals("max")) { mDlg.setMax(Integer.parseInt(progress[1])); } } //onPostExecute() 함수는 doInBackground() 함수가 종료되면 실행됨 @Override protected void onPostExecute(Integer result) { mDlg.dismiss(); Toast.makeText(mContext, Integer.toString(result)+ "개의 작업 완료", Toast.LENGTH_SHORT).show(); } }
Main.java
public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn = (Button) findViewById(R.id.btn_popup); btn.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { //ProgressDlgTest 실행 new ProgressDlgTest(Main.this).execute(100); } }); } }
AsyncTask 사용하면서 삽질을 좀 했는데
주의할 점이 많으니 사용 전 꼭 공식레퍼런스를 읽어보기.
첨엔 뭣 모르고 doInBackground() 함수내에서 ListView 갱신을 했더니 프로그램이 그냥 죽더라.
한참 헤매다가 AsyncTask 구조를 좀 이해하고 해결;;
결론은 UI 갱신은 publishProgress()를 사용해서 onProgressUpdate()콜백에서 처리해야 됨
암튼 직접 Thread 생성해서 작업하는거 보다 좋음
댓글 없음:
댓글 쓰기