안드로이드(Android) 커서(Cursor) 사용 방법(AsyncTask 활용)
커서(Cursor) 사용 방법
AsyncTask를 사용해보자.
AsyncTask 클래스는 스레드나 메시지 루프 등의 원리를 이해하지 않아도 UI 작업을 쉽게 할 수 있다.
execute()를 사용하여 AsyncTask를 실행한다. onPreExecute()가 먼저 실행 되고 그 후에 doInBackground()가 실행된다. doInBackground()작업이 끝나면 onPostExecute()로 결과 파라미너를 리턴한다. onPreExecute(), doInBackground(), onPostExecute()메소드는 메인 스레드에서 실행된다. 그렇기 때문에 Handler와 Looper , runOnUiThread()를 사용하지 않아도 UI객체에 자유롭게 접근할 수 있다.
안드로이드에서 코딩시 UI를 조작할 수 있는 방법은 크게 두가지가 있다.
Handler와 Looper 그리고 runOnUiThread()를 사용하는 것이다.
public class selectUsingContentsTask extends AsyncTask<String, Void, Boolean> {
//String : execute, doInBackground 의 파라미터 타입
//Void : onProgressUpdate 의 파라미터 타입
//Boolean : doInBackground 의 리턴값, onPostExecute 의 파라미터로 설정됨.
@Override
protected void onPreExecute() {
}
@Override
protected Boolean doInBackground(final String... args) {
try {
searchParam = args[0];
//adapter 데이터 초기화 : 데이터 중복 보이는 오류 수정 2017.12.19
if (!StringUtil.isEmpty(searchParam)) {
itemList = new ArrayList<MyNumbers>();
}
ULog.d("TAG", "================== doInBackground 검색어: " + searchParam);
dbHelper = new FcmSQLiteOpenHelper(getActivity());
database = dbHelper.getWritableDatabase();
Cursor curCSV = DataBaseUtil.selectMyNumberList(database, searchParam);
if (curCSV != null) {
final int count = curCSV.getCount();
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
textViewHeader2.setText("( 총 " + String.valueOf(count) +" 개 )");
}
});
if (count > 0) {
while (curCSV.moveToNext()) {
MyNumbers item = new MyNumbers( curCSV.getInt(0), curCSV.getString(1), curCSV.getInt(2)
, curCSV.getInt(3), curCSV.getInt(4), curCSV.getInt(5)
, curCSV.getInt(6), curCSV.getInt(7));
if(itemList!= null) itemList.add(item);
}
curCSV.close();
return true;
} else {
return false;
}
}
return false;
} catch (SQLException sqlEx) {
Log.e("selectUsingContentsTask", sqlEx.getMessage(), sqlEx);
return false;
} catch (Exception e) {
Log.e("selectUsingContentsTask", e.getMessage(), e);
return false;
}
}
@Override
protected void onPostExecute(final Boolean success) {
// if (this.dialog.isShowing() && !SearchActivity.this.isFinishing()) {
// this.dialog.dismiss();
// }
if (success) {
adapter = new MyNumberRecyclerViewAdapter(itemList, getActivity(), false);
recyclerView.setAdapter(adapter);
// adapter의 값이 변경되었다는 것을 알려줍니다.
adapter.notifyDataSetChanged();
} else {
MyNumbers item = new MyNumbers( 0, "", 0, 0, 0, 0, 0, 0);
if(itemList!= null) itemList.add(item);
adapter = new MyNumberRecyclerViewAdapter(itemList, getActivity(), true);
recyclerView.setAdapter(adapter);
// adapter의 값이 변경되었다는 것을 알림
adapter.notifyDataSetChanged();
}
}
}
그럼 실행해보자. execute()메소드를 호출하여 실행하면 된다.
private SQLiteDatabase database;
public FcmSQLiteOpenHelper dbHelper;
private ArrayList<MyNumbers> itemList = new ArrayList<MyNumbers>();
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.my_number_fragment, container, false);
TextView textViewHeader1 = rootView.findViewById(R.id.textViewHeader1);
TextView textViewHeader2 = rootView.findViewById(R.id.textViewHeader2);
selectUsingContentsTask task = new selectUsingContentsTask();
task.execute("1");
}
FcmSQLiteOpenHelper.class
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
public class FcmSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "test_sample.db";
private static final int DATABASE_VERSION = 7;
private static final String SQL_DELETE_TB_LOTTO_WINNER_NUMBER = "DROP TABLE IF EXISTS TB_LOTTO_WINNER_NUMBER";
private static final String SQL_DELETE_TB_LOTTO_MY_NUMBER = "DROP TABLE IF EXISTS TB_LOTTO_MY_NUMBER";
public static final String TB_LOTTO_MY_NUMBER = "TB_LOTTO_MY_NUMBER";
public static final String COLUMN_ADD_TEST = "_reg_type4";
private static final String DATABASE_ALTER_TB_LOTTO_MY_NUMBER_1 = "ALTER TABLE "
+ TB_LOTTO_MY_NUMBER + " ADD COLUMN " + COLUMN_ADD_TEST + " integer;";
private static final String DATABASE_ALTER_TB_LOTTO_MY_NUMBER_2 = "ALTER TABLE "
+ TB_LOTTO_MY_NUMBER + " ADD COLUMN " + COLUMN_ADD_TEST + " string;";
public FcmSQLiteOpenHelper(@Nullable Context context, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, factory, version);
}
public FcmSQLiteOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public FcmSQLiteOpenHelper(Context context, SQLiteDatabase.CursorFactory factory) {
super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//테이블 생성 스크립트
DataBaseUtil.createTablehistory(db); //DATABASE_CREATE
DataBaseUtil.createTableMyNumber(db); //DATABASE_CREATE
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//https://thebhwgroup.com/blog/how-android-sqlite-onupgrade
//기존 테이블 삭제 후 신규 처리방법 - 기존 데이터 다 삭제됨
//db.execSQL(SQL_DELETE_TB_LOTTO_WINNER_NUMBER);
//db.execSQL(SQL_DELETE_TB_LOTTO_MY_NUMBER);
//onCreate(db);
//칼럼을 추가하는 방법
// if (oldVersion < newVersion) {
// db.execSQL(DATABASE_ALTER_TB_LOTTO_MY_NUMBER_1);
// }
}
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
db.disableWriteAheadLogging();
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
AsyncTask는 execute(Runnable runnable) 메소드를 가지고 있다.
그럼으로 스레드 작업을 할 때도 사용할 수 있다.
AsyncTask.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
// 스레드 작업
}
});