21

I have a main activity which contains the action bar with 3 menu buttons in it.

I then have a fragment within this main activity which has a list.

I would like to be able to refresh the list in the fragment from the main activity, when one of the menu buttons is clicked, or preferably just removed all the rows from the list.

Any help is appreciated.

Thanks.

public class Favourite extends SherlockFragmentActivity {

    ActionBar actionBar;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.favourite);

        actionBar = getSupportActionBar();

        actionBar.setDisplayShowTitleEnabled(false);

        BitmapDrawable bg = (BitmapDrawable)getResources().getDrawable(R.drawable.actionbar_bg);
        bg.setTileModeX(TileMode.REPEAT); 
        getSupportActionBar().setBackgroundDrawable(bg);

        getSupportActionBar().setIcon(R.drawable.favourite_title);

        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        ActionBar.Tab tabAll = actionBar.newTab();
        ActionBar.Tab tabfavs = actionBar.newTab();
        ActionBar.Tab tabhist = actionBar.newTab();
        tabAll.setText("all");
        tabfavs.setText("favs");
        tabhist.setText("hist");
        tabAll.setTabListener(new MyTabListener());
        tabfavs.setTabListener(new MyTabListener());
        tabhist.setTabListener(new MyTabListener());
        actionBar.addTab(tabAll);
        actionBar.addTab(tabfavs);
        actionBar.addTab(tabhist);


        try{

        }
        catch(Exception e)
        {
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.actionbar_itemlist_favourite, menu);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
                case R.id.history:
                    break;
                case R.id.favourite:
                    Intent favAct = new Intent(this, Favourite.class);
                    startActivity(favAct);
                    break;
                case R.id.delete:
                    ///I WANT TO BE ABLE TO REFRESH FRAGMENTLIST FROM HERE
                }
                return true;
    }

  }

class MyTabListener implements ActionBar.TabListener {

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if(tab.getPosition()==0)
        {
            FavouriteAllWords frag = new FavouriteAllWords();
            ft.replace(android.R.id.content, frag);

        }
        else if(tab.getPosition()==1)
        {
            FavouriteFavWords frag = new FavouriteFavWords();
            ft.replace(android.R.id.content, frag);

        }
        else if(tab.getPosition()==2)
        {
            FavouriteHistWords frag = new FavouriteHistWords();
            ft.replace(android.R.id.content, frag);
        }
    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub

    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // TODO Auto-generated method stub

    }

}

////////////////////MY LIST FRAGMENT CLASS

public class FavouriteAllWords extends ListFragment {

    ArrayAdapter<String> adapter;

    List<String> stringOfFavWords;

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

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved)
    {   
        adapter = new ArrayAdapter<String>(  
                inflater.getContext(), R.layout.row, stringOfFavWords);  
                setListAdapter(adapter);  

        return super.onCreateView(inflater, group, saved);  
    }

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

}
Marian Paździoch
  • 7,671
  • 9
  • 49
  • 88
user1319668
  • 329
  • 1
  • 3
  • 16

7 Answers7

34

You can easily achieve this using INTERFACE

MainActivity.java

public class MainActivity extends Activity {

    public FragmentRefreshListener getFragmentRefreshListener() {
        return fragmentRefreshListener;
    }

    public void setFragmentRefreshListener(FragmentRefreshListener fragmentRefreshListener) {
        this.fragmentRefreshListener = fragmentRefreshListener;
    }

    private FragmentRefreshListener fragmentRefreshListener;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        Button b = (Button)findViewById(R.id.btnRefreshFragment);

        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(getFragmentRefreshListener()!=null){
                    getFragmentRefreshListener().onRefresh();
                }
            }
        });


    }


    public interface FragmentRefreshListener{
        void onRefresh();
    }

}

MyFragment.java

