Edited at

重いTableViewを開く時に体感速度を上げる小ネタ

More than 3 years have passed since last update.

Titanium Advent Calendar 2014 5日目の記事です。


はじめに

久々ですが、またTitaniumを使い始めました。

ずいぶん使い勝手が良くなって安定性も向上しておりびっくりしています。

iOSとAndroidの両方への対応がほぼ必須となった現在、Titaniumは非常に有力な選択肢だと思っています。

特にスマートフォンをクライアントと捉える、サーバーサイド主体のWebアプリとの相性は抜群ですね。

わたしはちょっと細かいですが、アプリの質が上がったかなと思える小ネタを紹介します。


使えるならListViewを使う

Titaniumでコレクションを扱うUIコンポーネントとして、長い間TableViewが利用されてきましたが、SDK 3.1.0からパフォーマンスや使い勝手が改善されたListViewが登場し、問題はかなり改善されました。

ListViewはテンプレートを事前に定義しておき、そこにデータをバインドすることで高速にUIを構築することが出来ます。

そのため現在では通常ListViewを使うことによって性能の改善が行えます。

しかしListViewはTableViewと異なってRowを動的に書き換えるなどの動作を行うことは出来ません。

そこで、重いTableViewが含まれたWindowを開くときの体感速度を上げる方法です。


Windowを開いてからTableViewRowを生成する

Alloyフレームワークを使った時の一例です。

<Alloy>

<Window id="window">
<TableView id="table" onClick="openItem">
<TableViewRow>
<ActivityIndicator id="indicator" />
</TableViewRow>
</TableView>
</Window>
</Alloy>

var jsonData = [

{
text: 'text1'
},
{
text: 'text2'
}
];

function createTableData(data) {
var tableData = [];

_.each(data, function(v, i) {
var row = Ti.UI.createTableViewRow({
rowIndex: i,
json: v
});

var textLabel = Ti.UI.createLabel({
text: v.text,
});

row.add(textLabel);

// 他にも要素をTableViewRowに追加するなど

tableData.push(row);
});

return tableData;
}

function openItem(e) {
var item = e.rowData;
alert(item.json.text);
}

// テーブルの生成を遅延させてウィンドウのOpenを高速化
setTimeout(function() {
$.table.data = createTableData(jsonData);
}, 100);


最後のsetTimeoutが肝

最初にViewとなるXMLでTableViewを作成し、RowにActivityIndicatorを入れておきます。

これでRowの1つ目にインジケータが表示されます。

次にTableViewRowを作成する処理は関数化しておき、最後にsetTimeoutで100ms遅延させてから呼び出してTableViewにdataをセットします。

普通はWindowをopenしたとき、TableViewRowが生成されるのを待ってからWindowが開かれるので、タップしてから数秒の待ち時間が発生してしまいます。

しかしsetTimeoutで遅延させることで、まずWindowはタップされたら即時openし、重いTableViewの場合は生成されるまでインジケータが回るので体感速度が大幅に上がって気持ちサクサクになります。

私が調べたところ、iOSではsetTimeoutのウェイト時間は0でもOKでしたがAndroidでは100ms必要でした。

どうしても、重いTableViewを扱わなければならないシーンに出くわしたら思い出して見て下さいね。


次は

明日は @ganezasan さんです。よろしくお願いします!