现在的位置: 首页 > 综合 > 正文

Eclipse开发Android应用程序入门:重装上阵

2013年10月17日 ⁄ 综合 ⁄ 共 9140字 ⁄ 字号 评论关闭

Eclipse开发Android应用程序入门:重装上阵

作者: coolshell  发布时间: 2011-04-12 10:56  阅读: 1662 次  推荐: 1   原文链接   [收藏]  

  原文:http://www.smashingmagazine.com/2011/03/28/get-started-developing-for-android-with-eclipse-reloaded/

  在我们教程系列的第一部分中,我们使用Android和Eclipse开发了一个简单的饮茶计时器的应用程序。在第二部分,我们将继续开发这个程序,并给它增加一些其他的额外的功能。在开发的过程中,我们将给你介绍更多重要而强大的Android SDK特性,包括持久化数据存储,Activity和Intent,和共享用户首选项(译者注:类似于windows
的注册表的一种机制)。

  跟着本教程,你需要上一篇教程中的代码,如果你想直接使用代码,你可以使用如下的指令从GitHub上check out出tutorial_par_1标记的代码:

$ git clone git://github.com/cblunt/BrewClock.git
$ cd BrewClock
$ git checkout tutorial_part_1

  在GitHub中检出了代码后,你需要将代码倒入到Eclipse中的项目中:

  1. 运行 Eclipse 选择 File → Import…
  2. 在导入窗口, 选择 “Existing Projects into Workspace”并点击 “Next.”
  3. 在下一屏,点击 “Browse,”选择你从GitHub上clone出的代码目录。
  4. 点击“Finish” 将项目导入到Eclipse中。

  在导入项目到Eclipse之后,你有可能会看到有如下的警告信息:

Android required .class compatibility set to 5.0.
Please fix project properties.

  如果有这种情况,右键点击“Project Explorer ”中新导入的BrewClock项目,并选择 “Fix Project Properties,” 并重启Eclipse。

  数据持久化入门

  当前,BrewClock 让用户为他们泡的茶设置一个定时器。这个非常棒的一个工作,但是如果对于不同的茶使用同一个泡茶时间的结果会怎样呢,是不每种茶都应该有自己的一个泡茶时间呢?如果这样,那岂不是所有的用户都需要记下每一类茶所需要泡的时间!这不是一个很好的用户体验。因此,在这篇教程中,我将新增一个功能来为用户每种不同的茶叶存放一个泡茶时间,并当用户想泡茶的时候,可以从茶叶列表中进行选择。

  为了实现这个目的,我们得利用Android的丰富的数据持久化的API。Android提供了几种方式来存储数据,本文将要覆盖其中的两种方式。第一种,使用SQLite数据库引擎来为我们存储数据。

  SQLite 是一种流行的轻量级SQL数据库引擎,它将数据存在单个文件中。SQLite经常用于桌面或在那些运行不能运行客户端-服务器SQL引擎(例如MySQL或PostgreSQL)的嵌入式的应用上。

  每个安装在Android上的应用都可以保存和使用多个SQLite数据库文件(由数据存储容量决定),这些数据由系统自动地进行管理。应用程序的数据是私有并且不能被其他的应用程序所访问。(数据可以通过ContentProvider(译者注:内容提供者类)类进行共享,但是我们不会在本教程中覆盖关于内容提供者的内容)。当数据应用程序被更新时,数据库文件就进行持久化,当应用程序被删除时,数据库文家就被删除。

  我们在BrewClock应用使用SQLite数据来维护我们的茶叶列表和泡茶所需要的时间。下面是我们我们将使用的数据表的一个总体介绍。

