Reputation: 35
I have this application where I implement the ActionBar Fragment interface. Underlying the interface, there is one ListFragment where the entries in the list keep duplicated every time I switch to a different tab. Can somebody show me the correct way to implement the listfragment with custom adapter?
The following is my code: FeaturedFragment.java
public class FeaturedFragment extends ListFragment {
static final String URL = "http://www.sundancepost.com/ivue/Featured.xml";
static final String KEY_PROJECT = "project"; // parent node
static final String KEY_BANNER = "banner";
ListView featuredList;
FeaturedListAdapter featuredAdapter;
ArrayList<HashMap<String, String>> projectsList = new ArrayList<HashMap<String, String>>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.featured_list, container, false);
featuredList = (ListView)view.findViewById(android.R.id.list);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ConnectivityManager cMgr = (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
if (cMgr.getActiveNetworkInfo() != null && cMgr.getActiveNetworkInfo().isConnectedOrConnecting()) {
new MyAsyncTask().execute();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Please check your internet connection");
builder.setTitle("Failed to download resources");
builder.setCancelable(false);
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
return;
}
});
AlertDialog alert = builder.create();
alert.show();
}
featuredAdapter = new FeaturedListAdapter(getActivity(), projectsList);
}
public class MyAsyncTask extends AsyncTask<Void,Void,Void>{
private final ProgressDialog recents_dialog = new ProgressDialog(getActivity());
@Override
protected Void doInBackground(Void... params) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL);
Document doc = parser.getDomElement(xml);
NodeList nl = doc.getElementsByTagName(KEY_PROJECT);
for (int i = 0; i < nl.getLength(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
map.put(KEY_BANNER, parser.getValue(e, KEY_BANNER));
projectsList.add(map);
}
return null;
}
@Override
protected void onPreExecute()
{
recents_dialog.setMessage("Loading ...");
recents_dialog.show();
recents_dialog.setCancelable(false);
}
@Override
protected void onPostExecute(Void result)
{
if(recents_dialog.isShowing() == true)
{
recents_dialog.dismiss();
}
// Getting adapter by passing xml data ArrayList
featuredList.setAdapter(featuredAdapter);
}
}
}
FeaturedListAdapter:
public class FeaturedListAdapter extends BaseAdapter {
private Activity activity;
ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public FeaturedListAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data= (ArrayList<HashMap<String, String>>) d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if(vi==null){
vi=new View(activity);
vi = inflater.inflate(R.layout.featured_listrow, null);
}
ImageView banner =(ImageView)vi.findViewById(R.id.banner); // thumb image
banner.setAdjustViewBounds(true);
imageLoader.DisplayImage(data.get(position).get(FeaturedFragment.KEY_BANNER), banner);
return vi;
}
}
[Edit] The following code is modified based on @10s's suggestion. But, the result is still the same..
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.featured_listrow, null);
holder = new ViewHolder();
holder.banner = (ImageView)convertView.findViewById(R.id.banner);
holder.banner.setAdjustViewBounds(true);
imageLoader.DisplayImage(data.get(position).get(FeaturedFragment.KEY_BANNER), holder.banner);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
return convertView;
}
public static class ViewHolder {
public ImageView banner;
}
Upvotes: 0
Views: 2255
Reputation: 694
The Reason for adding duplicate entries each time you switch the tab is, your onActivityCreated() method is called each n every time you switch to this tab. And hence your AsyncTask executes each time and in AsyncTask's doInBackground() method, you kept on adding your element to projectList arraylist without clearing it.
Clear the projectList before starting asyncTask or check whether the list contain some data or not and based on that make a call to execute asyncTask(if list is null or doesn't contain any elements).
Upvotes: 0
Reputation: 1699
The code that you are using in getView() of the Custom adapter is recreating the view every time it is called. And the adapter does re-render itself every time your activity, in your case fragment takes focus.
Try using a holder for your adapter. It is the android best practice and a very easy and useful one. A link to get you started: http://android.amberfog.com/?p=296
Upvotes: 1