How to refresh a listview within a Fragment

400 views Asked by At

I'm currently trying to build an android application which goal is to display 3 tabs (with a fragment per tab). Each tab display a listview with its proper information. The problem is that when i'm trying to refresh the listview after, for example, after deleting an element, I have trouble refreshing the good listview. Infact, I noticed that when I first load my application, I can freely delete an element on my first listview (in the first tab) and it'll refresh normally. But, if I slide to the next tab (to the right) and try to delete an item, it won't delete the item on this listview, but in the 1st one. Same thing, if I slide to the right once again, and try to delete an element, it will delete an item on the middle fragment (the 2nd one). From this time, wether I delete items on the 1st, 2nd or third tab won't matter because it's only the 2nd one which will be updated.

I think there's an underlying cycle of life mechanism which I don't understand explaining all this but I don't know what to change to my code.

In term of organization I have a MainActivity with 3 ListFragments (TabImages, TabMusiques, TabVideos). I'm using a FragmentStatePagerAdapter to instanciate my fragments depending on the position currently viewed by the user.

/**
 * Adapter used to instanciate the right Fragment depending on the current tab selected in the
 * MainActivity.
 */
public class ViewPagerAdapter extends FragmentStatePagerAdapter {

      // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
      CharSequence Titles[];
      // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
      int NumbOfTabs;


      //Build a Constructor and assign the passed Values to appropriate values in the class
      public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb) {
        super(fm);

        this.Titles = mTitles;
        this.NumbOfTabs = mNumbOfTabsumb;
   }

   /**
    * This method returns the fragment for a given position in the tabs
    * @param position Integer describing the position in the tabs of the activity
    */
    @Override
    public Fragment getItem(int position) {

        if(position == 0) // if the position is 0 we are returning the First tab
        {
            TabImages tabImages = new TabImages();
            return tabImages;
        }
        else if(position == 1)   //if the position is 1 we are returning the Second type of tab
        {
            TabMusiques tabMusiques = new TabMusiques();
            return tabMusiques;
        }
        else //else we return the last type of tab
        {
            TabVideos tabVideos = new TabVideos();
            return tabVideos;
        }


   }

   /**
    * This method returns the titles for the Tabs in the Tab Strip
    * @param position position of the tab asked
    * return the title of the tab
    */
    @Override
    public CharSequence getPageTitle(int position) {
        return Titles[position];
    }

    /**
     * This method returns the Number of tabs for the tabs Strip
     */
    @Override
    public int getCount() {
        return NumbOfTabs;
    }
}

Fragment :

public class TabImages extends ListFragment {

//Views
private View rootView;

//Vars
private Dossier dossier;
private StableArrayAdapterImage adapterImages;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

/**
 * Method called on the creation of the Fragment (initiated by the MainActivity)
 */
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    //Inflate the layout of the music tab
    rootView = inflater.inflate(R.layout.tab, container, false);

    dossier = new Dossier("Dossier1", "02/06/2015", EnumTypeElement.IMAGE);

    //Creating the object to add to the Dossier
    Element d1 = new Dossier("sous-dossier1", "03/12/2008", EnumTypeElement.IMAGE);
    Element d2 = new Dossier("sous-dossier2", "23/03/2002", EnumTypeElement.IMAGE);
    Element i1 = new Image("image1", "12/12/2012");
    Element i2 = new Image("image2", "13/03/2007");
    Element i3 = new Image("image3", "00/00/0000");
    Element i4 = new Image("image4", "15/15/1515");
    Element i5 = new Image("image5", "21/12/2345");
    Element i6 = new Image("image6", "22/11/1994");
    Element i7 = new Image("image7", "12/08/1995");
    Element i8 = new Image("image8", "01/12/1985");

    try {
        dossier.ajouterElement(d1);
        dossier.ajouterElement(d2);
        dossier.ajouterElement(i1);
        dossier.ajouterElement(i2);
        dossier.ajouterElement(i3);
        dossier.ajouterElement(i4);
        dossier.ajouterElement(i5);
        dossier.ajouterElement(i6);
        dossier.ajouterElement(i7);
        dossier.ajouterElement(i8);
    }
    catch (WrongTypeElementException e){
        e.getMessage();
    }