+-------------------------------------+
| Table: teas |
+------------+------------------------+
| Column | Description |
+------------+------------------------+
| _ID | integer
, autoincrement |
| name | text
, not null |
| brew_time | integer
, not null |
+------------+------------------------+

  如果以前你使用过SQL,你应该熟悉这些内容。数据表有三个字段,一个唯一标示(_ID),茶叶名称(name)和泡茶时间(brew_time)字段。我们将使用Android提供给我们的API在应用中建立数据表。系统将负责在正确的位置为我们的创建数据库文件。

  抽象数据库

  为了确保数据库的代码容易被维护,我们用一个单独的类TeaData来抽象所有处理数据库创建,插入,和查询的代码。如果你熟悉模型-试图-控制(译者注:MVC)方法的话,这个你也应该熟悉。所有数据库代码与我们的BrewClockActitvity类隔离开来。Actitvity可以初始化一个新的TeaData实例(这个实例将连接数据库)并完成它所需要的工作。以这种方式工作保证了我们可以方便的更改我们所使用的数据库而不用修改其他那些和数据库不相关部分的代码。

  通过菜单File → New → Class.在BrewClock项目中创建一个TeaData的新类。确保TeaData扩展于android.database.sqlite.SQLiteOpenHelper 类,并选中“Constructors from superclass”复选框。
  TeaData 类将为你自动地处理SQLite数据库的创建和版本。我们需要增加一些方法来作为其他代码到数据库的接口。

  增加两个常量来存储数据库的名字和版本,增加表名和表中列名。我们使用Android提供的常类BaseColumns._ID来做为表的唯一id列:

// src/com/example/brewclock/TeaData.java
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.provider.BaseColumns;

public class TeaData extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "teas.db";
private static final int DATABASE_VERSION = 1;

public static final String TABLE_NAME = "teas";

public static final String _ID = BaseColumns._ID;
public static final String NAME = "name";
public static final String BREW_TIME = "brew_time";

//
}

  为TeaData增加一个构造方法,以数据库名称合版本号为参数调用其父类的构造方法。Android将会自动地打开数据库(如果数据库不存在就自动创建它)。

