You are on page 1of 23

NotePad Exercise 1

Trong bi tp ny, bn s construct mt notes list n gin cho php user thm mi cc notes nhng khng c edit chng. Trong bi ny, chng ta s lm hiu cc phn c bn sau: C bn v ListActivity, to v x l menu options. S dng SQLite database lu tr cc notes. Bind d liu t mt database cursor vo mt ListView s dng mt SimpleCursorAdapter. C bn v screen layout (layout mt list view), thm cc item vo activity menu, v cch thc activity x l cc selection cho menu. Trc khi bt u, bn vo y download bi tp c cha NotepadCodeLab.

I.Step 1
B1.Trong Eclipse, click vo File->New->Android Project. B2.Chn Create project from existing source. B3.Click Browse v navigate n ni c cha th mc NotepadCodeLab v chn Notepadv1. B4.Click Finish.

II.Step 2
Sau khi to project Notepadv1, bn s thy lp NotesDbAdapter lp ny c cung cp ng gi d liu truy cp vo SQLite database m s nm gi cc notes data v cho php bn cp nht n. pha trn ca lp l mt s nh ngha constant s c s dng trong ng dng tm kim d liu t cc tn trng thch hp trong database. Tn ca database l data v tn ca table l notes gm c 3 field: _id, title v body. Constructor ca NotesDbAdapter c cha mt Context, cho php n giao tip vi cc kha cnh ca OS Android. Lp Activity implement lp Context, v vy bn thng s s dng t kha this t Activity, khi cn mt Context. Phng thc open() gi mt th hin ca lp DatabaseHelper (lp ny c ci t cc b trong lp NotesDbAdapter v kt tha t SQLiteOpenHelper). N gi getWritableDatabase() x l vic to v m database cho bn. Phng thc createNote() c cha cc string cho title v body ca mt note mi, sau to note trong database. Gi s note mi c to ra thnh cng, phng thc ny cng tr v gi tr _id cho note mi c to ra.

Phng thc deleteNote() c cha mt rowId cho mt note c th, v xa note t database. Phng thc fetchAllNote() thc hin truy vn v tr v mt Cursor cho tt c cc note trong database, l n gi phng thc query(). Trong phng thc query(), tham s u tin l tn ca database table truy vn (trong v d ny, DATABASE_TABLE l notes), tham s tip theo l danh sch cc column m bn mun tr v, trong v d ny l cc column: _id, title, v body, v vy chng c xc nh l mt mng String. Cc tham s thip theo ln lt l: selection, selectionArgs, groupBy, having v orderBy; gi tr ca having bng null, c ngha l bn mun tt c data, khng cn group chng v c th t mc nh. Xem thm SQLiteDatabase. Lu : Mt Cursor c tr v ch khng phi l mt collection ca cc row. iu ny cho php Android s dng cc resource mt cch hiu qu - thay v put cc d liu trc tip vo b nh, con tr s retrieve v release d liu khi cn thit, iu ny hiu qu hn nhiu vic s dng cc table c cha nhiu row. Phng thc fetchNote() tng t nh fetchAllNote() nhng ch nhn mt note vi rowId. Cui cng, phng thc updateNote() c cha rowId, title v body, v s dng mt th hin ca ContentValues cp nht note ca rowId cho trc.

III.Step 3
M file notepad_list.xml trong th mc res/layout, di y l mt s iu bn nn bit v file layout ny: Tt c cc file layout trong Android u bt u vi dng XML header:
<?xml version="1.0" encoding="utf-8"?>

Dng tip theo thng l mt nh ngha layout, trong v d ny l LinearLayout. Namespace XML ca Android lun lun c nh ngha ti top level ca component hay layout trong XML cc tags android: c th c s dng thng qua phn cn li ca file.

xmlns:android="http://schemas.android.com/apk/res/android"

IV.Step 4
By gi, bn cn to ra layout nm gi list. Thm on m sau vo bn trong phn t LinearLayout nh sau:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content">

<ListView android:id="@android:id/list" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@android:id/empty" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/no_notes"/> </LinearLayout>