public class MyFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = null; // some view

        /// Your Code


        ((MainActivity)getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {
            @Override
            public void onRefresh() {

                // Refresh Your Fragment
            }
        });


        return v;
    }
}
Biraj Zalavadia
  • 27,124
  • 9
  • 56
  • 73
  • 1
    This is completely the wrong way of doing things. A `Fragment` should *NEVER* 'know' about what type of `Activity` it is attached to. In particular, if a `Fragment` is to be self-contained and reusable how can there be any guarantee the `Activity` has defined any particular interface? Short answer - it can't. – Squonk Oct 28 '14 at 11:50
  • 6
    @ Squonk Do not get panic may friend. Read Question carefully. He had clearly write that I want to refresh fragment from the MainActivity.java. He did't tell that his fragment is general. So The answer I post is related to question not for generic purpose. If you have better approach please post rather arguing. – Biraj Zalavadia Oct 28 '14 at 11:59
  • 1
    @BirajZalavadia : The first point in the answer from "localhost" is correct. An `Activity` will always "know" everything about the `Fragments` it uses but `Fragments` should never "know" anything about any `Activity` they are attached to except for checking that the `Activity` implements the `Fragment's` own interface (where necessary). In short, a `Fragment` can define any number of public methods and the `Activity` can call them directly if needed. This approach is covered in this link... http://developer.android.com/training/basics/fragments/communicating.html#Deliver – Squonk Oct 28 '14 at 12:09
  • That's also one approach to achieve this. But you can't say that interface is the very bad approach. Even this approach it may possible that Fragmnet is not null but it is not attached to window. In that case application will crash. So what I mean is there can be several approaches with their pros and cons. So we can't say this is the perfect. – Biraj Zalavadia Oct 28 '14 at 12:51
  • @BirajZalavadia : You're still missing my point. In your code you use `((MainActivity)getActivity()).setFragmentRefreshListener(new MainActivity.FragmentRefreshListener() {...)` - you're explicitly using `MainActivity`. The point of a `Fragment` is it should be reusable - what happens if somebody wanted to use an instance of `MyFragment` attached to `AnotherActivity` or `AnyOtherActivity`? You'd have to edit the `Fragment` code each time you used it to cast the correct `Activity` class. All it needs is a public method in the `Fragment` and *EVERY* `Activity` can use it as it is. Think about it – Squonk Oct 28 '14 at 14:16
  • @Squonk I Understand your point. MainActivity I used is specific to the question. But if fragment is reusable than you can replace MainActivity with BaseActivity. And put interface code in BaseActivity. All activity in project will extends BaseActivity. This way you can reuse the fragment as well. – Biraj Zalavadia Oct 29 '14 at 04:16
  • @BirajZalavadia : It doesn't matter what you call your `Activity` (MainActivity, BaseActivity, etc) the point is that *EVERY* `Activity` which uses the `Fragment` would have to have the interface (either explicitly or inherited). `Fragments` shouldn't be restricted to relying on what type of `Activity` they're attached to - that breaks the whole design principle of a `Fragment` being reusable. What happens if you refactor the `Fragment` and move it to a library project? Every future project which used the `Fragment` would also need a "BaseActivity" with that interface. – Squonk Oct 29 '14 at 11:28
  • Is it not possible to save the fragment instance in an attribute and call a public method from it? – JCarlosR Aug 11 '16 at 20:20
  • @JCarlos Yes that is also possible. – Biraj Zalavadia Aug 12 '16 at 04:31
6
  • Just make your update/refresh method public and call it from your Activity.

OR

  • Use LocalBroadcastManager or EventBus to send event from your Activity, and by subscribing to this event in a Fragment - react to it and call refresh/update method.
localhost
  • 5,432
  • 1
  • 30
  • 50
  • 1
    The `Fragment` doesn't need to be an inner class of the `Activity` in order to use a public method. As long as the `Activity` has a reference to the `Fragment` instance, it can call any public method in the `Fragment`. – Squonk Oct 28 '14 at 11:04
5

Your activity can call methods in the fragment by acquiring a reference to the Fragment.

(1) Provide a tag when you add your fragment.

transaction.add(R.id.fragment_container, myFragment, "myfragmentTag");

(2) In your hosting activity you can find the fragment and have access to it's methods.

FragmentManager fm = getSupportFragmentManager();
myFragment f = (myFragment) fm.findFragmentByTag("myfragmentTag");
f.refreshAdapter()

(3) refreshAdapter() could now call adapter.notifyDataSetChanged().

This is one of the recommended ways to communicate up to a fragment. The interface implementation is mainly for communicating back to the activity.

Jeffrey
  • 1,480
  • 1
  • 17
  • 21
1

Biraj Zalavadia's answer is 100% right, you will call nay fragment methods from using interface.... this interface methods is running without error...

use this in MainActivity above oncreate private FragmentRefreshListener fragmentRefreshListener;

public FragmentRefreshListener getFragmentRefreshListener() {
    return fragmentRefreshListener;
}

public void setFragmentRefreshListener(
        FragmentRefreshListener fragmentRefreshListener) {
    this.fragmentRefreshListener = fragmentRefreshListener;
}

inside of Activity

private void refreshcall(String result2) {
    // TODO Auto-generated method stub
    if (getFragmentRefreshListener() != null) {
        getFragmentRefreshListener().onRefresh(result2);
    }

}

and put this in needed Fragment

private FragmentRefreshListener fragmentRefreshListener;

    public FragmentRefreshListener getFragmentRefreshListener() {
        return fragmentRefreshListener;
    }

    public void setFragmentRefreshListener(
            FragmentRefreshListener fragmentRefreshListener) {
        this.fragmentRefreshListener = fragmentRefreshListener;
    }
Nikolay Mihaylov
  • 3,788
  • 8
  • 25
  • 32
0

Communicating with Other Fragments

http://developer.android.com/training/basics/fragments/communicating.html

This can also be used to communicate between an Activity and a Fragment.

Francesco verheye
  • 1,514
  • 2
  • 13
  • 30
0

When you click on ActionBar any Button then call interface to refresh the ListFragment. Because in java interface is used for inter-communication.

Ramkailash
  • 1,782
  • 1
  • 19
  • 19
-1

In Kotlin Get the list of Support Fragment from the activity and check Instance and then call fragment function

val fragments = supportFragmentManager.fragments
            for (fragment in fragments) {
                if (fragment is HomeCategoriesFragment) {
                    fragment.updateAdapter() // Define function in Fragment 
                }
            }