- 浏览: 760842 次
- 性别:
- 来自: 成都
文章分类
- 全部博客 (139)
- 玩转Android (48)
- Android创意美工 (0)
- Android杂谈 (23)
- Android实例练习 (2)
- Android ROM研究 (5)
- Android NDK开发指南 (5)
- Android NDK (0)
- Android Tips (3)
- Windows Phone 7 (5)
- iPhone (0)
- HTML5学习室 (0)
- JAVA (9)
- SSH+ibatis (8)
- PHP (0)
- IT生活 (1)
- linux (2)
- C (4)
- C++ (1)
- web 前端 (1)
- 云计算 (0)
- 设计模式 (0)
- C# (2)
- 其他 (1)
- 数据结构 (5)
- Web开发 (10)
- 数据库 (3)
- 搜索引擎 (0)
- Go语言 (0)
最新评论
-
wi100sh:
多谢分享~
玩转Android---UI篇---ImageButton(带图标的按钮) -
zhanghaichang:
好文章的。
高性能web开发技术(一) -
yingang:
引用classes.dex.dex2jar.jar 拖入 j ...
Andorid杂谈---Apk文件的反编译 -
扶摇诺:
讲解的简明易懂,多谢啦!
玩转Android---UI篇---LinearLayout(线性布局) -
a13429921973:
更为详细的图文介绍,可参考这个http://blog.csdn ...
Android ROM研究---CyanogenMod源代码下载及编译
1. Android Intents
1.1. Android中的SQLite
SQLite是一个嵌入在Android中的开源数据库。SQLite支持标准的关系型数据库特征,比如SQL语法,事务和预处理语句。另外它在运行时只需要很少的内存(大约250KByte)
在Android中使用SQLite不需要任何数据库的安装或管理(不需要数据库管理员)。你可以指定SQL来使用数据库工作,并且数据库会为你自动管理。
在Android中使用数据库工作可以减缓由于必要的I/O操作,因此它建议在AsyncTask中执行这项任务。
数据库支持的数据类型:
TEXT 类似JAVA中的String
INTEGER 类似JAVA中的long
REAL 类似JAVA中的double
在将这些数据保存到数据库之前,所有其他的类型都必须转换成这些类型。实际上SQLite本身不验证写入列中的类型定义,你可以写一个整数到字符串列上。
如果您的应用程序创建一个数据库,这个数据库时保存在目录
”data/data/<项目包名>/databases/数据库名”。这里的第一个data目录的路径就是
Environment.getDataDirectory()的返回值。Environment.getDataDirectory()通常返回SD卡中的位置
一个SQLite数据库相对于创建它的应用程序是私有的,如果你想将数据分享给其他应用程序,可以使用ContentProvider
1.2. SQLiteOpenHelper
在你的应用程序中通过使用子类SQLiteOpenHelper来创建和更新一个数据库,在这个类中,在数据库模式变化的情况下,你需要重写onCreate()方法来创建数据库和重写onUpdate()方法来更新数据库。这两种方法都需要接收一个SQLiteOpenHelper对象。
SQLiteOpenHelper提供方法getReadableDatabase()和getWriteableDatabase()方法来获得一个SQLiteDatabase对象,在对象可以允许访问数据库,而不管是在读或写的模式下。
对于数据库的主键,你应该一直使用标识符”_id”来作为数据库主键,在Android的一些方法中最好依赖这个标准。
SQLiteDatabase提供方法insert()、update()、delete()和可以直接执行SQL的
execSQL()方法,对象ContentValues允许为insert和update定义键值,键就是列,值就是该列对应的值。
1.3. SQLiteDatabase和Cursor(游标)
我们可以通过创建rawQuery()方法通过接收SQL查询数据,或者通过query()方法,该方法提供了一个指定动态数据或SQLiteQueryBuilder的接口。SQLiteBuilder类似内容提供者的接口,因此通常用于ContentProvider中。查询通常返回的是一个游标(Cursor)
查询方法有如下一些参数:
query(String dbName,int[] columnNames,String whereClause, String[] valuesForWhereClause, String[] groupBy, String[] having, String[] orderBy)。
如果所有的参数都要选择的话,可以将那些不需要的字句设置为null,比如where的地方设置为null,当然还可以在where的地方填入其他值(如果需要的话),比如
“_id=18 and summary=?”。如果需要几个值呢?你可以通过在valuesForWhereClause数据来查询。一般来说,如果不需要的话,可以填入null,比如groupby字句。
一个游标就代表查询结果。要过的元素的数量,可以使用getCount()方法。要一在单个数据行与行之间移动数据,可以通过moveToFirst()和MoveToNext()方法。通过isAfterLast()方法,可以检查下面是否还有数据。
在ListView中可以通过SimpleCursorAdapter适配器来直接使用游标。
2. 开始编写应用程序
2.1. 概览
下面,我们通过一个示例程序来测试,这个程序可以允许用户保持它应该做的事项。这些事项被存放在SQLite数据库中,这个应用程序包括两个Activity,一个是用来查看所有待办事项清单,一个是用户创建/维护一个特定的待办事项。这两个Activity都是通过Intent来进行沟通的。
2.2. 工程
创建功能,名字为SQLiteTest,这里有两个Activity,一个视图用来显示待办事件列表,另一个用来编辑待办事件
2.3.数据库处理
数据库帮手:MySQLiteOpenHelper.java
package com.loulijun.sqlitetest; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; public class MySQLiteOpenHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "hualang"; private static final int DATABASE_VERSION = 1; //数据库创建语句 private static final String DATABASE_CREATE = "create table test(_id integer primary key autoincrement, "+ "category text not null, summary text not null, description text not null);"; public MySQLiteOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } //创建数据库时调用 @Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); } //更新数据库时调用,比如更新数据库版本 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(MySQLiteOpenHelper.class.getName(), "upgrading database from version "+ oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS test"); onCreate(db); } }
在上面这个助手的基础上,我们可以写类"MyAdapter"。用之来提供查询,创建,更新等功能。通过助手类的open()方法打开数据库。在更新和创建值的时候,可以使用"android.content.ContentValues"类,这个类可以存储键值对,你可以使用列名作为ContentValues的键。
package com.loulijun.sqlitetest; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; public class MyAdapter { public static final String KEY_ROWID = "_id"; public static final String KEY_CATEGORY = "category"; public static final String KEY_SUMMARY = "summary"; public static final String KEY_DESCRIPTION = "description"; public static final String DATABASE_TABLE = "test"; private Context context; private SQLiteDatabase db; private MySQLiteOpenHelper dbHelper; public MyAdapter(Context context) { this.context = context; } public MyAdapter open() throws SQLException { dbHelper = new MySQLiteOpenHelper(context); db = dbHelper.getWritableDatabase(); return this; } public void close() { dbHelper.close(); } /** * 创建一个新的标test,如果test成功创建则返回一个新的列id,否则返回-1来表示失败 */ public long createTest(String category, String summary, String description) { ContentValues initialValues = createContentValues(category, summary, description); return db.insert(DATABASE_TABLE, null, initialValues); } //更新表test public boolean updateTest(long rowId, String category, String summary, String description) { ContentValues updateValues = createContentValues(category, summary, description); return db.update(DATABASE_TABLE, updateValues, KEY_ROWID + "=" +rowId, null)>0; } //删除表test public boolean deleteTest(long rowId) { return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null)>0; } //返回数据库中表test的所有游标列表 public Cursor fetchALlTests() { return db.query(DATABASE_TABLE, new String[]{KEY_ROWID, KEY_CATEGORY,KEY_SUMMARY,KEY_DESCRIPTION}, null, null, null, null, null); } //返回在表test中被定义的某个位置的游标 public Cursor fetchTest(long rowId)throws SQLException { Cursor mCursor = db.query(true, DATABASE_TABLE, new String[]{KEY_ROWID, KEY_CATEGORY, KEY_SUMMARY, KEY_DESCRIPTION}, KEY_ROWID + "=" +rowId, null, null, null,null,null); if(mCursor != null) { mCursor.moveToFirst(); } return mCursor; } private ContentValues createContentValues(String category, String summary, String description) { ContentValues values = new ContentValues(); values.put(KEY_CATEGORY, category); values.put(KEY_SUMMARY, summary); values.put(KEY_DESCRIPTION, description); return values; } }
<!--[if !supportLists]-->2.4. <!--[endif]-->资源
在res/menu/目录下创建listment.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/insert" android:title="Insert" /> </menu>
在res/values目录下,编写res/values/priority.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="priorities"> <item>紧急</item> <item>提醒</item> </string-array> </resources>
strings.xml如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, SQLiteTestActivity!</string> <string name="app_name">SQLiteTest</string> <string name="no_tests">目前没有保存的待办事项</string> <string name="menu_insert">增加事项</string> <string name="menu_delete">删除待办</string> <string name="test_summary">概要</string> <string name="test_description">描述</string> <string name="test_edit_summary">编辑概要</string> <string name="test_edit_description">编辑描述</string> <string name="test_edit_confirm">确认</string> <color name="lisicolor">#FFE87C</color> <color name="black">#000000</color> </resources>
2.5. 视图
我定义了三个布局文件,一个是为列表,一个是为列表的行,一个是为记事本的主体
这是第一个布局,用户设置列表
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:baselineAligned="@color/lisicolor" > <ListView android:id="@android:id/list" android:layout_width="fill_parent" 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_tests" /> </LinearLayout>
这是第二个布局,用于设置列表的每一行的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:layout_width="fill_parent" android:background="@color/lisicolor"> <ImageView android:id="@+id/icon" android:src="@drawable/hualang" android:layout_marginLeft="4px" android:layout_marginRight="8px" android:layout_height="40px" android:layout_marginTop="8px" android:layout_width="30px"> </ImageView> <TextView android:text="@+id/TextView01" android:layout_height="wrap_content" android:id="@+id/label" android:textSize="40px" android:layout_marginTop="6px" android:layout_width="fill_parent" android:textColor="@color/black"> </TextView> </LinearLayout>
下面是备忘录的编辑布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:background="@color/lisicolor">
<Spinner android:id="@+id/category" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:entries="@array/priorities"></Spinner>
<LinearLayout android:id="@+id/LinearLayout01"
android:layout_height="wrap_content" android:layout_width="fill_parent">
<EditText android:layout_height="wrap_content" android:id="@+id/todo_edit_summary"
android:layout_weight="1" android:layout_width="wrap_content"
android:hint="Summary"></EditText>
</LinearLayout>
<EditText android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_weight="1"
android:id="@+id/todo_edit_description" android:hint="Description" android:gravity="top"></EditText>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/todo_edit_button"
android:text="@string/test_edit_confirm"></Button>
</LinearLayout>
下面的是两个Activity的代码
SQLiteOverView.java
package com.loulijun.sqlitetest; import android.app.ListActivity; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ListView; import android.widget.SimpleCursorAdapter; public class SQLiteOverView extends ListActivity { private MyAdapter dbHelper; private static final int ACTIVITY_CREATE = 0; private static final int ACTIVITY_EDIT = 1; private static final int DELETE_ID = Menu.FIRST + 1; private Cursor cursor; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_list); this.getListView().setDividerHeight(2); dbHelper = new MyAdapter(this); dbHelper.open(); fillData(); registerForContextMenu(getListView()); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.listmenu, menu); return true; } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch(item.getItemId()) { case R.id.insert: createTest(); return true; } return super.onMenuItemSelected(featureId, item); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.insert: createTest(); return true; } return super.onOptionsItemSelected(item); } @Override public boolean onContextItemSelected(MenuItem item) { switch(item.getItemId()) { case DELETE_ID: AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo(); dbHelper.deleteTest(info.id); fillData(); return true; } return super.onContextItemSelected(item); } public void createTest() { Intent i = new Intent(this,TestDetails.class); startActivityForResult(i, ACTIVITY_CREATE); } // ListView 和 view (row) on 被点击 @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); Intent i = new Intent(this, TestDetails.class); i.putExtra(MyAdapter.KEY_ROWID, id); // Activity返回一个结果给startActivityForResult startActivityForResult(i, ACTIVITY_EDIT); } /** * 根据其他的Activity的结果被调用 * requestCode是发送到Activity的原始码 * resutCode是返回码,0表示一切OK */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); fillData(); } private void fillData() { cursor = dbHelper.fetchALlTests(); startManagingCursor(cursor); String[] from = new String[] { MyAdapter.KEY_SUMMARY }; int[] to = new int[] { R.id.label }; //现在创建一个数组适配器并且设置它现在在我们的列中 SimpleCursorAdapter notes = new SimpleCursorAdapter(this, R.layout.test_row, cursor, from, to); setListAdapter(notes); } @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); } @Override protected void onDestroy() { super.onDestroy(); if (dbHelper != null) { dbHelper.close(); } } }
TestDetails.java
package com.loulijun.sqlitetest; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; public class TestDetails extends Activity { private EditText mTitleText; private EditText mBodyText; private Long mRowId; private MyAdapter mDbHelper; private Spinner mCategory; @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); mDbHelper = new MyAdapter(this); mDbHelper.open(); setContentView(R.layout.test_edit); mCategory = (Spinner) findViewById(R.id.category); mTitleText = (EditText) findViewById(R.id.todo_edit_summary); mBodyText = (EditText) findViewById(R.id.todo_edit_description); Button confirmButton = (Button) findViewById(R.id.todo_edit_button); mRowId = null; Bundle extras = getIntent().getExtras(); mRowId = (bundle == null) ? null : (Long) bundle .getSerializable(MyAdapter.KEY_ROWID); if (extras != null) { mRowId = extras.getLong(MyAdapter.KEY_ROWID); } populateFields(); confirmButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { setResult(RESULT_OK); finish(); } }); } private void populateFields() { if (mRowId != null) { Cursor todo = mDbHelper.fetchTest(mRowId); startManagingCursor(todo); String category = todo.getString(todo .getColumnIndexOrThrow(MyAdapter.KEY_CATEGORY)); for (int i=0; i<mCategory.getCount();i++){ String s = (String) mCategory.getItemAtPosition(i); Log.e(null, s +" " + category); if (s.equalsIgnoreCase(category)){ mCategory.setSelection(i); } } mTitleText.setText(todo.getString(todo .getColumnIndexOrThrow(MyAdapter.KEY_SUMMARY))); mBodyText.setText(todo.getString(todo .getColumnIndexOrThrow(MyAdapter.KEY_DESCRIPTION))); } } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); saveState(); outState.putSerializable(MyAdapter.KEY_ROWID, mRowId); } @Override protected void onPause() { super.onPause(); saveState(); } @Override protected void onResume() { super.onResume(); populateFields(); } private void saveState() { String category = (String) mCategory.getSelectedItem(); String summary = mTitleText.getText().toString(); String description = mBodyText.getText().toString(); if (mRowId == null) { long id = mDbHelper.createTest(category, summary, description); if (id > 0) { mRowId = id; } } else { mDbHelper.updateTest(mRowId, category, summary, description); } } }
还有最后一步,注册TestDetails.java
<activity android:name=".TestDetails" android:windowSoftInputMode="stateVisible|adjustResize"/>
2.6. 运行应用程序
注意:项目是UTF-8编码的,在windows系统中用eclipse需要将其设置为UTF-8编码
相关推荐
本项目名为“iOS备忘录小程序”,是一个自编的简易备忘录应用程序示例,特别适合初学者用来学习iOS开发,尤其是数据库管理方面。下面我们将详细探讨这个小程序涉及的主要知识点。 首先,该项目采用`FMDB`库来处理...
【手机备忘录程序】是一种常见且实用的智能手机应用程序,主要功能是帮助用户记录日常生活、工作中的重要事项或想法,确保不会遗忘待办任务。它通常具有简洁的用户界面和高效的提醒机制,使得用户可以方便地创建、...
在Android平台上,开发一款备忘录应用是一...这个超精细的备忘录源码提供了一个深入学习Android应用开发,特别是数据库操作的好例子。通过分析和理解这个源码,开发者可以提升对Android系统的理解,增强实际开发能力。
这个PDF文档,"Android中使用SQLite保存备忘录数据的代码清单",提供了使用SQLite来保存备忘录数据的具体步骤和代码示例。下面我们将详细解析其中的关键知识点。 1. **SQLiteOpenHelper子类**: - 在Android中,`...
对于备忘录的存储,我们可以选择数据库(如SQLite)、文本文件或XML文件等方式。如果使用数据库,MFC提供了CDatabase和CRecordset类来操作数据库。如果使用文件,可以利用fstream进行读写操作。每条备忘录作为一个...
为了存储备忘录数据,我们可以选择使用文件系统(如XML或文本文件)、数据库(如SQLite或SQL Server Compact Edition)或者最近的序列化技术。VS2008提供了对这些存储机制的内置支持,使得开发者可以方便地进行数据...
这款APP结合了多种常用的功能,如日记编写、备忘录创建以及纪念日提醒,以提升用户的日常生活组织和回忆能力。 首先,日记功能是此类应用的核心之一。用户可以通过简洁易用的界面记录每日的心情、事件或感悟,可以...
3. **数据存储**:为了保存用户的备忘录和记事,应用可能利用了SQLite数据库,这是Android系统内置的轻量级数据库。通过ContentProvider,应用可以将数据操作封装,使得数据能在不同组件间共享。此外,考虑到简单性...
本文实例为大家分享了Intent如何实现一个简单的记事本功能的演示过程,供大家参考,具体内容如下 ...到Android SDK API 23的Samples的NotePad例子下找到app_notes.png,将其添加到该项目中,并将其换名为ch