Biu tng @ trong id strings ca cc tag ListView v TextView c ngha l XML parser nn parse v expand phn cn li ca id string v s dng mt ID resource. ListView v TextView c th c xem nh l hai view khc nhau, ch mt trong s s c hin th ti mt thi im. ListView s c s dng khi c cc notes c hin th, trong khi TextView (trong c mt gi tr mc nh l "No Notes Yet!" c nh ngha nh l mt string resource trong res/values/strings.xml) s c hin th nu khng c bt k note no hin th. Cc ID list v empty c cung cp cho bn bng Android platform, v vy, chng ta phi prefix id vi android: (v d, @android:id/list). View vi id empty c s dng t ng khi ListAdapter khng c d liu cho ListView. Ngoi ra, bn c th thay view empty mc nh bng cch s dng setEmptyView(View) trn ListView. Ni rng ra, lp android.R l mt tp hp cc resource c nh ngha trc cung cp cho bn bi platform, trong khi lp R ca project ca bn l tp hp cc resource project ca bn c nh ngha. Cc resource c trong lp resource android.R c th c s dng trong cc file XML bng cch s dng prefix name space android: (nh chng ta thy y).

V.Step 5
to ra danh sch cc notes trong ListView, bn cn nh ngha mt View cho mt row: B1.To mt layout resource mi notes_row.xml trong th mc res/layout. B2.Thm cc ni dung sau y file va to:
<?xml version="1.0" encoding="utf-8"?> <TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"/>

y l View c s dng hin th mi notes title row ch c mt text field bn trong n.

Trong trng hp ny, bn to ra mt id mi gi l text1. Du + sau @ trong id string cho bit rng id nn c to ra t ng nh l mt resource nu n khng tn ti, v vy chng ta nh ngha n s dng. B3.Lu file. M lp R.java trong project ca bn, bn s thy cc nh ngha mi cho notes_row v text1, c ngha l by gi chng ta c th truy cp vo chng trong code.

VI.Step 6
Tip theo, m lp Notepadv1. Trong bc ny, bn s sa i n tr thnh mt list adapter v hin th cc notes, ng thi cho php thm note mi. Notepadv1 k tha t mt lp con ca Activity, l ListActivity, trong c chc nng b sung cho ph hp vi loi cng vic m bn c th mun lm vic trn mt list, v d: hin th cc list item trong cc row ln mn hnh, di chuyn qua li gia cc list item, v cho php la chn trn chng. Trong lp ny, c mt bin mNoteNumber c s dng to ra cc note title c nh s (numbered). ng thi, chng c 3 phng thc s c override sau y: o onCreate() c gi khi activity c start, n c s dng thit lp (set up) cc resource v state cho activity khi n ang chy. o onCreateOptionsMenu() c s dng populate menu cho Activity. Menu s c hin th khi user nhn phm MENU trn thit b, n c mt danh sch cc option user c th chn. o onOptionsItemSelected() c s dng x l cc s kin pht sinh khi user chn mt item trong Menu.

VII.Step 7
Thay i lp Notepadv1 k tha ListActivity thay v Activity.
public class Notepadv1 extends ListActivity {

Lu : Bn s phi import ListActivity vo Notepadv1 s dng Eclipse, nhn t hp phm ctrl-shift-O trn Windows hay Linux, hay cmd-shift-O trn Mac.

VIII.Step 8
Ci t phng thc onCreate(). y bn s ci t title cho Activity (hin th top ca mn hnh), s dng layout notepad_list m bn to ra trc , thit lp mt th hin ca NotesDbAdapter truy cp d liu note, v populate danh sch vi cc note title sn c: B1.Trong phng thc onCreate(), gi super.onCreate() vi tham s saveInstanceState. B2.Gi setContentView() v gn R.layout.notepad_list.

B3.Ti top ca lp, to mt bin lp private mi mDbHelper ca lp NotesDbAdapter. B4.Tr li phng thc onCreate(), to ra mt i tng mi NotesDbAdapter v gn n cho trng mDbHelper. B5.Gi phng thc open() trn mDbHelper m (hay to mi) database. B6.Cui cng, to mi mt phng thc fillData() nhn d liu v populate ListView s dng helper chng ta vn cha nh ngha phng thc ny.

Phng thc onCreate() s trng nh sau:


@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.notepad_list); mDbHelper = new NotesDbAdapter(this); mDbHelper.open(); fillData(); }

