Refresh or force redraw the fragment
Asked Answered
P

8

56

I have a fragment that inflates an xml layout. My requirement is to update the text size on all my views inside my fragment when my Activity is resumed. I tried

    fragment.getView().invalidate();

which didn't seem to do the work. I also tried

    fragment.getView().requestLayout();

which didn't work either.

On another activity, I have a ListFragment which needs to do the same thing. I tried

    listfragment.getListView().invalidate();

which did the trick, refreshing my list view and redrawing all the items inside it.

I don't understand why one works but not the other.

I have also seen people recommending initiating a fragment transaction and replacing the current fragment with a new one, and it has kept me wondering

  1. Why should I create a whole new fragment and replace my current fragment when all I need is to refresh the text on the views that my fragment contains.

  2. Fragment transaction method will prevent me from defining my fragment in the layout xml of my activity and I will have to programatically insert the fragment at the right position.

Is there any simple approach to this?

Predator answered 7/3, 2013 at 3:53 Comment(9)
Updating a known property of a TextView like text size is not the sort of the thing you should need to call invalidate() for; the framework does this for you when the property changes. Perhaps show the code where you are updating the text properties; the problem is more likely there. The only time you should ever need to invalidate() a view manually is if you create a custom property Android doesn't know about.Georgeannageorgeanne
The fragment is responsible for loading the data in all the views it contains and while populating that data, it is checking the text size set by the user from Preferences and at that time it is setting that size. I believe if the size changes significantly, the views have to adjust themselves to wrap the content and hence need to redraw. And even if it is a custom property instead of text size, how do we force the fragment view to redraw itself?Predator
Again, when you set the text value, the view/layout system knows that it needs to re-measure and re-draw. Just take a look at setRawTextSize() in the TextView sources (line 2406)...what gets called after the property is updated? android.googlesource.com/platform/frameworks/base/+/refs/heads/… Also, as an aside, invalidate() does not force views to adjust themselves, requestLayout() does that.Georgeannageorgeanne
Strangely requestLayout didn't work for me in this case. I now understand what you ar saying about changing text size, but I am wondering if it is something else for which I need to redraw the fragment views, how will I achieve that?Predator
I'm experiencing the same issue. Based on the number of un-answered questions here, I'm wondering if I really understand how View elements are supposed to work.Frasco
did you tried getAllViews() and than invalidate them all in a loop?Sexed
Are you sure that your fragment's onResume() is called?Dearr
Try to use Swipe-to-Refresh To Your App. See this https://mcmap.net/q/168364/-fragment-refresh/…Granniah
Help me please: #61811728Bagwig
I
29

I do not think there is a method for that. The fragment rebuilds it's UI on onCreateView()... but that happens when the fragment is created or recreated.

You'll have to implement your own updateUI method or where you will specify what elements and how they should update. It's rather a good practice, since you need to do that when the fragment is created anyway.

However if this is not enough you could do something like replacing fragment with the same one forcing it to call onCreateView()

FragmentTransaction tr = getFragmentManager().beginTransaction();
tr.replace(R.id.your_fragment_container, yourFragmentInstance);
tr.commit()

NOTE

To refresh ListView you need to call notifyDataSetChanged() on the ListView's adapter.

Icicle answered 18/4, 2014 at 8:45 Comment(1)
Any help here: #40096326Somali
D
25

In my case, detach and attach worked:

 getSupportFragmentManager()
   .beginTransaction()
   .detach(contentFragment)
   .attach(contentFragment)
   .commit();
Doherty answered 1/2, 2015 at 3:42 Comment(3)
The original text has been update w/ my comment, making my comment no longer relevant, so I am deleting it.Walford
this solution damages my back stackChiasmus
yeah, I just need to refresh an adapter, detaching and reattaching seems an overkill (even tho it looks like the only solution)Frimaire
S
10

detach().detach() not working after support library update 25.1.0 (may be earlier). This solution works fine after update:

getSupportFragmentManager()
    .beginTransaction()
    .detach(oldFragment)
    .commitNowAllowingStateLoss();

getSupportFragmentManager()
    .beginTransaction()
    .attach(oldFragment)
    .commitAllowingStateLoss();
Schutzstaffel answered 22/12, 2016 at 9:35 Comment(1)
Everything was working prior to updating to a newer support library version, but this solution saved me! Quick note--I had to use runOnUiThread() to use commitNowAllowingStateLoss, but it wouldn't work without it.Ahwaz
O
10

Use the following code for refreshing fragment again:

FragmentTransaction ftr = getFragmentManager().beginTransaction();                          
ftr.detach(EnterYourFragmentName.this).attach(EnterYourFragmentName.this).commit();
Organicism answered 1/6, 2017 at 6:6 Comment(0)
T
1

To solve the problem, I use this:

Fragment frg = null;
frg = getFragmentManager().findFragmentByTag("Feedback");
final android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
Typewritten answered 23/8, 2016 at 15:9 Comment(1)
Where is the tag? How do I find it? I am adding something to the Sqlite Db. I would like to refresh the Fragment from the Acvitiy once that is done.Somali
D
0

