Android 애플리케이션 개발에 관심이 있어서 간단한 프로그램을 만들어 보고 있다.
그러던중, xml 데이터를 읽어오보 ListView 로 출력하는 과정이 1~2초 정도 걸리는데..
뭔가 작업을 진행하고 있다고 표시해주는게 좋을듯 싶어 ProgressDialog 라는 녀석을 적용해보았다.
Creating a ProgressDialog 문서를 읽으면서 쉽게 될 것으로 예상했으나.. 생각보다 헤매였다.
문서상에는 되게 간단한 것으로 보여지지만,
Thread 와 Handler 를 이용해서 제어를 해야한다. (간단한건가…;;;)
package com.eunchul.zipcode;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class ZipcodeFinderActivity extends Activity {
ListView zipcodeListView;
ArrayAdapter zipcodeArrayAdapter;
ArrayList zipcodes;
ProgressDialog progressDialog;
private Handler handler = new Handler();
final private int PROGRESS_DIALOG = 0;
final private int ZIPCODE_DIALOG = 21;
Zipcode selectedZipcode;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//final EditText keyword = (EditText)findViewById(R.id.keyword);
final Button searchButton = (Button)findViewById(R.id.search_button);
zipcodeListView = (ListView)findViewById(R.id.zipcode_list_view);
searchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread thread = new Thread(null, getZipcodes);
thread.start();
showDialog(PROGRESS_DIALOG);
}
});
zipcodeListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView _av, View _v, int _index, long arg3) {
selectedZipcode = zipcodes.get(_index);
Log.d(this.getClass().getName(), selectedZipcode.getAddress());
Log.d(this.getClass().getName(), selectedZipcode.getZipcode());
showDialog(ZIPCODE_DIALOG);
}
});
}
private Runnable getZipcodes = new Runnable() {
public void run() {
try {
final EditText keyword = (EditText)findViewById(R.id.keyword);
Log.d("getZipcodes", "executed...");
ZipcodeFactory zf = new ZipcodeFactory();
zipcodes = zf.search(keyword.getText().toString());
handler.post(updateResults);
} catch (Exception e) {
Log.e("getZipcodes", e.toString());
}
}
};
private Runnable updateResults = new Runnable() {
public void run () {
if (zipcodes != null) {
Log.d("updateResults", "executed...");
int layoutId = android.R.layout.simple_list_item_1;
zipcodeArrayAdapter = new ArrayAdapter(ZipcodeFinderActivity.this, layoutId, zipcodes);
zipcodeListView.setAdapter(zipcodeArrayAdapter);
} else {
showNotFoundZipcodes();
}
progressDialog.dismiss();
ZipcodeFinderActivity.this.removeDialog(PROGRESS_DIALOG);
}
};
private void showNotFoundZipcodes() {
Toast toast = Toast.makeText(this, "Not found", Toast.LENGTH_SHORT);
toast.show();
}
@Override
protected Dialog onCreateDialog (int id) {
switch (id) {
case (PROGRESS_DIALOG):
progressDialog = new ProgressDialog(this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setMessage("Now loading..");
return progressDialog;
case (ZIPCODE_DIALOG):
LayoutInflater li = LayoutInflater.from(this);
View zipcodeDialogView = li.inflate(R.layout.zipcode_dialog, null);
AlertDialog.Builder zipcodeDialog = new AlertDialog.Builder(this);
zipcodeDialog.setTitle("Detail");
zipcodeDialog.setView(zipcodeDialogView);
return zipcodeDialog.create();
}
return null;
}
@Override
protected void onPrepareDialog (int id, Dialog dialog) {
switch (id) {
case(ZIPCODE_DIALOG):
AlertDialog zipcodeDialog = (AlertDialog)dialog;
zipcodeDialog.setTitle(selectedZipcode.getZipcode());
TextView tvAddress = (TextView)zipcodeDialog.findViewById(R.id.dialog_address);
TextView tvZipcode = (TextView)zipcodeDialog.findViewById(R.id.dialog_zipcode);
tvAddress.setText(this.getString(R.string.zipcode_address) + " " + selectedZipcode.getAddress());
tvZipcode.setText(this.getString(R.string.zipcode_zipcode) + " " + selectedZipcode.getZipcode());
break;
}
}
}
코드는 조잡하지만..
searchButton 을 클릭하면 Thread 로 getZipcodes 를 호출하게 되고, progressDialog 를 표시하게 된다.
getZipcodes 가 XML 데이터를 읽고 ListView 로 처리하는 과정을 마치게 되면,
Handler의 MessageQueue 에 updateResults 를 실행하라고 집어넣게 된다.
그러면 updateResults 가 실행이 되고, ListView 로 표시하는 작업이 끝나고, progressDialog 를 dismiss() 하고,
removeDialog()로 제거를 시킨다.
removeDialog() 로 제거를 해주지 않으면,
progressDialog 가 멈춘상태로 표시가 된다.
버그가 있을수도 있고..
코드가 우아하지 않지만.. 이런 삽질을 반복하지 않기 위해 기록해 두련다.ㅋㅋ
이상한 점이나, 개선점이 있으면 코멘트 남겨 주시길..
참고: Creating a ProgressDialog, [TinyTut] - Displaying a simple ProgressDialog (anddev.org)
2 Comments
소스 올려주신거에 대해서 감사하게 생각합니다^^
근데 쓰레드 사용하시면서 getZipcodes 를 사용하셨는데 선언이 안되어 있어서 햇갈리더군요 알려주세요. 감사합니다.
피드백 감사합니다.
제가 처음으로 공부삼아 만들어본 우편번호 찾기 프로그램이라서..;;
언제 기회가 되면 소스 정리해서 올려보도록 하겠습니다. ㅡ.ㅡ
아니면, 제게 메일 주시면.. 허접한 소스 보내드리도록 하겠습니다.