V m bo rng, bn khai bo mDbHelper:


private NotesDbAdapter mDbHelper;

IX.Step 9
Ci t phng thc onCreateOptionsMenu(). By gi, bn s to button Add item c truy cp bng cch nhn menu button trn thit b. V chng ta xc nh rng n chim v tr u tin trong Menu. B1.Trong resource strings.xml (trong th mc res/values), v thm mt string mi c t tn menu_insert vi gi tr ca n l Add Item.
<string name="menu_insert">Add Item</string>

Sau lu file v tr v Notepadv1. B2.To mt hng menu position ti top ca lp:

public static final int INSERT_ID = Menu.FIRST;

B3.Trong phng thc onCreateOptionsMenu(), khai bo mt bin cc b result kiu boolean v gn cho super.onCreateOptionsMenu(). B4.Sau , thm menu item vi phng thc add(). By gi phng thc onCreateOptionsMenu() trng nh sau:

@Override public boolean onCreateOptionsMenu(Menu menu) {

boolean result = super.onCreateOptionsMenu(menu); menu.add(0, INSERT_ID, 0, R.string.menu_insert); return result;

Cc i s c gn vo trong phng thc add() cho bit: mt group identifier, mt unique ID, th t ca item v resource ca string s dng cho item.

X.Step 10
Ci t phng thc onOptionsItemSelected(). Trong phn ny, chng ta s x l menu item Add Note. Khi item ny trn Menu c chn, phng thc onOptionsItemSelected() s c gi vi item.getId() thit lp cho INSERT_ID (hng m bn s dng identify menu item). B1.Gi super.onOptionsItemSelected() vo cui phng thc ny. B2.Vit mt biu thc switch da vo item.getId(). Phng thc onOptionsItemSelected() trng nh sau:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case INSERT_ID: createNote(); return true; } } return super.onOptionsItemSelected(item);

XI.Step 11
Ci t phng thc createNote(). Trong phng thc ny, bn n gin ch to mt note mi vi title c gn da trn mt counter (v d, Note 1, Note 2) vi mt body trng. B1.Xy dng name vi Note v counter c nh ngha trong lp ny:
String noteName = "Note " + mNoteNumber++;

B2.Gi mDbHelper.createNote() s dng noteName lm title v lm body . B3.Gi phng thc fillData() populate danh sch cc notes phng thc ny s c to trong bc tip theo. o Phng thc createNote() trng nh sau:

