ListViewで表示される分だけデータをロードする


以前の記事でも紹介しているようにListViewでは文字や画像を表示することができます。

しかし、Adapterを単純にListViewに設定してしまうと1度に画面に表示できないデータも
ロードしてしまうため、データの数が多い場合はデータのロードに時間がかかってしまいます。

通常、1画面に表示できるデータは限られていますので、
表示できる分だけデータをロードすれば不要なデータはロードする必要がなくなり、
ロード時間を短縮することができます。

詳細な説明は続きをご覧下さい。

ポイントは画面に表示するべきデータ数だけをロードして、
画面がスクロールしたら必要なデータだけをロードすることです。
これを実現するためには画面のスクロールを検知する必要があります。
ListViewの基本的な使い方については「リストビューを使ってデータを一覧表示する」をご覧下さい。

ListView.OnScrollListener

ListView.OnScrollListenerを使うことで、
ListViewのスクロール状態を検知できるので、
スクロールしたときに表示するべきデータを選別できるようにします。

まず、クラスにListView.OnScrollListenerインタフェースを実装します。

public class slowLoadList extends ListActivity implements ListView.OnScrollListener

次にonScrollStateChangedメソッドをオーバーライドします。
onScrollStateChangedメソッドはスクロールの状態を検知するためのメソッドです。
以下のようにスクロール中と画面をはじいたときにはフラグを立ててデータを表示しないようにして、
スクロールが終わったときにフラグを外してデータを表示するようにします。

// スクロールの状態を検知する
public void onScrollStateChanged(AbsListView view, int scrollState) {
	switch (scrollState) {

	// スクロールしていない
	case OnScrollListener.SCROLL_STATE_IDLE:

		// スクロール中であることを示すフラグをfalseに
		mBusy = false;

		// ListViewの表示するべきデータ位置を取得
		int first = view.getFirstVisiblePosition();
		int count = view.getChildCount();

		// ListViewに表示するべきデータを設定する
		for (int i = 0; i < count; i++) {
			TextView t = (TextView) view.getChildAt(i);
			if (t.getTag() != null) {
				t.setText(mStrings[first + i]);
				t.setTag(null);
			}
		}
		break;

	// スクロール中
	case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
		mBusy = true;
		break;

	// はじいたとき
	case OnScrollListener.SCROLL_STATE_FLING:
		mBusy = true;
		break;
	}
}

あとは、adapterのgetViewメソッドの実装を以下のようにします。
スクロール中であればデータを表示せずにLoadingと表示させます。

public View getView(int position, View convertView, ViewGroup parent) {
	TextView text;

	if (convertView == null) {
		text = (TextView) mInflater.inflate(
				android.R.layout.simple_list_item_1, parent, false);
	} else {
		text = (TextView) convertView;
	}

	// スクロール中でなければデータを表示する
	if (!mBusy) {
		text.setText(mStrings[position]);
		text.setTag(null);

	// スクロール中であればデータを表示せずにLoadingと表示
	} else {
		text.setText("Loading...");
		// Non-null tag means the view still needs to load it's data
		text.setTag(this);
	}

	return text;
}