This worked for me from within Fragment:

Fragment frg = null;
Class fragmentClass;
fragmentClass = MainFragment.class;

try {
    frg = (android.support.v4.app.Fragment)     
    fragmentClass.newInstance();
} catch(Exception ex) {
    ex.printStackTrace();
}

getFragmentManager()
    .beginTransaction()
    .replace(R.id.flContent, frg)
    .commit();
Desantis answered 4/2, 2017 at 13:18 Comment(0)
S
-1

I am using remove and replace both for refreshing content of Fragment like

final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.remove(resetFragment).commit();
fragmentTransaction.replace(R.id.frame_container,resetFragment).commit();
Savil answered 27/1, 2017 at 7:36 Comment(1)
Your suggestion causes the app to crash.Adscititious
R
-1

let us see the below source code. Here fragment name is DirectoryOfEbooks. After completion of the background task, i am the replacing the frame with current fragment. so the fragment gets refreshed and reloads its data

    import android.app.ProgressDialog;
    import android.content.DialogInterface;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v4.view.MenuItemCompat;
    import android.support.v7.app.AlertDialog;
    import android.support.v7.widget.DefaultItemAnimator;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.SearchView;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import android.widget.Toast;

    import com.github.mikephil.charting.data.LineRadarDataSet;

    import java.util.ArrayList;
    import java.util.List;


    /**
     * A simple {@link Fragment} subclass.
     */
    public class DirectoryOfEbooks extends Fragment {

        RecyclerView recyclerView;
        branchesAdapter adapter;
        LinearLayoutManager linearLayoutManager;
        Cursor c;
        FragmentTransaction fragmentTransaction;
        SQLiteDatabase db;
        List<branch_sync> directoryarraylist;

        public DirectoryOfEbooks() {
            // Required empty public constructor
        }
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {


            View view = inflater.inflate(R.layout.fragment_directory_of_ebooks, container, false);
            directoryarraylist = new ArrayList<>();
            db = getActivity().openOrCreateDatabase("notify", android.content.Context.MODE_PRIVATE, null);
            c = db.rawQuery("select * FROM branch; ", null);

            if (c.getCount() != 0) {
                c.moveToFirst();
                while (true) {
                    //String ISBN = c.getString(c.getColumnIndex("ISBN"));
                    String branch = c.getString(c.getColumnIndex("branch"));

                    branch_sync branchSync = new branch_sync(branch);
                    directoryarraylist.add(branchSync);
                    if (c.isLast())
                        break;
                    else
                        c.moveToNext();
                }

                recyclerView = (RecyclerView) view.findViewById(R.id.directoryOfEbooks);
                adapter = new branchesAdapter(directoryarraylist, this.getContext());
                adapter.setHasStableIds(true);
                recyclerView.setItemAnimator(new DefaultItemAnimator());
                System.out.println("ebooks");
                recyclerView.setHasFixedSize(true);
                linearLayoutManager = new LinearLayoutManager(this.getContext());
                recyclerView.setLayoutManager(linearLayoutManager);
                recyclerView.setAdapter(adapter);
                System.out.println(adapter.getItemCount()+"adpater count");

            }
            // Inflate the layout for this fragment
            return view;
        }
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //setContentView(R.layout.fragment_books);
            setHasOptionsMenu(true);
        }
        public void onPrepareOptionsMenu(Menu menu) {
            MenuInflater inflater = getActivity().getMenuInflater();
            inflater.inflate(R.menu.refresh, menu);
            MenuItem menuItem = menu.findItem(R.id.refresh1);
            menuItem.setVisible(true);
        }
        public boolean onOptionsItemSelected(MenuItem item) {
            if (item.getItemId() == R.id.refresh1) {
                new AlertDialog.Builder(getContext()).setMessage("Refresh takes more than a Minute").setPositiveButton("Refresh Now", new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int which) {

                        new refreshebooks().execute();
                    }
                }).setNegativeButton("Refresh Later", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {

                    }
                }).setCancelable(false).show();

            }
            return super.onOptionsItemSelected(item);
        }

    public class refreshebooks extends AsyncTask<String,String,String>{
        ProgressDialog progressDialog;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
          progressDialog=new ProgressDialog(getContext());
            progressDialog.setMessage("\tRefreshing Ebooks .....");
            progressDialog.setCancelable(false);
            progressDialog.show();
        }

        @Override
        protected String doInBackground(String... params) {
            Ebooksync syncEbooks=new Ebooksync();
            String status=syncEbooks.syncdata(getContext());
            return status;

        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if(s.equals("error")){
                progressDialog.dismiss();
                Toast.makeText(getContext(),"Refresh Failed",Toast.LENGTH_SHORT).show();
            }
            else{
                fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.mainframe, new DirectoryOfEbooks());
                fragmentTransaction.commit();
                progressDialog.dismiss();
                adapter.notifyDataSetChanged();
                Toast.makeText(getContext(),"Refresh Successfull",Toast.LENGTH_SHORT).show();
            }

        }
    }

    }
Realpolitik answered 26/3, 2017 at 6:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.