/** * Copyright (c) 2013-2014, Rinc Liu (http://rincliu.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.rincliu.library.widget.listpager; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.Locale; import com.rincliu.library.R; import com.rincliu.library.util.RLAsyncTask; import com.rincliu.library.util.RLFileUtil; import com.rincliu.library.util.RLUiUtil; import com.rincliu.library.widget.pulltorefresh.ILoadingLayout; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; public abstract class ListPagerAdapter implements ListPagerView.DataObserver { private ListPagerView pager; private final Object obj = new Object(); private ArrayList<Object> list = new ArrayList<Object>(); private ArrayList<?> tmpList; private boolean hasFetchedData = false; private boolean isReset = false; private boolean hasMore = false; private String cacheFile = null; private String data = null; private long cacheKeepTime = 0; private int start = 0; private int tmpStart = 0; private int pageLimit = -1; private int currentPage = 0; private UpdateDataTask task; /** * @return */ protected int getNextStart() { return start; } /** * @return */ public boolean hasMore() { return hasMore; } @Override public BaseAdapter getBaseAdapter() { return adapter; } @Override public ArrayList<Object> getDataSet() { return list; } @Override public void setDataSet(ArrayList<Object> list) { this.list = list; } @Override public void notifyAdapter() { adapter.notifyDataSetChanged(); } @Override public void refresh() { if (task == null || task.getStatus() == RLAsyncTask.Status.FINISHED) { pager.setRefreshing(true); pager.setEmptyView(null); isReset = true; start = 0; tmpStart = 0; currentPage = 0; task = new UpdateDataTask(); executeTask(); } else { pager.notifyFinish(true); } } @Override public void loadMore() { if (hasMore) { if (task == null || task.getStatus() == RLAsyncTask.Status.FINISHED) { pager.setRefreshing(true); pager.setEmptyView(null); isReset = false; task = new UpdateDataTask(); executeTask(); } else { pager.notifyFinish(false); } } else { pager.notifyFinish(false); RLUiUtil.toast(pager.context, "No more data."); } } /** * @param pager * @param cacheFile * @param cacheKeepTime */ public ListPagerAdapter(ListPagerView pager, int pageLimit, String cacheFile, long cacheKeepTime) { this.pager = pager; this.cacheFile = cacheFile; this.cacheKeepTime = cacheKeepTime; this.pageLimit = pageLimit; } /** * @param data */ public void notifyFetchDataSuccess(String data) { this.data = data; if (data != null) { if (cacheFile != null && start == 0) { RLFileUtil.getInstance().write2Sd(cacheFile, data); } currentPage++; tmpList = onReadDataSet(data); } hasFetchedData = true; synchronized (obj) { obj.notify(); } } /** * */ public void notifyFetchDataFailed() { hasFetchedData = true; synchronized (obj) { obj.notify(); } } private void fetchData() { if (tmpList != null) { if (!tmpList.isEmpty()) { tmpList.clear(); } tmpList = null; } boolean isLoadFirstPage = start == 0; boolean isNeedCache = cacheFile != null && new File(cacheFile).exists(); ConnectivityManager connManager = (ConnectivityManager) pager.context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo netInfo = connManager.getActiveNetworkInfo(); boolean isNetworkNotAvailable = netInfo == null || !netInfo.isAvailable() || !netInfo.isConnected(); boolean isCacheNeverOverTime = cacheKeepTime == -1; boolean isCacheNotOverTime = false; if (isNeedCache) { isCacheNotOverTime = (cacheKeepTime != -1 && System.currentTimeMillis() - new File(cacheFile).lastModified() < cacheKeepTime); } if (isLoadFirstPage && isNeedCache && (isNetworkNotAvailable || isCacheNeverOverTime || isCacheNotOverTime) && readCache()) {} else { onFetchDataHttp(currentPage, start); } if (!hasFetchedData) { synchronized (obj) { try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } hasFetchedData = false; } private boolean readCache() { boolean readSuccess = false; data = RLFileUtil.getInstance().readFromSd(cacheFile); if (onCheckValid(data)) { tmpList = onReadDataSet(data); readSuccess = true; hasFetchedData = true; } return readSuccess; } private void dealWithData() { if (onCheckValid(data) && tmpList != null) { if (isReset) { tmpStart = 0; if (list != null) { list.clear(); } else { list = new ArrayList<Object>(); } pager.removeFooter(); } start = onReadNextStart(data); if (pager.isReverse) { Collections.reverse(tmpList); if (list == null) { list = new ArrayList<Object>(); } list.addAll(0, tmpList); } else { if (list == null) { list = new ArrayList<Object>(); } list.addAll(tmpList); } adapter.notifyDataSetChanged(); if (pageLimit == -1 || !(hasMore = onCheckHasMore(data))) { pager.addFooter(); } } else { if (isReset) { start = tmpStart; tmpStart = 0; } if (onCheckValid(data)) { String errorStr = onReadErrorMessage(data); if (errorStr != null) { RLUiUtil.toast(pager.context, errorStr); } } } adapter.notifyDataSetChanged(); ILoadingLayout layout = null; if (isReset) { if (pager.getIsShowStartTime()) { if (pager.getIsShowEndTime()) { layout = pager.getLoadingLayoutProxy(true, true); } else { layout = pager.getLoadingLayoutProxy(true, false); } } } else { if (pager.getIsShowEndTime()) { layout = pager.getLoadingLayoutProxy(false, true); } } if (layout != null) { layout.setLastUpdatedLabel(pager.context.getString(R.string.ptr_updated_at) + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(new Date( System.currentTimeMillis()))); } pager.notifyFinish(isReset); isReset = false; } private void executeTask() { task.executeOnExecutor(RLAsyncTask.DUAL_THREAD_EXECUTOR); } private class UpdateDataTask extends RLAsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(Void... params) { fetchData(); return null; } @Override protected void onCancelled() { pager.notifyFinish(isReset); } @Override protected void onCancelled(Void result) { pager.notifyFinish(isReset); } @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); } @Override protected void onPostExecute(Void result) { dealWithData(); } } private BaseAdapter adapter = new BaseAdapter() { @Override public int getCount() { return list == null ? 0 : list.size(); } @Override public Object getItem(int position) { return list == null ? null : list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { return pager.itemHandler.onGetItemView(position, convertView, parent); } }; /** * @param currentPage * @param currentStart */ public abstract void onFetchDataHttp(int currentPage, int currentStart); /** * @param data * @return */ public abstract boolean onCheckValid(String data); /** * @param data * @return */ public abstract String onReadErrorMessage(String data); /** * @param data * @return */ public abstract boolean onCheckHasMore(String data); /** * @param data * @return */ public abstract int onReadNextStart(String data); /** * @param data * @return */ public abstract ArrayList<?> onReadDataSet(String data); }