private void createNote() { String noteName = "Note " + mNoteNumber++; mDbHelper.createNote(noteName, "");

fillData();

XII.Step 12
nh ngha v ci t phng thc fillData(). Phng thc ny s dng SimpleCursorAdapter v mt Cursor bind n vo cc field c cung cp trong layout. Cc field ny nh ngha cc phn t row ca list (trong v d ny, field text1 trong layout notes_row.xml). lm iu ny bn phi cung cp mt mapping t field title trong Cursor tr v n text1, m c thc hin bng cch nh ngha hai mng: u tin l mt mng string vi danh sch cc column cho map (trong v d ny l "title", t constant NotesDbAdapter.KEY_TITLE) v, th hai l mt mng int c cha cc tham chiu n cc view bn bind d liu vo (R.id.text1).

private void fillData() { // Get all of the notes from the database and create the item list Cursor c = mDbHelper.fetchAllNotes(); startManagingCursor(c); String[] from = new String[] { NotesDbAdapter.KEY_TITLE }; int[] to = new int[] { R.id.text1 }; // Now create an array adapter and set it to display using our row SimpleCursorAdapter notes = new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to); setListAdapter(notes); }

Sau y l nhng g m chng ta thc hin: B1.Sau khi nhn c Cursor t mDbHelper.fetchAllNotes(), chng ta s dng phng thc startManagingCursor() ca Activity cho php Android quan tm n lifecycle ca Cursor thay v chng ta lo lng v iu (chng ta s tho lun vn ny trong bi tp 3, nhng by gi ch bit rng iu ny cho php Android lm mt s cng vic qun l resource cho bn). B2.Sau chng ta to ra mt mng string, trong khai bo cc column m chng ta mun (trong v d ny, ch c title), v mt mng int nh ngha cc View m chng ta mun bind cc column. B3.Bc tip theo l khi to SimpleCursorAdapter. Ging nh nhiu lp trong Android, SimpleCursorAdapter cn mt Context thc hin cc cng vic ca n, v vy chng ta gn this cho context (cc lp con ca Activity thc thi Context). Chng ta gn View notes_row to ra trc lm ch cha (receptable) cho d liu, Cursor m chng ta va to ra v cc mng. Trong tng lai, hy nh rng vic mapping t cc column v cc resource c thc hin bng cch s dng th t ca hai mng mt cch tng ng. Nu bn c nhiu column bind, v nhiu View bind chng vo, bn s xc nh chng theo th t, v

d bn c th s dng {NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_BODY} v {R.id.text1, R. id.text2} bind hai field vo row (v cng cn phi nh ngha text2 trong notes_row.xml, cho body text). y l cch m bn c th bind cc field vo mt row n (v c c mt custom row layout).

XIII.Step 13
Chy ng dng.

XIV.Gii php v bi tp tip theo


Trong bi tip theo, bn s c tm hiu cch thc to, sa i v xa cc notes. Link tham kho: http://developer.android.com/resources/tutorials/notepad/notepadex1.html.

Notepad Exercise 2
Trong bi tp ny, bn s thm mt Activity th hai vo ng dng notepad, cho php user to v chnh sa cc notes. Bn cng s cho php user xa cc notes ang tn ti thng qua mt context menu. Activity mi ny chu trch nhim to cc notes mi bng cch collect user input v ng gi n vo mt Bundle tr v c cung cp bi Intent. Bi tp ny th hin: Xy dng mt Activity mi v thm n vo Android manifest. Gi mt Activity khc khng ng b (asynchronously) s dng startActivityForResult(). Gn d liu vo cc Activity thng qua cc i tng Bundle. Nng cao v s dng screen layout. To mt context menu.

I.Step 1
To project mi s dng source t Notepadv2 trong th mc NotepadCodeLab nh bn lm trong bi tp 1. M project Notepadv2 v xem xt mt s vn sau: M file string.xml trong th mc res/values c mt vi string mi m bn s s dng cho cc chc nng mi. M lp Notepadv2, bn s thy mt s constant mi c nh ngha cng vi mt field mi mNotesCursor nm gi cursor. Trong phng thc fillData() c mt vi comment mi v s dng field mi mNotesCursor lu tr Cursor. Phng thc onCreate() vn nh bi tp 1. C mt s phng thc cn override mi: onCreateContextMenu(), onContextItemSelected(), onListItemClick() v onActivityResult().

II.Step 2
u tin, to menu context cho php user xa cc notes. M lp Notepadv2 v thc hin cc cng vic sau: B1.Vo cui phng thc onCreate(), ng k context menu cho mi item trong ListView bng cch gi registerForContextMenu() v gn n vo ListView.
registerForContextMenu(getListView());

Bi v activity ca bn k tha t ListActivity, nn getListView() s tr v mt i tng local ListView cho activity. Lc ny, mi item trong ListView ny s kch hot context menu.

B2.Trong onCreateContextMenu(), gi phng thc menu.add() thm mt menu item mi xa mt note.


@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(0, DELETE_ID, 0, R.string.menu_delete); }

III.Step 3
By gi, bn ng k ListView cho mt context menu v nh ngha item trong n, v cng vic cn lm l x l khi mt item c chn. lm iu ny, bn cn xc nh list ID ca item c chn, sau xa n. V vy, bn x l trong phng thc onContextItemSelected() nh sau:

@Override public boolean onContextItemSelected(MenuItem item) { switch(item.getItemId()) { case DELETE_ID: AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); mDbHelper.deleteNote(info.id); fillData(); return true; } return super.onContextItemSelected(item); }

