반응형

이미지를 로딩하거나 외부데이터베이스의 데이터를 로딩하는 등의 오래걸리는 작업을 수행할 때 사용자가 앱이 멈춘것이 아니라는 것을 인지시키기 위해 ProgressDialog를 사용하게 됩니다. 이 ProgressDialog에는 두가지 모양의 Progress가 가능합니다.


1. 로딩할 데이터의 양이 얼마인지 몰라 현재 얼마만큼 작업이 수행된건지 측정할 수 없을 때 사용하는 둥근 형태의 SPINNER 스타일.

2. 로딩할 데이터의 양이 얼마인지 알고있어서 현재 작업수행정도를 표시할 수 있을 때 사용하는 막대바 형태의 HORIZONTAL 스타일.


이 중 막대바형태의 ProgressDialog 를 진행시키기 위해서는 별도의 Thread를 사용해야만 합니다. 이때 별도의 Thread에서 Progress를 진행하는 것은 어렵지 않지만 주의할 점은 화면(UI)은 오로지 main(UI) Thread 만 변경이 가능하다는 것입니다. 그렇기에 별도의 작업스레드에서 진행상황을 변경하는 명령을 수행할 수 없어서 runOnUiThread() 메소드를 호출하거나 Handler를 이용하여 UI를 변경하는 작업을 수행해야 합니다. 이는 다소 불편하게 느껴질수 있습니다. 그래서 별도의 Thread 작업과 UI 작업을 한번에 할 수 있는 AsyncTask 클래스를 이용해서 막대바 형태의 ProgressDialog를 실행시키는 앱을 소개합니다.



버튼을 누르면 0.1초(100ms) 간격으로 ProgressDialog가 진행되고 끝마치면 Toast를 표시하는 예제 앱 소스입니다.


메인화면                                       버튼클릭시 나타나는 ProgressDialog         Progress 종료후 Toast 완료 메세지























Layout 파일

 activity_main.xml

 <RelativeLayout 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"

    tools:context="${relativePackage}.${activityClass}" >


    <Button android:id="@+id/button"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="Progress Dialog by AsyncTask"

        android:onClick="mOnClick"/>


</RelativeLayout>


소스파일 

 MainActivity.java

 public class MainActivity extends Activity {

ProgressDialog dialog;   //ProgressDialog 참조변수

int pos_dilaog=0;         //ProgressDialog의 진행 위치


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

    }

    

    //Button 클릭시에 자동으로 호출되는 callback Method...

    public void mOnClick(View v){

    

     switch( v.getId() ){

    

     case R.id.button:

    

     if(dialog!=null) return;  //ProgressDialog가 현재 보여지고 있다면 아무작업도 하지 않음.

    

     new AsyncProgressDialog().execute(100); // 다이얼로그의 max 값으로 100 전달

    

    

     break;

     }

    

    }

    

    

    //AsyncTask를 상속한 클래스선언

    //AsyncTask 클래스의 콜백 메소드들 중 doInBackground를 제외하고는 기본적으로 main(UI) Thread에서 실행됨.

    //doInBackground를 제외한 다른 메소드에서는 어디서든 UI 작업 가능 

    

    //AsyncTask< 작업스레드가 처리할 데이터 타입 , 다이얼로그의 설정 데이터 타입, 작업의 결과로 리턴할 데이터 타입 >

    //쉽게 소개하면

    //첫번재 데이터 타입은 doInBackground() 메소드의 파라미터 타입을 지정

    //두번재 파라미터의 타입은 onProgressUpdate() 메소드의 파라미터 타입을 지정

    //세번째 파라미터의 타입은 onPostExecute() 메소드의 파라미터 타입을 지정

    class AsyncProgressDialog extends AsyncTask<Integer, Integer, String>{

    

    

     //작업이 시작되기 전에 호출되는 메소드로서 일반적으로 이곳에서 ProgressDialog 객체를 생성.    

     @Override

     protected void onPreExecute() {

     // TODO Auto-generated method stub

     super.onPreExecute();

    

     dialog= new ProgressDialog(MainActivity.this); //ProgressDialog 객체 생성

     dialog.setTitle("Progress");                   //ProgressDialog 제목

     dialog.setMessage("Loading.....");             //ProgressDialog 메세지

     dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //막대형태의 ProgressDialog 스타일 설정

     dialog.setCanceledOnTouchOutside(false); //ProgressDialog가 진행되는 동안 dialog의 바깥쪽을 눌러 종료하는 것을 금지

    

     dialog.show(); //ProgressDialog 보여주기    

     }    

    

     //excute() 메소드에 의해 실행되는 작업 스레드의 메소드  ( excute()호출 시에 전달한 값 params에서 받음 )

@Override

protected String doInBackground(Integer... params) { 

     // TODO Auto-generated method stub

while( pos_dilaog < params[0]){ //현재 ProgessDialog의 위치가 100보다 작은가? 작으면 계속 Progress

pos_dilaog++;

//ProgressDialog에 변경된 위치 적용 ..

publishProgress(pos_dilaog);  //onProgressUpdate()메소드 호출.

try {

Thread.sleep(100); //0.1초간 스레드 대기 ..예외처리 필수

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}//while

//while을 끝마치고 여기까지 오면 Progress가 종료되었다는 것을 의미함.

pos_dilaog=0; //다음 프로세스를 위해 위치 초기화

return "Complete Load"; // AsyncTask 의 작덥종료 후 "Complete Load" String 결과 리턴

}

//publishProgress()에 의해 호출되는 메소드

@Override

protected void onProgressUpdate(Integer... values) {

// TODO Auto-generated method stub

super.onProgressUpdate(values);

dialog.setProgress(values[0]); //전달받은 pos_dialog값으로 ProgressDialog에 변경된 위치 적용

}

//doInBackground() 메소드 종료 후 자동으로 호출되는 콜백 메소드

//doInBackground() 메소드로부터 리턴된 결과를 파라미터로 받음

@Override

protected void onPostExecute(String result) {

// TODO Auto-generated method stub

super.onPostExecute(result);

dialog.dismiss(); //ProgressDialog 보이지 않게 하기

dialog=null;      //참조변수 초기화

//doInBackground() 메소드로부터 리턴된 결과 "Complete Load" string Toast로 화면에 표시

Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();

}

    

    }//AsyncProgressDailog class..


}//MainActivity class..


반응형

+ Recent posts