首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

应用Titanium Mobile开发iPhone/Android应用(10)- 数据库的使用

2012-07-27 
使用Titanium Mobile开发iPhone/Android应用(10)- 数据库的使用数据库的使用这回我们说说使用数据库来操作

使用Titanium Mobile开发iPhone/Android应用(10)- 数据库的使用
数据库的使用

这回我们说说使用数据库来操作数据。具体来说,就是我们在Twitter客户端的Home页面,取得Timeline数据后将其保存,这样一来我们就能在启动的时候显示前一次取得的Timeline数据,也能够检索Timeline中的内容。

取得Timeline

在最开始的页面上我们不仅仅显示自己的信息,也将Follow中的人的Timeline取出来显示。在以前我们做成的table_view.js中,关于Timeline取得部分的代码做如下修改:

Ti.include("lib/twitter_api.js");Ti.include("twitter_settings.js");Ti.include("tweet_db.js");//initializationTi.App.twitterApi = new TwitterApi({    consumerKey: TwitterSettings.consumerKey,    consumerSecret: TwitterSettings.consumerSecret});var twitterApi = Ti.App.twitterApi;twitterApi.init(); twitterApi.statuses_home_timeline(    {        onSuccess: function(response){            updateTimeline(db.savedTweets());        },        onError: function(error){            Ti.API.error(error);        }    });

截止目前的message_window.js中的TwitterApi的初期化移到table_view.js中去,还有,通过TwitterApi对象实现TimeLine的取得。


Titanium.Database

在TItanium中,提供了通过Titanium.Database这个对象来访问RDBMS的功能,不管是在iPhone还是在Android中都能够使用提供的SQLite库。SQLite是Public Domain的RDBMS,由于其轻量并且高速的运行,被各个领域使用。如果习惯了MySQL等RDBMS的话,应该使用起来不会是困难。