y, bn nhn mt AdapterContextMenuInfo t getMenuInfo(). Trng id ca i tng ny n cho bn bit v tr ca item trong ListView. Sau , bn gn gi tr ny vo deleteNote() ca NotesDbAdapter v note s c xa.

IV.Step 4
Trong phng thc createNote(), to mt i tng Intent to mt note (ACTIVITY_CREATE) s dng lp NoteEdit. Sau , pht sinh Intent s dng phng thc startActivityForResult().

Intent i = new Intent(this, NoteEdit.class);

startActivityForResult(i, ACTIVITY_CREATE);

Phng thc startActivityForResult() c s dng pht sinh mt Intent gi n mt Activity mi (trong v d ny l NoteEdit), v sau khi Activity mi ny hon tt, th activity gi phng thc ny s nhn c mt callback onActivityResult() v bn s ci t phng thc ny trong bc sau. C mt cch khc gi mt Activity l s dng startActivity(), tuy nhin khi gi phng thc ny, activity ca bn s khng nhn c callback onActivityResult() sau khi activity mi kt thc. Trong cc bc sau, chng ta s to ra lp EditNote.

V.Step 5
Trong bc ny, bn s ci t callback onListItemClick(), callback ny c gi khi user chn mt item trong list. Phng thc ny c 4 tham s ln lt l: mt ListView, mt View bn trong ListView khi c chn, position trong list c chn, v mRowId ca item c chn. Phng thc ny s dng mt Intent edit note s dng lp NoteEdit, sau thm d liu vo extras Bundle ca Intent (chng s c gn vo Activity c gi). i tng Intent ny c s dng gn title, body v mRowId cho note ang c edit. Cui cng gi phng thc startActivityForResult().

@Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Cursor c = mNotesCursor; c.moveToPosition(position); Intent i = new Intent(this, NoteEdit.class); i.putExtra(NotesDbAdapter.KEY_ROWID, id); i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString( c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE))); i.putExtra(NotesDbAdapter.KEY_BODY, c.getString( c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY))); startActivityForResult(i, ACTIVITY_EDIT); }

Phng thc putExtra() c s dng thm cc item vo extras Bundle. Trong v d ny, bn s dng Bundle gn title, body v mRowId ca note mun edit. Lu : Khi bn gn field mNotesCursor cho mt bin cc b, iu ny c thc hin nh l mt ti u ha ca m Android. Truy cp vo mt bin cc b hiu qu hn so vi truy cp vo mt field trong Dalvik VM.

VI.Step 6
Override callback onActivityResult(), callback ny c pht sinh khi mt Activity tr v mt result v Activity launch trc s dng startActivityForResult(). Phng thc ny c 3 tham s: requestCode: c xc nh trong Intent invocation (trong v d ny hoc ACTIVITY_CREATE hoc ACTIVITY_EDIT). resultCode: m kt qu hay m li ca li gi, zero nu mi th OK v non-zero nu fail. intent: y l Intent c to bi Activity ang tr v result. N c s dng tr v d liu trong Intent extras.
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); Bundle extras = intent.getExtras(); switch (requestCode) { case ACTIVITY_CREATE: String title = extras.getString(NotesDbAdapter.KEY_TITLE); String body = extras.getString(NotesDbAdapter.KEY_BODY); mDbHelper.createNote(title, body); fillData(); break; case ACTIVITY_EDIT: Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID); if (mRowId != null) { String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE); String editBody = extras.getString(NotesDbAdapter.KEY_BODY); mDbHelper.updateNote(mRowId, editTitle, editBody); } fillData(); break; } }

VII.Step 7
M file note_edit.xml, trong file ny bn lu thuc tnh android:layout_weight. Tt c cc View u c layout_weight bng zero. N cho bit t trng ca space sn c ca cc widget nn c s dng. V d, c 2 widget, widget u tin thit lp thuc tnh android:weight =1, v widget th hai thit lp android:weight=2 th nu cn space trong container cha 2 widget ny, widget th hai s chim gp i space sn c so vi widget th nht.

