* insert 후 화면
4. URIMatcher를 생성한다.
URIMatcher는 컨텐트 프로바이더가 받은 URI의 종류를 결정하고, 프로바이더를 정수값의 상수로 매칭시킨다.
4-1. Define final integer constants for multiple and single rows of data.
4-2. Declare a static global variable for the complete UriMatcher
4-3. Define a buildUriMatcher method that associates URI's with their int match
data/TaskContentProvider.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package com.tistory.qlyh8.buildcontentprovider.data; /* * Created by YUNHEE on 2018-01-09. */ import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.net.Uri; import android.support.annotation.NonNull; public class TaskContentProvider extends ContentProvider { // 디렉토리일 경우 100, 200, 300 등으로 임의 지정한다. public static final int TASKS = 100; // 해당 디렉토리 안의 각 아이템일 경우 101, 102, 103 등으로 임의 지정한다. public static final int TASK_WITH_ID = 101; private static final UriMatcher sUriMatcher = buildUriMatcher(); private TaskDbHelper mTaskDbHelper; // URI 를 상수값으로 매치 시켜주는 메서드 public static UriMatcher buildUriMatcher() { // UriMatcher.NO_MATCH 상수를 넘겨 빈 매처를 만든다. UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); /* * addURI(String authority, String path, int code) * 첫 번째와 두 번째 인자는 합쳐져, 인식하고자 하는 URI 를 매처에게 알려준다. * 세번째 인자를 사용해 해당 URI 를 어느 상수에 매칭시킬지 설정한다. */ // 할일 디렉토리의 모든 행을 나타내는 URI uriMatcher.addURI(TaskContract.AUTHORITY, TaskContract.PATH_TASKS, TASKS); // 하나의 할일을 나타내는 URI uriMatcher.addURI(TaskContract.AUTHORITY, TaskContract.PATH_TASKS + "/#", TASK_WITH_ID); return uriMatcher; } @Override public boolean onCreate() {...} @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {...} @Override public String getType(@NonNull Uri uri) {...} @Override public Uri insert(@NonNull Uri uri, ContentValues values) {...} @Override public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {...} @Override public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {...} } | cs |
** UI 코드에서 데이터베이스에 작업을 호출하는 과정
UI - Resolver(URI) - Provider - URIMatcher - SQL Code - Database
a. UI 코드에서 Content Resolver를 가져와 쿼리 메소드를 호출하고,
b. 특정 프로바이더와 읽고자 하는 데이터를 나타내는 URI를 같이 넘겨준다.
c. 리졸버는 넘겨진 URI의 authority에 따라 올바른 TaskContentProvider를 찾아서 쿼리를 전달한다.
d. 쿼리 함수는 URIMatcher를 사용해 어떤 데이터를 가져와야 하는지 (전체/하나) 결정한다.
e. 쿼리 함수는 선택된 데이터에 대해 알맞은 SQL code를 생성한다.
f. 프로바이더는 database에서 대상 데이터가 담긴 커서를 반환한다.
5. 데이터에 추가하기 위해 insert 메서드를 구현한다.
5-1. Get Writeable access to the task database.
5-2. Write URIMatching code to recognize the match for the tasks directory.
5-3. Write code to insert a row of data into the existing directory.
5-4. Set the value for the returned URI and write the default case.
5-5. Notify the ContentResolver if the URI has changed.
data/TaskContentProvider.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | package com.tistory.qlyh8.buildcontentprovider.data; /* * Created by YUNHEE on 2018-01-09. */ import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.support.annotation.NonNull; public class TaskContentProvider extends ContentProvider { // 디렉토리일 경우 100, 200, 300 등으로 임의 지정한다. public static final int TASKS = 100; // 해당 디렉토리 안의 각 아이템일 경우 101, 102, 103 등으로 임의 지정한다. public static final int TASK_WITH_ID = 101; private static final UriMatcher sUriMatcher = buildUriMatcher(); private TaskDbHelper mTaskDbHelper; // URI 를 상수값으로 매치 시켜주는 메서드 public static UriMatcher buildUriMatcher() {...} // 데이터 소스를 설정하는 데 필요한 것을 초기화 해야한다. // 이 경우 SQLite 데이터베이스로 작업하기 때문에 DbHelper 를 초기화해야 액세스 할 수 있다. @Override public boolean onCreate() {...} // 요청된 데이터를 담고 있는 하나 이상의 로우에 대한 Cursor 객체를 반환하는 메서드. @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {...} // 반환될 내용의 MIME 타입을 반환하는 메서드. MIME 타입은 내용이 어떤 형식으로 되어있는지 식별한다. @Override public String getType(@NonNull Uri uri) {...} /** * 데이터 추가 메서드 * @param uri: 데이터를 추가할 디렉토리를 알려주는 컨텐트 URI * @param values: 추가할 데이터를 담고있는 ContentValues 객체 * @return 새로 추가된 데이터의 위치를 알려주는 컨텐트 URI, 실패시 -1 */ @Override public Uri insert(@NonNull Uri uri, ContentValues values) { Uri returnUri; // 새 데이터를 쓰기 위해 데이터베이스에 접근한다. final SQLiteDatabase db = mTaskDbHelper.getWritableDatabase(); // 할일 디렉토리에 매칭되는 URI 매칭 코드를 받는다. int match = sUriMatcher.match(uri); switch (match){ case TASKS: // 테이블에 추가한다. long id = db.insert(TaskContract.TaskEntry.TABLE_NAME, null, values); if(id > 0){ // insert 성공 // ContentUris 는 URI 를 쉽게 만들 수 있게 도와주는 메서드를 담고있는 헬퍼 클래스 // withAppendId(): 첫 번째 인자를 베이스로 URI 를 만들고 두 번째 인자로 들어온 id를 path 의 마지막에 덧붙인다. returnUri = ContentUris.withAppendedId(TaskContract.TaskEntry.CONTENT_URI, id); } else { // insert 실패 throw new android.database.SQLException("Failed to insert row into " + uri); } break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); } // 컨텐트 리졸버에게 특정 URI 에 변경사항이 생겼다고 알린다. getContext().getContentResolver().notifyChange(uri,null); return returnUri; } // 데이터 삭제 메서드. // 어느 행을 삭제할 지 알려주는 URI 를 인자로 받아야 하며, 삭제된 행의 개수를 반환한다. @Override public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {...} // 데이터 갱신 메서드. // insert 의 인자들을 인자로 받아, 어느 URI 에 어떤 ContentValues 에 담긴 데이터로 갱신할 것인지 알 수 있다. // 갱신된 행의 개수를 반환환다. @Override public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {...} } | cs |
5-6. Put the text description and priority into a ContentValues object.
5-7. Use a ContentResolver to insert these values into the tasks directory.
5-8. Include a Toast to view the inserted content URI.
AddTaskActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | package com.tistory.qlyh8.buildcontentprovider; /* * Created by YUNHEE on 2018-01-09. */ import android.content.ContentValues; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.RadioButton; import android.widget.Toast; import com.tistory.qlyh8.buildcontentprovider.data.TaskContract; public class AddTaskActivity extends AppCompatActivity{ private int mPriority; @Override protected void onCreate(Bundle savedInstanceState) {...} // 우선순위 버튼을 눌렀을 때 호출된다. // 선택한 버튼을 기준으로 mPriority 의 값이 변경된다. public void onPrioritySelected(View view) {...} // "ADD" 버튼을 눌렀을 때 호출된다. // 사용자 입력을 얻어 새 할일 데이터를 기본 데이터베이스에 삽입한다. public void onClickAddTask(View view) { String input = ((EditText) findViewById(R.id.editTextTaskDescription)).getText().toString(); if (input.length() == 0) { return; } // 할 일 데이터를 담을 새로운 ContentValue 객체 생성한다. ContentValues contentValues = new ContentValues(); // 할일과 우선순위의 key 와 value 를 각각 넣는다. contentValues.put(TaskContract.TaskEntry.COLUMN_DESCRIPTION, input); contentValues.put(TaskContract.TaskEntry.COLUMN_PRIORITY, mPriority); // 컨텐트 리졸버를 호출해 데이터베이스에 추가하고 // 할 일 디렉터리에 접근하기 위한 올바른 컨텐트 URI 를 넘겨준다. Uri uri = getContentResolver().insert(TaskContract.TaskEntry.CONTENT_URI, contentValues); if(uri != null){ Toast.makeText(getBaseContext(), uri.toString(), Toast.LENGTH_LONG).show(); } // 메인 액티비티로 돌아간다. finish(); } } | cs |
Android Course of Udacity - Lesson 9
'Android' 카테고리의 다른 글
Custom Content Provider - (4) 데이터 삭제 (0) | 2018.02.12 |
---|---|
Custom Content Provider - (3) 데이터 조회 (0) | 2018.02.12 |
Custom Content Provider - (1) 프로바이더 및 URI 생성 (0) | 2018.01.10 |
Content Provider - (3) 코드에 적용하기 (0) | 2018.01.08 |
Content Provider - (2) 사용방법 (0) | 2018.01.08 |