这里,我们先做成一个连接数据库的对象,新做成一个tweet_db.js文件放置到Resources文件夹下,然后编写一下代码,在使用这个对象的时候,可以使用函数TweetDB。
var TweetDB = function() {    this.dbName = 'tweetdb'; //(1)        this.open = function () { //(2)        this.db = Titanium.Database.open(this.dbName);    };    this.close = function () { //(3)        this.db.close();    };    this.addTweets = function (tweets) { //(4)        this.open();        for (var i=0;i<tweets.length;i++) {            var tweet = tweets[i];            var rows = this.db.execute( //(5)                'SELECT * FROM tweets WHERE status_id = ?',                tweet.id_str            );            Ti.API.debug('Found: ' + rows.getRowCount() );            if ( rows.getRowCount() > 0 ) continue;            var res = this.db.execute(                'INSERT INTO tweets (screen_name, profile_image_url, tweet_text, status_id, created_at) VALUES(?,?,?,?,?)',                tweet.user.screen_name,                tweet.user.profile_image_url,                tweet.text,                tweet.id_str,                tweet.created_at            );            Ti.API.debug('Add to DB');        }        this.close();        return true;    };    this.open();    this.db.execute('CREATE TABLE IF NOT EXISTS tweets (screen_name TEXT, profile_image_url TEXT, tweet_text TEXT, status_id TEXT, created_at TEXT)');    this.close();};

我们从头解释一下这段代码。

最开始(1)的位置,把连接的数据库名设置到对象的属性中。

在下来的(2),(3)的位置,分别定义了open和close方法。这两个方法中,只是简单的实现了在数据库处理的开始时调用Titanium.Database.open,终了时调用close处理的功能。在open方法中,使用了Titanium.Database.open方法来开启数据库的连接。通过这个方法返回的Titatnium.Database对象来实现以后的各个数据库操作。

后边(4)的位置,我们定义了addTweet方法,将获取到TimeLine信息的数据tweets中需要保存的数据保存到数据库中。首先需要通过this.open()来连接到数据库。之后,对于TimeLine中的各个Tweet判断是否已经保存(A),没有保存的话,保存到数据库当中(B)。
var rows = this.db.execute(  'SELECT * FROM tweets WHERE status_id = ?',   tweet.id_str);Ti.API.debug('Found: ' + rows.getRowCount() );if ( rows.getRowCount() > 0 ) continue;

其中所说的(A)处理就是,(5)位置的处理,对于保存到this.db当中的Titatnium.Database对象执行SQL的SELECT查询。其中第一个参数中的SQL语句里带有的‘?’是第二个参数以后为了变化SQL语句的占位符。

SQL执行后的结果中,如果有返回数据的时候,从execute方法的返回对象Titanium.Database.ResultSet的getRowCount()方法能判断出来。在这个例子中,返回数据的时候,判断getRowCount()比0大的时候,因为该Tweet已经被保存到了数据库中,所以不需要做任何处理,继续处理下一条Tweet。

还有在接下来的代码中,(B)的往数据库中保存数据部分,通过执行INSERT语句,将各个Tweet信息保存到DB中。

TimeLine中所有的Tweet处理完成之后,调用this.close()方法。关闭数据库连接,结束处理。

还有一个重要的地方是在定义了saveTweet方法之后,有以下代码:
this.db.execute('CREATE TABLE IF NOT EXISTS tweets (screen_name TEXT, profile_image_url TEXT, tweet_text TEXT, status_id TEXT, created_at TEXT)');

这段代码在这个TweetDB对象在被new的时候,只执行一次,tweets表不存在的时候,在数据库中做成tweets表的CREATE TABLE语句。

这样一来我们就准备好了往数据库中保存Tweet。TimeLine取得部分中将会保存Tweet。
var db = new TweetDB();twitterApi.statuses_home_timeline(    {        onSuccess: function(response){            db.addTweets(response);            updateTimeline(response);        },        onError: function(error){            Ti.API.error(error);        }    });

首先是做成TweetDB对象,在获取自己的TimeLine的时候,把内容传给addTweets方法,然后就能将Tweet内容保存到数据库中。

取出Tweet

因为我们已经把Tweet保存到了数据库中,表示的时候就需要从数据库中把Tweet取出来显示。这样一来,最新的Tweet和过去的Tweet就能连续的表示到页面上了。

下边在tweet_db.js中编写获取Tweet的getSavedTweets方法。
this.getSavedTweets = function() {    this.open();    var rows = this.db.execute( 'SELECT * FROM tweets ORDER BY created_at DESC' ); //(1)    var res = [];    if ( rows.getRowCount() > 0 ) {        while ( rows.isValidRow() ) { //(2)            var tweetObj = {};            tweetObj.user = {};            tweetObj.user.screen_name = rows.fieldByName('screen_name');            tweetObj.user.profile_image_url                = rows.fieldByName('profile_image_url');            tweetObj.text = rows.fieldByName('tweet_text');            var date = new Date(rows.fieldByName('created_at'));            tweetObj.created_at = date.toLocaleString();            res.push(tweetObj);            rows.next();        }    }    rows.close();    this.close();    return res;};

在(1)的位置,执行SELECT语句,将保存的所有Tweet取出。然后在(2)的位置将取出来的Tweet循环处理,挨个将其变化成和Twitter API返回的数据相同的结构。这里重点是循环处理的最后位置的rows.next()方法,一旦执行了这个方法,rows中指定的数据内容就变成了下一条数据,如果下一条数据不存在的话,isValidRow()将会返回false循环处理结束。

而且,Titanium.Database.ResultSet对象中的rows被close之后,以后将不能再被使用。所以还需要修改table_view.js中表示时候的Tweet取得方法。
twitterApi.statuses_home_timeline(    {        onSuccess: function(response){            db.addTweets(response);            updateTimeline(db.getSavedTweets());        },        onError: function(error){            Ti.API.error(error);        }    });

TimeLine取得之后,将其保存,然后再从数据库总取得数据。

检索Tweet

在这篇的最后,我们来实现一下简单的检索功能:按下页面左上角的Search按钮后,弹出检索窗口,然后能通过用户名来检索Tweet。


在tweet_db.js中追加,返回包含特定字符的用户的Tweet的方法。
this.searchByScreenName = function (screen_name) {    this.open();    var rows = this.db.execute(        'SELECT * FROM tweets WHERE screen_name like ?',        '%' + screen_name + '%'    );    var res = [];    if ( rows.getRowCount() > 0 ) {        while ( rows.isValidRow() ) {            var tweetObj = {};            tweetObj.user = {};            tweetObj.user.screen_name = rows.fieldByName('screen_name');            tweetObj.user.profile_image_url                = rows.fieldByName('profile_image_url');            tweetObj.text = rows.fieldByName('tweet_text');            var date = new Date(rows.fieldByName('created_at'));            tweetObj.created_at = date.toLocaleString();            res.push(tweetObj);            rows.next();        }    }    rows.close();    this.close();    return res.length ? res : null;;

和getSavedTweets方法基本上是一样的。参数中要执行的查询SQL语句的WHERE部分稍有不一样。SQL的WHERE部分通过like检索screen_name,返回用户名中包含了特定字符的用户的Tweet。

下来继续修改table_view.js的显示部分。
var search = Titanium.UI.createSearchBar({  //(1)    height:43,    top:0});win1.add(search);search.addEventListener('return', function(e) //(2){    var query = e.value;    var res = db.searchByScreenName(query);    if (res) {        updateTimeline(res);    }    search.blur();    search.hide();});search.addEventListener('change', function(e) //(3){    if (e.value.length == 0 ) {        updateTimeline(db.savedTweets());        search.blur();        search.hide();    }});search.hide(); //(4)var searchButton = Ti.UI.createButton( //(5)    {        title: 'search'    });searchButton.addEventListener( //(6)    'click',    function () {        search.show();    });win1.leftNavButton = searchButton;

在这部份代码中,(1)的位置是做成SearchBar对象。

(2)的位置是SearchBar中换行处理的监听。在(2)这里调用了刚才做好的searchByScreenName()方法,只显示用户名中包含输入的字符的用户的Tweet。

(3)的位置是SearchBar中字符发生变化时处理的监听。当SearchBar中没有字符的时候,将会把所有的Tweet表示出来。

SearchBar如果一直表示的话也不好,所以在(4)的位置将其先隐藏,然后在(5)的位置做成一个将SearchBar表示出来的按钮。

(6)的位置当按钮按下后,通过SearchBar对象的show()方法将其表示出来。

总结一下,我们说明了使用SQL来操作Tweet的数据,不仅能表示过去的Tweet信息,又能够实现Tweet的检索。从Tweet的例子当中我们也可以看出,在检索不重复保存的相同数据的时候,SQL也是很方便的。如果在使用Titanium开发应用的时候,需要使用大量的数据,最好考虑使用SQL。

热点排行