VIII.Step 8
To lp NoteEdit k tha t Activity. Override phng thc onCreate().
package com.android.demo.notepad2; import android.app.Activity; import android.os.Bundle; public class NoteEdit extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }

IX.Step 9
Trong bc ny, bn s ci t phng thc onCreate() ca NoteEdit. B1.Thit lp layout.
setContentView(R.layout.note_edit);

B2.Thay i title cho Activity bi string Edit Note.


setTitle(R.string.edit_note);

B3.Tm kim cc component EditText v Button thng qua cc ID ca chng trong lp R.


mTitleText = (EditText) findViewById(R.id.title); mBodyText = (EditText) findViewById(R.id.body); Button confirmButton = (Button) findViewById(R.id.confirm);

Lu : mTitleText v mBodyText l cc field member nn bn cn khai bo chng ti top ca nh ngha lp.


private EditText mTitleText; private EditText mBodyText;

B4.Ti top ca lp, khai bo mt field private Long mRowId lu tr mRowId ang c edit.

private Long mRowId;

B5.Tip tc trong onCreate(), khi to title, body v mRowId t extras Bundle trong Intent.
mRowId = null; Bundle extras = getIntent().getExtras(); if (extras != null) { String title = extras.getString(NotesDbAdapter.KEY_TITLE); String body = extras.getString(NotesDbAdapter.KEY_BODY); mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID); if (title != null) { mTitleText.setText(title); } if (body != null) { mBodyText.setText(body); } }

B6.ng k s kin cho button confirmButton.


confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { } });

X.Step 10
Trong phn ny, bn s ci t phng thc onClick() cho confirmButton. B1.To i tng Bundle v put title v body vo n.
Bundle bundle = new Bundle(); bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString()); bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString()); if (mRowId != null) { bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId); }

B2.Thit lp thng tin tr v (Bundle) cho i tng Intent mi v finish Activity.


Intent mIntent = new Intent(); mIntent.putExtras(bundle); setResult(RESULT_OK, mIntent); finish();

Trong v d ny, Intent n gin l data carrier c cha Bundle (vi title, body v mRowId). Phng thc setResult() c s dng thit lp result code v Intent tr v c gn tr li cho Intent caller. Trong v d ny, mi th lm vic OK, v vy bn tr v RESULT_OK cho result code. Phng thc finish() c s dng kt thc Activity hin ti.

Tm li, phng thc onCreate() s c ci t nh sau:


private EditText mTitleText; private EditText mBodyText; private Long mRowId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.note_edit); setTitle(R.string.edit_note); mTitleText = (EditText) findViewById(R.id.title); mBodyText = (EditText) findViewById(R.id.body); Button confirmButton = (Button) findViewById(R.id.confirm); mRowId = null; Bundle extras = getIntent().getExtras(); if (extras != null) { String title = extras.getString(NotesDbAdapter.KEY_TITLE); String body = extras.getString(NotesDbAdapter.KEY_BODY); mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID); if (title != null) { mTitleText.setText(title); } if (body != null) { mBodyText.setText(body); }

confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Bundle bundle = new Bundle(); bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText() .toString()); bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText() .toString()); if (mRowId != null) { bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId); }

} }); }

Intent mIntent = new Intent(); mIntent.putExtras(bundle); setResult(RESULT_OK, mIntent); finish();

XI.Step 11
Trong bc ny, bn m file AndroidManifest.xml thm activity mi (NoteEdit) trong tag <application> nh sau:
<activity android:name=".NoteEdit" />

XII.Step 12
Chy ng dng.

XIII.Gii php v bi tp tip theo


By gi, bn c gng edit mt note, sau nhn vo phm BACK trn Emulator thay v nhn confirm button. Bn s thy rng c mt error pht sinh. R rng l ng dng cn gp phi mt s vn . T hn na, nu bn thc hin mt s thay i v nhn button BACK, th khi quay li notepad, bn s thy rng cc thay i ca bn b mt. Trong bi tp tip theo, bn s tm hiu cch fix cc vn ny.

