PulltoRefresh と EndlessAdapter を使用しようとしていますが、アプリを初めて実行すると、リストは非常にうまく読み込まれますが、最後にさらにデータを読み込むとクラッシュします。
ライブラリ EndLessAdapter: https://github.com/commonsguy/cwac-endless
ライブラリ PulltoRefresh: https://github.com/chrisbanes/Android-PullToRefresh
PullToRefresh なしで動作していました。
そのアプリを初めて実行すると、次のように呼び出されます。
- getPendingView
- MyAsyncTask
- hasmoredata を返す
- postOnExecute を呼び出す - リスナー
- OnItemsReady を呼び出す
- DemoAdapter.notydatasetchanged を設定します
リストの終わりを取得すると、次のように呼び出します。
- getPendingView
- MyAsyncTask
- hasmoredata を返す
- IndexOutofBoundException を与える
スタックトレース:
01-28 11:12:15.273: E/AndroidRuntime(12735): FATAL EXCEPTION: main
01-28 11:12:15.273: E/AndroidRuntime(12735): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
01-28 11:12:15.273: E/AndroidRuntime(12735): at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
01-28 11:12:15.273: E/AndroidRuntime(12735): at java.util.ArrayList.get(ArrayList.java:311)
01-28 11:12:15.273: E/AndroidRuntime(12735): at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:225)
01-28 11:12:15.273: E/AndroidRuntime(12735): at android.widget.AbsListView.obtainView(AbsListView.java:1592)
01-28 11:12:15.273: E/AndroidRuntime(12735): at android.widget.ListView.makeAndAddView(ListView.java:1782)
01-28 11:12:15.273: E/AndroidRuntime(12735): at android.widget.ListView.fillDown(ListView.java:705)
PullToRefreshListinViewPager サンプルの内部:
public View instantiateItem(ViewGroup container, int position) {
PullToRefreshListView plv = null;
Context context = container.getContext();
plv = (PullToRefreshListView) LayoutInflater.from(context).inflate(
R.layout.layout_listview_in_viewpager, container, false);
endlessList = new ArrayList<HashMap<String, String>>();
demoAdapter = new DemoAdapter(context, endlessList);
demoAdapter.setRunInBackground(false);
plv.setAdapter(demoAdapter);
plv.setOnRefreshListener(BaseSampleActivity.this);
// Now just add ListView to ViewPager and return it
container.addView(plv, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
return plv;
}
EndLessAdapter:
private class DemoAdapter extends EndlessAdapter implements IItemsReadyListener{
private RotateAnimation rotate=null;
private View pendingView=null;
private ArrayList<HashMap<String, String>> data;
private List<HashMap<String, String>> mOriginalNames;
private boolean hasMoreData=true;
private Context mContext;
DemoAdapter(Context context, ArrayList<HashMap<String, String>> d) {
super(new LazyAdapter(context, d));
this.data = d;
this.mContext = context;
rotate=new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatCount(Animation.INFINITE);
}
@Override
protected View getPendingView(ViewGroup parent) {
View row = LayoutInflater.from(mContext).inflate(R.layout.row, null);
View child=row.findViewById(android.R.id.text1);
child.setVisibility(View.GONE);
child=row.findViewById(R.id.throbber);
child.setVisibility(View.VISIBLE);
child.startAnimation(rotate);
return(row);
}
@Override
protected boolean cacheInBackground() {
if(isNetworkOnline() == true){
new MyAsyncTask(this, data.size()).execute();
}
return hasMoreData;
}
public void onItemsReady(ArrayList<HashMap<String, String>> data) {
endlessList.addAll(data);
demoAdapter.onDataReady(); // Tell the EndlessAdapter to remove it's pending
// view and call notifyDataSetChanged()
hasMoreData = endlessList.isEmpty();
}
@Override
protected void appendCachedData() {
if (getWrappedAdapter().getCount()<75) {
@SuppressWarnings("unchecked")
LazyAdapter a=(LazyAdapter)getWrappedAdapter();
for (int i = 0; i < data.size(); i++) {
a.add(data.get(i));
}
}
}
}
非同期タスク:
private static class MyAsyncTask extends AsyncTask<Void,Void,ArrayList<HashMap<String, String>>>{
IItemsReadyListener listener;
int startPoint;
public MyAsyncTask(IItemsReadyListener listener, int startPoint) {
// TODO Auto-generated constructor stub
this.listener = listener;
this.startPoint = startPoint;
}
@Override
protected ArrayList<HashMap<String, String>> doInBackground(Void... params) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
for (int i = 0; i < 10; i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
endlessList.add(map);
}
return (endlessList);
}
@Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result)
{
listener.onItemsReady(endlessList);
// Getting adapter by passing xml data ArrayList
if (demoAdapter != null)
{
demoAdapter.notifyDataSetChanged();
}
}
}
アップデート:
私はただ変更します:
@Override
protected boolean cacheInBackground() throws Exception {
if(isNetworkOnline() == true){
new MyAsyncTask(this).execute();
}
if (getWrappedAdapter().getCount()<75) {
return(true);
}
throw new Exception("Gadzooks!");
}
より多くのコンテンツをロードするようになりましたが、3 回ロードして最終段階に入ると、例外 Gadzooks がスローされ、同じ IndexOutofBoundException が表示されます。
cacheinBackground が false を返すたびにクラッシュすることを知っています。