I have a ListFragment with an adapter and a AsyncTask to load data, currently it builds up a listview with text, and I have put a non-dynamic image as a place holder for now. I was wondering if someone could shed light on the best way to implement downloading images from the net, I have url's to test from google, and caching and showing those images through the adapter, I don't have a scrolllistener yet for when the page reaches bottom, but I am kinda stuck on what the best solution to pass over and load my dynamic images would be, if someone could tell me the best way to load images and preferably cache them, so I don't not have to download them to sd card and everything every time.
Here are my classes
TestListFragment
public class TestListFragment extends ListFragment
implements
android.support.v4.app.LoaderManager.LoaderCallbacks<List<TestItemModel>> {
TestCustomArrayAdapter _adapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
System.out.println("TestListFragment.onActivityCreated");
// Initially there is no data
setEmptyText("Refresh: No Data Here");
// Create an empty adapter we will use to display the loaded data.
_adapter = new TestCustomArrayAdapter(getActivity());
setListAdapter(_adapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Insert desired behavior here.
Log.i("TestListFragment", "Item clicked: " + id);
TestItemModel ti = this._adapter.getItem(position);
System.out.println(ti.getId());
}
@Override
public Loader<List<TestItemModel>> onCreateLoader(int arg0, Bundle arg1) {
System.out.println("TestListFragment.onCreateLoader");
return new TestListLoaderAsync(getActivity());
}
@Override
public void onLoadFinished(Loader<List<TestItemModel>> arg0,
List<TestItemModel> data) {
_adapter.setData(data);
System.out.println("TestListFragment.onLoadFinished");
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
@Override
public void onLoaderReset(Loader<List<TestItemModel>> arg0) {
_adapter.setData(null);
}
}
TestCustomArrayAdapter
public class TestCustomArrayAdapter extends ArrayAdapter<TestItemModel> {
private final LayoutInflater _inflater;
public OnItemClickListener ol;
public TestCustomArrayAdapter(Context context) {
super(context, R.layout.test_list_fragment);
_inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setData(List<TestItemModel> data) {
clear();
if (data != null) {
for (TestItemModel appEntry : data) {
add(appEntry);
}
}
}
/**
* Populate new items in the list.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = _inflater.inflate(R.layout.test_single_item, parent, false);
} else {
view = convertView;
}
TestItemModel item = getItem(position);
((TextView) view.findViewById(R.id.item_label)).setText(item.getName());
((TextView) view.findViewById(R.id.item_id)).setText(item.getId());
ImageView image = (ImageView) view.findViewById(R.id.image_id);
Resources resources = this.getContext().getResources();
image.setImageDrawable(resources.getDrawable(R.drawable.ic_launcher));
Button btn = (Button) view.findViewById(R.id.button_id);
Button btn2 = (Button) view.findViewById(R.id.button_id_2);
Button btn3 = (Button) view.findViewById(R.id.button_id_3);
ol = new OnItemClickListener(position, item);
btn.setOnClickListener(ol);
btn.setTag(1);
btn2.setOnClickListener(ol);
btn2.setTag(2);
btn3.setOnClickListener(ol);
btn3.setTag(3);
return view;
}
private class OnItemClickListener implements OnClickListener {
private int _position;
private TestItemModel _ti;
public OnItemClickListener(int position, TestItemModel ti) {
_position = position;
_ti = ti;
}
// TODO
// provide functionality for which button was clicked then pass the item
// to which it was clicked in.
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_id:
// btn clicked
Toast.makeText(getContext(),
" Button1 clicked at positon" + v.getTag(),
Toast.LENGTH_SHORT).show();
break;
case R.id.button_id_2:
// btn2 clicked
Toast.makeText(getContext(),
" Button2 clicked at positon" + v.getTag(),
Toast.LENGTH_SHORT).show();
break;
case R.id.button_id_3:
Toast.makeText(getContext(),
" Button3 clicked at positon" + v.getTag(),
Toast.LENGTH_SHORT).show();
// btn 3 clciked
break;
}
// the view is the button, so you get get the tag it has set with
// v.getTag() to know what button is pressed.
Log.v("YOOO",
"Button Click at position " + _position + " " + v.getTag()
+ " Item ID = " + _ti.getId());
}
}
}
TestListLoaderAsync
public class TestListLoaderAsync extends AsyncTaskLoader<List<TestItemModel>> {
List<TestItemModel> _models;
public TestListLoaderAsync(Context context) {
super(context);
}
@Override
public List<TestItemModel> loadInBackground() {
System.out.println("TestListLoader.loadInBackground");
// You should perform the heavy task of getting data from
// Internet or database or other source
// Here, we are generating some Sample data
// Create corresponding array of entries and load with data.
List<TestItemModel> entries = new ArrayList<TestItemModel>(5);
entries.add(new TestItemModel("Java", "1"));
entries.add(new TestItemModel("C++", "2"));
entries.add(new TestItemModel("Python", "3"));
entries.add(new TestItemModel("JavaScript", "4"));
entries.add(new TestItemModel("D", "5"));
entries.add(new TestItemModel("C", "6"));
entries.add(new TestItemModel("Perl", "7"));
entries.add(new TestItemModel("Fortran", "8"));
entries.add(new TestItemModel("Cobalt", "9"));
entries.add(new TestItemModel("Ruby", "10"));
entries.add(new TestItemModel("Pascal", "11"));
entries.add(new TestItemModel("HTML", "12"));
entries.add(new TestItemModel("CSS", "13"));
entries.add(new TestItemModel("PHP", "14"));
entries.add(new TestItemModel("MYSQL", "15"));
TestItemModel lastItem = new TestItemModel("C#", "16");
lastItem.setId("TestingId");
entries.add(lastItem);
return entries;
}
/**
* Called when there is new data to deliver to the client. The super class
* will take care of delivering it; the implementation here just adds a
* little more logic.
*/
@Override
public void deliverResult(List<TestItemModel> listOfData) {
if (isReset()) {
// An async query came in while the loader is stopped. We
// don't need the result.
if (listOfData != null) {
onReleaseResources(listOfData);
}
}
List<TestItemModel> oldApps = listOfData;
_models = listOfData;
if (isStarted()) {
// If the Loader is currently started, we can immediately
// deliver its results.
super.deliverResult(listOfData);
}
// At this point we can release the resources associated with
// 'oldApps' if needed; now that the new result is delivered we
// know that it is no longer in use.
if (oldApps != null) {
onReleaseResources(oldApps);
}
}
/**
* Handles a request to start the Loader.
*/
@Override
protected void onStartLoading() {
if (_models != null) {
// If we currently have a result available, deliver it
// immediately.
deliverResult(_models);
}
if (takeContentChanged() || _models == null) {
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad();
}
}
/**
* Handles a request to stop the Loader.
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Handles a request to cancel a load.
*/
@Override
public void onCanceled(List<TestItemModel> apps) {
super.onCanceled(apps);
// At this point we can release the resources associated with 'apps'
// if needed.
onReleaseResources(apps);
}
/**
* Handles a request to completely reset the Loader.
*/
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// At this point we can release the resources associated with 'apps'
// if needed.
if (_models != null) {
onReleaseResources(_models);
_models = null;
}
}
/**
* Helper function to take care of releasing resources associated with an
* actively loaded data set.
*/
protected void onReleaseResources(List<TestItemModel> apps) {
}
}
TestItemModel
public class TestItemModel {
private String name;
private String id;
public TestItemModel(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Keep in mind this is all in testing phase, dummy state, so I know some things should be cleaned up, etc.. that was all part of the plan when I got this to work. Thanks.