とりあえず作ってみたAndroidアプリの中で一番苦労した部分。そして、きっともっと良い方法はあるであろうやり方。Threadの理解が足りていないのが原因だろう。イケてないやり方だが自分の振り返り用に一応メモしておく。
まず検索部分は初めてのAndroid 第3版の7章「世界との接続」の4節「Webサービスの使い方」の翻訳アプリを参考にして、guiThreadとsearchThreadを用意した。本を読めばわかるので、詳細は省く。
guiThread = new Handler();
searchThread = Executors.newSingleThreadExecutor();
で、下までいったら次のリストを検索とは下記のようにしてListenerをセットした。SearchTaskは初めてのAndroidでいうTranslateTaskにあたるもので、検索した結果のItemをItemListAdapterにaddしていくTask。今の商品リストにaddしたいので、今のItemListAdapterのilaをSearchTaskに渡している。getListView().setOnScrollListener(new OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (totalItemCount == firstVisibleItem + visibleItemCount) { // ListView最下であるか
if (offset == totalItemCount || totalItemCount % 20 != 0) { // 次のリストがあるか
return;
}
offset = totalItemCount;
String query = queryText.getText().toString().trim();
if (query.length() == 0) {
return;
}
try {
SearchTask task = new SearchTask(MainActivity.this, Main.Activity.ila, query, offset);
searchThread.submit(task);
} catch (RejectedExecutionException e) {
}
}
}
public void onScrollStateChanged(AbsListView abslistview,int scrollState) {
}
});
これを実行して下までスクロールして見ると、下記エラーで上手く動かない。いじれるのはcreateしたoriginal threadだけらしい。android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
ここから調べてみたり実行してみたりでトライアンドエラーの連続。結局上手い方法がわからなかった。
で、どうしたのかというと結局新しくnewして別のItemListAdapterをSearchTaskに渡すことにした。
getListView().setOnScrollListener(new OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (totalItemCount == firstVisibleItem + visibleItemCount) { // ListView最下であるか
if (offset == totalItemCount || totalItemCount % 20 != 0) { // 次のリストがあるか
return;
}
offset = totalItemCount;
String query = queryText.getText().toString().trim();
if (query.length() == 0) {
return;
}
try {
items = new ArrayList();
for (int i = 0; i < MainActivity.this.ila.getCount(); i++) {
items.add(MainActivity.this.ila.getItem(i));
}
ItemListAdapter ila2 = new ItemListAdapter(MainActivity.this, items);
SearchTask task = new SearchTask(MainActivity.this, ila2, query, offset);
searchThread.submit(task);
} catch (RejectedExecutionException e) {
}
}
}
public void onScrollStateChanged(AbsListView abslistview,int scrollState) {
}
});
なんかイケてない気がする。あと、これだとリストの一番上に戻ってしまう。getListView().setSelectionFromTop(offset, getListView().getHeight() - 30);
こんな感じにしておいた。-30は適当。しないと下にリストが追加されたのが分かりにくかったため^^;;やっつけ実装感は否めない。もう少しThread周りを勉強して理解して出直してこよう。