    adapterImages = new StableArrayAdapterImage(getActivity(), android.R.layout.simple_list_item_1, dossier.getListeElement());
    setListAdapter(adapterImages);

    return rootView;
}

public void updateFragmentImages(){
    if(adapterImages != null){
        adapterImages.notifyDataSetChanged();
    }
}

/**
 * Method called once the Fragment is created
 * Allows us to register the Context menu and make it available for the event listeners
 * @param savedInstanceState If the fragment is being re-created from a previous state, this is the state
 */
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    registerForContextMenu(getListView());
}

/**
 * Method called on click of a ListView item
 * @param l the ListView on which the call occured
 * @param v the View containing the ListView
 * @param position the position of the item clicked
 * @param id the id of the item clicked
 */
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

    Element element = dossier.getListeElement().get(position);

    if(element instanceof Dossier) //Si l'element est un dossier
    {
        Toast.makeText(getActivity(), "Impossible de lire un fichier actuellement", Toast.LENGTH_SHORT).show();
    }
    else
    {
        //Clicking on a element result in the launching of the lecture activity
        Intent myIntent = new Intent(v.getContext(), ImageLectureActivity.class);
        myIntent.putExtra("dossier", dossier);
        myIntent.putExtra("position", position);
        startActivityForResult(myIntent, 0);
    }

}

/**
 * Listener of the LongClick on an item of the list
 * Results in the layout inflation of the menu
 * @param menu The context menu being created
 * @param v The view for which the context menu is being built
 * @param menuInfo additional information on the menu (depends mainly on the view v)
 */
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);

    MenuInflater inflater = this.getActivity().getMenuInflater();
    inflater.inflate(R.menu.context_menu_images, menu);
    menu.setHeaderTitle(R.string.menuImageTitle);
}

/**
 * Listener of the click on an item of the contextual menu
 * Handles the items one by one
 * @param item selected item of the menu.
 * @return true to override the behaviour of the click on the item, false otherwise
 */
@Override
public boolean onContextItemSelected(MenuItem item) {
    final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
    switch (item.getItemId()) {
        case R.id.menu1:
            return true;
        case R.id.menu2:
            return true;
        case R.id.menu3:
            //Handles the click on the "Supprimer" button of the context menu
            new AlertDialog.Builder(getActivity())
                    .setTitle("Supprimer")
                    .setMessage("Confirmer la suppression")
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            try{
                                dossier.supprimerElement(info.position);
                                updateFragmentImages();
                            }
                            catch(ElementNotFoundException e) {
                                e.getMessage();
                            }
                        }
                    })
                    .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // do nothing
                        }
                    })
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .show();
            return true;
        default:
            return super.onContextItemSelected(item);
    }
}
}

Adapter used to populate the listview (there's an adapter per tab because the 3 listviews won't take the same objects :

package com.antoine.polytelecommande.views.Adapters;

public class StableArrayAdapterImage extends ArrayAdapter<Element> {

private HashMap<String, Integer> mIdMap = new HashMap<>();

/**
 * Constructor of the adapter.
 * Iterates on the element of the list to populate the HashMap mIdMap.
 * @param context Application context passed to the adapter.
 * @param textViewResourceId layout used for the listview.
 * @param objects List of Images used to populate the listview.
 */
public StableArrayAdapterImage(Context context, int textViewResourceId, List<Element> objects) {
    super(context, textViewResourceId, objects);
    for (int i = 0; i < objects.size(); ++i) {
        mIdMap.put(objects.get(i).toString(), i);
    }
}

/**
 * Getter of an item in the listview given its position.
 * @param position position in the listview.
 * @return the id of the item.
 */
@Override
public long getItemId(int position) {
    String item = getItem(position).toString();
    return mIdMap.get(item);
}


@Override
public boolean hasStableIds() {
    return true;
}

}
0

There are 0 answers