// src/com/example/brewclock/TeaData.java
public TeaData(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

  我们需要重载onCreate方法,并执行一个SQL 串执行创建数据库表的操作。Android将会在数据库文件第一次被创建时调用这个方法。

  在启动过程中,Android检查数据库的版本是否我们传入的版本一致。如果版本发生了改变,Android将会调用onUpgrade方法,在这个方法总,你可以编写修改数据库结构的业务逻辑。在本教程中,我们将让Android删除数据库并重建数据库。

在onCreate和onUpgrade中增加如下的代码:

// src/com/example/brewclock/TeaData.java
@Override
public void onCreate(SQLiteDatabase db) {
// CREATE TABLE teas (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, brew_time INTEGER);
String sql =
"CREATE TABLE " + TABLE_NAME + " ("
+ _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ NAME + " TEXT NOT NULL, "
+ BREW_TIME + " INTEGER"
+ ");";

db.execSQL(sql);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(
"DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}

  下一步,我们需要新增代码让我们方便地在数据库中新增茶叶记录。我们新增一个带茶叶名称和泡茶时间的方法来负责插入记录。Android为了尽量避免开发者使用SQL语句,提供了一堆类来处理向数据库中查入记录。首先,我们创建一个ContentValues集合,并将相关的值插入到这个集合中去。

  对于ContentValues集合,我们只要简单地提供一个列名和值来插入就行了。Android负责创建和运行正确的SQL。使用Android的数据类确保了你能写出安全,跨平台的数据库操作代码。

  Add a new method, insert(), to the TeaData class:

// src/com/example/brewclock/TeaData.java
public void insert(String name, int brewTime) {
SQLiteDatabase db
= getWritableDatabase();

ContentValues values
= new ContentValues();
values.put(NAME, name);
values.put(BREW_TIME, brewTime);

db.insertOrThrow(TABLE_NAME,
null, values);
}

  查询数据

  我们应用程序具有了在数据库中保存数据的能力后,我们同样也需要一种方式将数据取回来。Android提供了游标Cursor接口来完成这件工作。一个游标代表了针对数据库运行一个SQL返回的结果集,游标在这个结果集中维护了一个指针来指向结果集中的一行。这个指针可以向前,向后移动,并返回每一列的值,下面我们用图形来帮助你理解游标:

  SQL 查询: SELECT * from teas LIMIT 3;

+-----------------------------------+

| _ID | name | brew_time |

+-----------------------------------+

|
1 | Earl Grey | 3 |

|
2 | Green | 1 | <= Cursor

|
3 | Assam | 5 |

+-------+-------------+-------------+

  在这个例子中,游标指向了结果集中的第二条记录(绿茶)。我们可以通过调用cursor.moveToPrevious()方法,将游标向前移动,让它指向第一行(Earl Grey),或者调用moveToNext向前移动指向Assam。要取到游标所指向记录的茶叶的名称,我们只要调用cursor.getString(1),1代表我们向提取数据列的下标(注意下标识从0开始的,1代表第二列,依次类推)。

  在了解游标后,我们增加一个创建游标对象并返回数据库中所有的茶叶信息。在TeaData中增加all方法:

// src/com/example/brewclock/TeaData.java
public Cursor all(Activity activity) {
String[] from
= { _ID, NAME, BREW_TIME };
String order
= NAME;

SQLiteDatabase db
= getReadableDatabase();
Cursor cursor
= db.query(TABLE_NAME, from, null, null, null, null, order);
activity.startManagingCursor(cursor);

return cursor;
}

  因为这个方法乍一看有点古怪,所以让我们先来关心一下这个方法的一些细节。我们没有使用SQL的查询语句,而是使用了Android提供的数据库接口方法。

  第一,我们需要告诉Android,我们所关心的列的信息。我们创建了一个字符串数组,数组中存放这TeaData中列的标示信息。我们还设置了我名们期望的结果集按照哪一个列进行排序的列名。

  第二,我们使用getReadalbeDatabase()创建了一个到数据库的只读连接,并调用query方法告诉Android我们希望用query方法运行一个查询。query()方法有很多的参数,Android在内部将这些参数转化为一个查询语句。此外,Android的抽象层保证了即使底层数据储存机制发生了变化,我们的应用程序代码也能正确的工作。

  由于我们只要返回表中的所有记录,所以我们没有在方法中使用到链接join,过滤filter和分组group(例如:在SQL中的WHERE,JOIN,和GROUP BY)。from和order变量告诉查询数据库需要返回那些列和提取数据时按什么列进行排序。我们使用SQLiteDatabase.query()作为和数据库的人机交互接口。

  最后,我们让Activity(在本例中,我们的BrewClockActivity)来管理游标。通常,游标需要人工刷新内容,因此当我们增加一个新茶信息到数据库中时,我们就需要刷新我们的游标。每当我们的应用被挂起和恢复的时候,通过调用startManagingCursor()让Android来帮我们重建结果集。

  在TeaData类中增加count方法:

// src/com/example/brewclock/TeaData.java
public long count() {
SQLiteDatabase db
= getReadableDatabase();
return DatabaseUtils.queryNumEntries(db, TABLE_NAME);
}

  保存TeaData类,使用修正没有import 的类(Source → Organize Imports),在完成我们的数据类后,下一步我们将着手修改我们BrewClock的人机界面。

  修改BrewClock用户界面,允许进行茶叶选择

  持久化茶和泡茶的时间的目的是让用能快速的选择他们所钟爱的预设置的茶。为了完成这个功能,我们需要再BrewClock的主界面上增加一个Spinner(类似于桌面上弹出菜单),生成一个来自于TeaData的茶列表。

  和前面的教程一样,我们使用了Eclipse的布局器编辑器在BrewClock的主界面布局XML文件中增加Spinner。在LinearLayout元素下面增加下面这些代码(大约在24行)。如果你打开了可视化的布局编辑器后,你可以点击窗口下面的地”Code View”进行切换。

<!-- /res/layout/main.xml -->

<!-- Tea Selection -->
<LinearLayout
android:orientation="vertical"
android:layout_width
="fill_parent"
android:layout_height
="wrap_content">

<Spinner
android:id="@+id/tea_spinner"
android:layout_width
="fill_parent"
android:layout_height
="wrap_content" />

</LinearLayout>

  在BrewClockActivity类里面,增加一个成员变量指向Spinner,通过使用findViewById连接界面上的控件:

// src/com/example/brewclock/BrewClockActivity.java
protected Spinner teaSpinner;
protected TeaData teaData;

//

public void onCreate(Bundle savedInstanceState) {
//
teaData = new TeaData(this);
teaSpinner
= (Spinner) findViewById(R.id.tea_spinner);
}

  运行你的程序以确保新的界面正确地生效。你应该在泡茶计数器下看见一个空白的弹出式菜单(或者是Spinner)。如果点击spinner,Android将显示一个弹出式的菜单并为你提供选择列表。在这时,菜单的内容因该是空的,现在让我们来绑定Spinner和我们的茶叶数据库。

  数据绑定

  当Android从数据库中查询数据时,它将会返回一个游标Cursor对象。Cursor代表了来自数据库的结果集,并可以移动游标来提取结果中的数据。使用一类Android提供的称为“适配器Adapter”的类,我们很容易将这个结果集绑定到Spinner上。适配器完成了提取数据库结果集中的数据并在界面上显示这些数据等这些复杂而困难工作。

  在我们的TeaData.all()方法中已经可以返回一个带有tea表内容的游标,使用这个游标,我们所需要做的工作就是创建一个SimpleCursor适配器来绑定我们的teaSpinner,Android会负责处理将数据显示在spinner的列表中。

  通过创建一个SimpleCursorAdapter类来连接Spinner与teaData.all()返回的游标:

// com/example/brewclock/BrewClockActivity.java

public void onCreate(Bundle savedInstanceState) {
//
Cursor cursor = teaData.all(this);

SimpleCursorAdapter teaCursorAdapter
= new SimpleCursorAdapter(
this,
android.R.layout.simple_spinner_item,
cursor,
new String[] { TeaData.NAME },
new int[] { android.R.id.text1 }
);

teaSpinner.setAdapter(teaCursorAdapter);
teaCursorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
}

  注意,我们使用了Android内建的android.R对象。这个对象提供了你的应用程序中的默认资源,例如视图和布局。在我们的代码中,我们使用了android.R.layout.simple_spinner_item,它是简单的文本标签布局。

  如果你再次运行的应用程序,你将会看到spinner中仍然是空的!虽然我们已经连接了我们的数据库,但是由于数据库中没有任何记录,所以我们任何看到了空列表。

  我们通过在构造方法中增加一些默认记录来让用户可以选择所需要的茶叶,为了避免重复记录,我们只有在数据库中记录为0的情况才增加默认记录。在本教程的代码中,我们使用前面增加的count()来检查数据库中表记录是否为空。

  增加当数据库中表为空的默认记录代码。把这些代码增加从数据库提取茶叶数据的前面(译者注:上一段的代码前)。

// com/example/brewclock/BrewClockActivity.java
public void onCreate(Bundle savedInstanceState) {
//

// Add some default tea data! (Adjust to your preference <img src="http://coolshell.cn/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley">
if(teaData.count() == 0) {
teaData.insert(
"Earl Grey", 3);
teaData.insert(
"Assam", 3);
teaData.insert(
"Jasmine Green", 1);
teaData.insert(
"Darjeeling", 2);
}

// Code from the previous step:
Cursor cursor = teaData.all(this);

//
}

  现在再次运行你的应用程序。你将会发现茶叶Spinner有了一条选择。点击Spinner让你可以从数据库选择你要的茶叶。

  恭喜你!你已经成功关联了你的界面和代码。这是任何软件开发过程中一个非常重要的方面。正如你所看见的,Android将这一步简化的非常容易,但是功能有是非常的NB。使用游标和适配器,你可以将数据源(丛简单的字符串数组到复杂的数据库查询)绑定到任何类型的视图:spinner或列表,设置是类似iTunes
cover-flow gallery!

  虽然现在已经可以开始泡茶了,但是我们工作还远没有结束。当你从Spinner选择了不同的茶,这个选择却不会发生任何作用。我们需要根据用户所选茶叶的种类取更新我们的泡茶时间。

  读取选中茶叶数据并更新泡茶时间

抱歉!评论已关闭.