Link tham kho: http://developer.android.com/resources/tutorials/notepad/notepadex2.html.

Notepad Exercise 3
Trong bi tp ny, bn s s dng cc callback life-cycle lu tr v nhn state data ca ng dng. Bi tp ny s m t: Life-cycle events v lm th no ng dng ca bn c th s dng chng. Cc k thut duy tr trng thi ca ng dng.

I.Step 1
Import ng dng Notepadv3 vo Eclipse. ng dng hin ti c mt s vn nhn nt BACK trn thit b s gy ra mt crash, v bt c iu g xy ra trong qu trnh chnh sa s lm cho qu trnh edit b mt. fix vn ny, chng ta chuyn hu ht cc chc nng nh to v chnh sa note vo lp NoteEdit, v gii thiu mt full life cycle cho cc note ang c chnh sa.

B1.Remove code trong lp NoteEdit m parse title v body t extras Bundle. Thay vo , s dng lp DBHelper truy cp vo cc notes t database mt cch trc tip. Bn cn gn vo activity NoteEdit mt mRowId nu edit, ngc li nu create th khng gn g. Bn remove cc dng code sau y:
String title = extras.getString(NotesDbAdapter.KEY_TITLE); String body = extras.getString(NotesDbAdapter.KEY_BODY);

B2.Bn s thit lp gi tr cho title v body trong UI, nn bn cng b cc dng code sau y:
if (title != null) { mTitleText.setText(title); } if (body != null) { mBodyText.setText(body); }

II.Step 2
Trong lp NoteEdit, to mt field NotesDbAdapter nh sau:
private NotesDbAdapter mDbHelper;

Trong onCreate() ca NoteEdit, bn thm vo mt th hin ca NotesDbAdapter ngay bn di super.onCreate() nh sau:

mDbHelper = new NotesDbAdapter(this); mDbHelper.open();

III.Step 3
Trong NoteEdit, bn cn kim tra savedInstanceState cho mRowId, trong trng hp note editing c cha mt saved state trong Bundle, m bn s recover (iu ny xy ra nu Activity mt focus v sau restart).

B1.Thay th code ang khi to mRowId


mRowId = null; Bundle extras = getIntent().getExtras(); if (extras != null) { mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID); }

c thay th bng:
mRowId = (savedInstanceState == null) ? null : (Long) savedInstanceState .getSerializable(NotesDbAdapter.KEY_ROWID); if (mRowId == null) { Bundle extras = getIntent().getExtras(); mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID): null; }

B2.Bn cn kim tra null cho savedInstanceState, bi bn cn load mRowId t extras Bundle nu n khng c cung cp bi savedInstanceState. B3.Lu vic s dng cc Bundle.getSerializable() thay v Bundle.getLong(). on code phn sau tr v mt long primitive v do khng th c s dng i din cho trng hp khi mRowId l null.

IV.Step 4
Tip theo, bn cn populate cc field da trn mRowId nu bn c n:
populateFields();

Phng thc ny c t trc confirmButton.setOnClickListener(). Bn s nh ngha phng thc ny trong phn tip theo.

V.Step 5
Loi b Bundle trong onClick(). Activity khng cn tr v bt k thng tin extras n caller. V bi v khng cn c mt Intent tr v, chng ta ch s dng setResult() nh sau:

public void onClick(View view) { setResult(RESULT_OK); finish(); }

Bn cn cn thn trong vic lu tr cc cp nht hay cc notes mi trong database, s dng cc phng thc life-cycle. Tm li, phng thc onCreate() s trng nh sau:

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDbHelper = new NotesDbAdapter(this); mDbHelper.open(); setContentView(R.layout.note_edit); setTitle(R.string.edit_note); mTitleText = (EditText) findViewById(R.id.title); mBodyText = (EditText) findViewById(R.id.body); Button confirmButton = (Button) findViewById(R.id.confirm); mRowId = (savedInstanceState == null) ? null : (Long) savedInstanceState .getSerializable(NotesDbAdapter.KEY_ROWID ); if (mRowId == null) { Bundle extras = getIntent().getExtras(); mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID) : null; } this.populateFields(); confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { setResult(RESULT_OK); finish(); } }); }

