问题
I'm building a gridview that contains alot of images likely around 1000++ pictures. To reduce the loading time for the gridview, I want to implement an onScrollListener using AbsListView. I will limit 20 images per view, then when scrolling reaches bottom it will load another 20 images. This will repeat until all images has been loaded.
I've been googling samples, but doesnt seem to find one that suits my codes. Could anyone please guide me how it is done? I'm currently using imageloader Lazylist for my images. Also I'm using AsyncTask.
MainGridView.class
public class MainGridView extends SherlockActivity {
private ProgressDialog pDialog;
ArrayList<HashMap<String, String>> songsList;
static final String KEY_SONG = "song";
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_CAT_ARTIST = "artistcat";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";
static final String KEY_BIG_URL = "big_url";
static final String KEY_CAT_URL = "cat_url";
static String IMAGE_POSITION;
GridView grid;
MainGridViewLazyAdapter adapter;
String cat_url;
String artist_url;
private int visibleThreshold = 5;
private int currentPage = 0;
private int previousTotal = 0;
private boolean loading = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gridview_main);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
checkInternetConnection();
grid = (GridView) findViewById(R.id.grid_view);
grid.setOnScrollListener(new OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if (loading) {
if (visibleItemCount > totalItemCount) {
loading = false;
previousTotal = totalItemCount;
currentPage++;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// I load the next page of gigs using a background task,
// but you can call any function here.
new loadGridView().execute(currentPage + 1);
loading = true;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
});
}
public class loadGridView extends AsyncTask<Integer, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainGridView.this);
pDialog.setTitle("Connect to Server");
pDialog.setMessage("This process can take a few seconds to a few minutes, depending on your Internet Connection Speed.");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
@Override
protected String doInBackground(Integer... args) {
// updating UI from Background Thread
Intent in = getIntent();
songsList = new ArrayList<HashMap<String, String>>();
cat_url = in.getStringExtra(KEY_CAT_URL);
artist_url = in.getStringExtra(KEY_CAT_ARTIST);
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(cat_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 < nl.getLength(); 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));
map.put(KEY_BIG_URL, parser.getValue(e, KEY_BIG_URL));
// adding HashList to ArrayList
songsList.add(map);
}
return null;
}
@Override
protected void onPostExecute(String args) {
ActionBar ab = getSupportActionBar();
ab.setTitle(artist_url);
adapter=new MainGridViewLazyAdapter(MainGridView.this, songsList);
grid.setAdapter(adapter);
pDialog.dismiss();
}
}
回答1:
I suppose you want to load images from Urls. For that purpose, you could use this solution: Lazy load of images in ListView
In order to control your paging using onScrollListener
, I think you want to see the Endless scrolling example. This is a simplistic example, but the only thing you have to add is a check if you have reached the last item of your xml.
Inside your AsyncTask
(called at each new loading), you would only parse a bit of data from your xml (corresponding to 20 items in your case). This is an example of use based on your code:
public class MainGridView extends SherlockActivity implements OnScrollListener {
public static final String KEY_SONG = "song";
public static final String KEY_ID = "id";
public static final String KEY_TITLE = "title";
public static final String KEY_ARTIST = "artist";
public static final String KEY_CAT_ARTIST = "artistcat";
public static final String KEY_DURATION = "duration";
public static final String KEY_THUMB_URL = "thumb_url";
public static final String KEY_BIG_URL = "big_url";
public static final String KEY_CAT_URL = "cat_url";
private final static int ITEMS_PPAGE = 20;
private ProgressDialog mDialog;
private ArrayList<HashMap<String, String>> mSongsList;
private static String IMAGE_POSITION;
private GridView mGridView;
//MainGridViewLazyAdapter mAdapter;
private ArrayAdapter<String> mAdapter;
private String cat_url;
private String artist_url;
private int mVisibleThreshold = 5;
private int mCurrentPage = 0;
private int mPreviousTotal = 0;
private boolean mLoading = true;
private boolean mLastPage = false;
private String mXml;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(SherlockBarUtils.getCurrentTheme(this));
super.onCreate(savedInstanceState);
setContentView(R.layout.gridview_main);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
//checkInternetConnection();
mGridView = (GridView) findViewById(R.id.grid_view);
mGridView.setOnScrollListener(this);
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
//mAdapter=new MainGridViewLazyAdapter(MainGridView.this);
mGridView.setAdapter(mAdapter);
new DownloadDataAsyncTask().execute();
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mLoading) {
if (totalItemCount > mPreviousTotal) {
mLoading = false;
mPreviousTotal = totalItemCount;
mCurrentPage++;
// Find your own condition in order to know when you
// have finished displaying all items
if (mCurrentPage + 1 > 50) {
mLastPage = true;
}
}
}
if (!mLastPage && !mLoading &&
(totalItemCount - visibleItemCount) <= (firstVisibleItem + mVisibleThreshold)) {
new AddItemsAsyncTask().execute();
mLoading = true;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
public class DownloadDataAsyncTask extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
mDialog = new ProgressDialog(MainGridView.this);
mDialog.setTitle("Connect to Server");
mDialog.setMessage("This process can take a few seconds to a few minutes, depending on your Internet Connection Speed.");
mDialog.setIndeterminate(false);
mDialog.setCancelable(false);
mDialog.show();
}
@Override
protected String doInBackground(String... args) {
// Downloading XML
/*
Intent in = getIntent();
mSongsList = new ArrayList<HashMap<String, String>>();
cat_url = in.getStringExtra(KEY_CAT_URL);
artist_url = in.getStringExtra(KEY_CAT_ARTIST);
XMLParser parser = new XMLParser();
mXml = parser.getXmlFromUrl(cat_url); // getting XML from URL
*/
return null;
}
@Override
protected void onPostExecute(String args) {
/*
getSupportActionBar().setTitle(artist_url);
*/
mDialog.dismiss();
mLoading = false;
}
}
public class AddItemsAsyncTask extends AsyncTask<Integer, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(Integer... args) {
MainGridView.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// Parsing 20 more items and adding them to the adapter
for (int i = mCurrentPage * ITEMS_PPAGE; i < (mCurrentPage + 1) * ITEMS_PPAGE; i++) {
MainGridView.this.mAdapter.add(String.valueOf(Math.random() * 5000));
}
MainGridView.this.mAdapter.notifyDataSetChanged();
}
});
return null;
}
@Override
protected void onPostExecute(String args) {
}
}
}
For the convenience, I used texts instead of images inside the GridView
. I focused on the paging system so I didn't parse XML, just added some random values on the fly.
Also, you could consider using the same addItemsAsyncTask
to download only a part (20 items) of your xml at each loading instead of downloading the whole 1000+ items before creating the GridView
.
来源:https://stackoverflow.com/questions/12170466/android-using-gridview-with-onscrolllistener