Table of Contents generated with DocToc
Titanium Studioを起動して、QiitaViewer用にプロジェクトを作成するためにFile → New → Mobile Project と進みます
Projectのテンプレートを選択する画面が標示されたら、「Default Project」を選択して次に進みます
Projectの詳細情報を入力する画面が標示されるので以下のように入力/選択して、finishボタンをクリックします
- プロジェクト名:QiitaViewer
- AppID:info.ti.qiitaviewer
- ターゲットOS:iPhone、Androidのみチェック。iPad、MobileWebはオフにする
しばらくすると、以下の様な画面が標示されて、Projectの初期設定が完了します
念のためこの状態でbuildが出来るかどうか確認するため、Titanium StudioのApp Explorerのrunのアイコンを選択します
iPhone起動時の画面キャプチャ | Android起動時の画面キャプチャ |
---|---|
Projectの設定が完了したので、次から具体的にQiitaViewerの機能を実装していきます
Qiitaの開発者向けのAPIを通じて投稿情報を取得する機能を実装します
Titanium Mobileで実装をはじめる前に、Qiitaの投稿情報を取得する時のWebAPIについて簡単に説明します
ブラウザで以下URLにアクセスすることでパブリックな新着投稿を取得することができます。
https://qiita.com/api/v1/items
投稿情報は以下の様なJSON形式になりますが、詳しい情報を知りたい方は、Qiitaのサイトをご覧ください
[{"id": 1,
"uuid": "1a43e55e7209c8f3c565",
"user":
{"name": "Hiroshige Umino",
"url_name": "yaotti",
"profile_image_url": "https://si0.twimg.com/profile_images/2309761038/1ijg13pfs0dg84sk2y0h_normal" },
"title": "てすと",
"body": "<p>foooooooooooooooo</p>\n",
"created_at": "2012-10-03 22:12:36 +0900",
"updated_at": "2012-10-03 22:12:36 +0900",
"created_at_in_words": "18 hours ago",
"updated_at_in_words": "18 hours ago",
"tags":
[{"name": "FOOBAR",
"url_name": "FOOBAR",
"icon_url": "http://qiita.com/icons/thumb/missing.png",
"versions": ['1.2', '1.3']}],
"stock_count": 0,
"stock_users": [],
"comment_count": 0,
"url": "http://qiita.com/items/1a43e55e7209c8f3c565",
"gist_url": null,
"tweet": false,
"private": false,
"stocked": false
},
...
]
QiitaのようなWebAPIと連携するアプリを開発する場合に、Titanium Mobile標準機能のhttpCLientを活用することで簡単に実現できます。 まずはhttpCLientの使い方について解説をします。
-
プロジェクト作成時に自動的に生成されたapp.jsの中身を全て削除します。
-
その後に以下を記述します
var xhr,qiitaURL,method;
qiitaURL = "https://qiita.com/api/v1/items";
method = "GET";
xhr = Ti.Network.createHTTPClient();
xhr.open(method,qiitaURL);
xhr.onload = function(){
var body;
if (this.status === 200) {
body = JSON.parse(this.responseText);
Ti.API.info(body);
} else {
Ti.API.info("error:status code is " + this.status);
}
}
xhr.onerror = function(e) {
var error;
error = JSON.parse(this.responseText);
Ti.API.info(error.error);
}
xhr.timeout = 5000;
xhr.send();
動作確認するために、buildした結果は以下のとおりです
iPhone起動時の画面キャプチャ | Android起動時の画面キャプチャ |
---|---|
シミュレーターの画面には何も標示されずコンソール上に複数の文字が標示されるかと思いますので、その点が確認できたらOKなので、次で画面に表示する方法について解説します
ご存じの方が多いかもしれませんが、念のためTitanium MobileのhttpClientについて解説します
var xhr,qiitaURL,method;
qiitaURL = "https://qiita.com/api/v1/items";
method = "GET";
xhr = Ti.Network.createHTTPClient(); // (1)
xhr.open(method,qiitaURL); // (2)
xhr.onload = function(){
var body;
if (this.status === 200) { // (3)
body = JSON.parse(this.responseText); // (4)
Ti.API.info(body);
} else {
Ti.API.info("error:status code is " + this.status);
}
}
xhr.onerror = function(e) { // (5)
var error;
error = JSON.parse(this.responseText);
Ti.API.info(error.error);
}
xhr.timeout = 5000;
xhr.send();
-
httpClientを利用するためのオブジェクトを生成します
-
open()メソッドを使ってQiitaのWebAPIにアクセスします。最初の引数にHTTPメソッドを指定しますが、Qiitaの投稿の取得をする場合には、GETメソッドを指定する必要があります(詳しくはQiitaのドキュメントを参照してください)次の引数で投稿情報を取得するQiitaのエンドポイントとなるURLを指定します。
-
QiitaのWebAPIにアクセスして、接続成功したかどうかを判定して、その後の処理を実施します。具体的にはthis.statusの値を確認して、値が200の場合には接続成功しているため該当する処理を実施します
-
this.responseTextの値を確認することで、サーバから取得できた値をテキスト形式で取得できます。this.responseTextは見た目はJSON形式になっていますが、そのまま変数に代入すると文字列としてその後処理されてしまうため、JSON.parse()を使って、JSON化した状態で変数に格納します
-
例えば、QiitaのWebAPIにアクセスして、150リクエスト/1時間というAPIの利用制限に引っかかってしまう場合などはエラーになり、その時にはonerrorイベントが呼び出されます。
イメージとしては以下のような対応関係になります
Titanium Mobileの標準APIであるhttpCLientを活用して、Qiitaの投稿情報を取得する処理までは実装出来ましたので、今度は取得した情報を画面に表示する部分について解説します
Qiitaの開発者向けのAPIを通じて投稿情報を取得した結果をTableViewを活用して表示する方法について解説します。
図にすると以下の様な処理になります。
まずは取得した投稿情報のタイトルのみを表示する以下のソースコードをサンプルに順次解説していきます。
var xhr,qiitaURL,method,mainTable,win;
mainTable = Ti.UI.createTableView({
width: 320,
height:480,
backgroundColor:"#fff",
left: 0,
top: 0
});
win = Ti.UI.createWindow({
title:'QiitaViewer'
});
qiitaURL = "https://qiita.com/api/v1/items";
method = "GET";
xhr = Ti.Network.createHTTPClient();
xhr.open(method,qiitaURL);
xhr.onload = function(){
var body,_i ,_len ,row ,rows,textLabel;
if (this.status === 200) {
body = JSON.parse(this.responseText);
rows = [];
for (_i = 0, _len = body.length; _i < _len; _i++) { // (1)
Ti.API.info(body[_i].title);
row = Ti.UI.createTableViewRow({ // (2)
width: 'auto',
height:40,
borderWidth: 0,
className:'entry',
color:"#222"
});
textLabel = Ti.UI.createLabel({ // (3)
width:'auto',
height:30,
top:5,
left:5,
color:'#222',
font:{
fontSize:16,
fontWeight:'bold'
},
text:body[_i].title
});
row.add(textLabel); // (4)
rows.push(row); // (5)
}
mainTable.setData(rows); // (6)
win.add(mainTable);
win.open();
} else {
Ti.API.info("error:status code is " + this.status);
}
};
xhr.onerror = function(e) {
var error;
error = JSON.parse(this.responseText);
Ti.API.info(error.error);
};
xhr.send();
- body.lengthの値を確認することでWebAPIから取得した投稿件数が確認できるので、その件数分ループして、投稿情報を1つづつ取り出していきます
- 投稿情報の要素を格納するためにTableViewRowを生成します
- 投稿情報のタイトル部分を格納するためにLabelを生成します
- 上記で生成したLabelをTableViewRowに配置します
- TableViewRowを配列rowsに挿入します
- WebAPIから取得した投稿件数分のTableViewRowが配列rowsに格納されているので、その情報をTableViewに表示するために、setDataメソッドを使います
上記をbuildして、iPhone、AndroidのEmulatorで表示した場合以下の様になります
iPhone起動時の画面キャプチャ | Android起動時の画面キャプチャ |
---|---|
先程は、タイトルのみ表示する方法について解説しましたが、タイトルだけではなく投稿したユーザのアイコンをTableViewを活用して表示する方法について解説します
図にすると以下の様な処理になります。
投稿したユーザのアイコンを表示するために、TitaniumのImageViewを以下のように活用します。
// 一部抜粋
imagePath = body[_i].user.profile_image_url;
iconImage = Ti.UI.createImageView({
width:40,
height:40,
top:5,
left:5,
defaultImage:"logo.png",
image: imagePath
});
row.add(iconImage);
今回のようなWebAPIを通じて画像を取得して表示するような場合、ネットワークの回線状況によってはすぐに標示されるとは限りません。
そのため、ImageViewのdefaultImageというプロパティに、あらかじめローカルに準備しておいた画像を指定することで、
- 最初にローカルの画像が表示
- 画像のダウンロード完了時に、ローカルの画像とリモートから取得した画像が入れ替わる
という処理が自動的にされるので、このdefaultImageは積極的に活用することをお勧めします
上記ソースコードをbuildして、iPhone、AndroidのEmulatorで表示した場合以下の様になります
iPhone起動時の画面キャプチャ | Android起動時の画面キャプチャ |
---|---|
TableViewを使って投稿情報のタイトルと投稿したユーザのアイコンを表示するソースコード全体は以下になります
var xhr,qiitaURL,method,mainTable,win;
mainTable = Ti.UI.createTableView({
width: 320,
height:480,
backgroundColor:"#fff",
left: 0,
top: 0
});
win = Ti.UI.createWindow({
title:'QiitaViewer'
});
qiitaURL = "https://qiita.com/api/v1/items";
method = "GET";
xhr = Ti.Network.createHTTPClient();
xhr.open(method,qiitaURL);
xhr.onload = function(){
var body,_i ,_len ,row ,rows,textLabel,iconImage,imagePath;
if (this.status === 200) {
body = JSON.parse(this.responseText);
rows = [];
for (_i = 0, _len = body.length; _i < _len; _i++) {
row = Ti.UI.createTableViewRow({
width: 'auto',
height:60,
borderWidth: 0,
className:'entry',
color:"#222"
});
textLabel = Ti.UI.createLabel({
width:250,
height:30,
top:5,
left:60,
color:'#222',
font:{
fontSize:16,
fontWeight:'bold'
},
text:body[_i].title
});
imagePath = body[_i].user.profile_image_url;
iconImage = Ti.UI.createImageView({
width:40,
height:40,
top:5,
left:5,
defaultImage:"logo.png",
image: imagePath
});
row.add(textLabel);
row.add(iconImage);
rows.push(row);
}
mainTable.setData(rows);
win.add(mainTable);
win.open();
} else {
Ti.API.info("error:status code is " + this.status);
}
};
xhr.onerror = function(e) {
var error;
error = JSON.parse(this.responseText);
Ti.API.info(error.error);
};
xhr.timeout = 5000;
xhr.send();
QiitaViewerの機能としてはひとまずここまでにとどめることにします。
次の章では、少ない手間とちょっとしたアイデアで標準APIを使ってる用に見せないための工夫について取り上げていきます