VI.Step 6
nh ngha phng thc populateFields().
private void populateFields() { if (mRowId != null) { Cursor note = mDbHelper.fetchNote(mRowId); startManagingCursor(note); mTitleText.setText(note.getString(note .getColumnIndexOrThrow(NotesDbAdapter.KEY _TITLE))); mBodyText.setText(note.getString(note .getColumnIndexOrThrow(NotesDbAdapter.KEY _BODY))); } }

Phng thc ny s dng NotesDbAdapter.fetchNote() nhm tm kim mt note hp l edit, sau n gi startManagingCursor() t lp Activity, l mt phng thc tin li m Android cung cp qun l life-cycle ca Cursor. iu ny s release v re-create cc resource tng t nh life-cycle ca Activity. Sau , bn ch cn ly cc gi tri title v body t Cursor v populate cc phn t View vi chng.

VII.Step 7
Vn trong lp NoteEdit, bn override cc phng thc sau: onSaveInstanceState() onPause() v onResume(). y l cc phng thc life-cycle (cng vi onCreate() m bn thc hin trn). onSaveInstanceState() c gi bi Android nu Activity ang c stop v c th b kill trc khi n c tr v! iu ny c ngha l n s lu tr cc trng thi cn thit ti khi to vi cng mt iu kin khi Activity c restart. Trong thc t, i tng savedInstanceState trong onCreate() cng chnh l i tng outState trong phng thc onSaveInstanceState(). onPause() lun lun c gi khi Activity kt thc, ngay c khi chng ta gi tng minh phng thc finish(). S dng n lu tr note hin ti vo database. Ngoi ra, bn c th gii phng cc ti nguyn no c th c trong phng thc ny. onResume() s gi populateFields() c cc notes t database v populate cc field.

B1.Override onSaveInstanceState()
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); saveState(); outState.putSerializable(NotesDbAdapter.KEY_ROWID, mRowId);

Chng ta s nh ngha phng thc saveState() trong bc tip theo.

B2.Override onPause()
@Override protected void onPause() { super.onPause(); saveState(); }

B3.Override onResume()
@Override protected void onResume() { super.onResume(); populateFields(); }

Lu : saveState() phi c gi trong c onSaveInstanceState() v onPause() m bo rng d liu c lu vo database. Bi v khng c iu g m bo rng phng thc onSaveInstanceState() s lun lun c gi, v khi c gi th n s gi trc onPause().

VIII.Step 8
nh ngha saveState() put d liu vo database.
private void saveState() { String title = mTitleText.getText().toString(); String body = mBodyText.getText().toString(); if (mRowId == null) { long id = mDbHelper.createNote(title, body); if (id > 0) { mRowId = id; } } else { mDbHelper.updateNote(mRowId, title, body); }

Lu rng chng ta capture gi tr tr v t createNote() v nu mt row ID hp l c tr v, chng ta lu n trong field mRowId c th cp nht note trong tng lai, hn l to ra mt ci mi.

IX.Step 9
Ci t li phng thc onActivityResult() trong lp Notepadv3. Tt c cc cng vic cp nht by gi u xy ra trong NoteEdit life cycle, v vy trong onActivityResult(), bn ch cn cp nht li d liu ca ListView.

@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); fillData(); }

X.Step 10
Trong onListItemClick(), bn b cc dng code sau y:
Cursor c = mNotesCursor; c.moveToPosition(position); i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString( c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE))); i.putExtra(NotesDbAdapter.KEY_BODY, c.getString( c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));

By gi, phng thc onListItemClick() s nh sau:

@Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Intent i = new Intent(this, NoteEdit.class); i.putExtra(NotesDbAdapter.KEY_ROWID, id); startActivityForResult(i, ACTIVITY_EDIT); }

By gi, bn c th remove field mNotesCursor, v trong phng thc fillData() s dng mt bin cc b notesCursor thay th cho mNotesCursor.

Cursor notesCursor = mDbHelper.fetchAllNotes(); By gi, bn hy chy ng dng.

You might also like