nullpointer17 nullpointer17 - 1 year ago 95
Android Question

Update fragment from async task

A little background:
My main activity when 'onResume' connect to my server asking for info. This works correctly.
When the activity receives the answer it loads the data on a array, after it finishes loading the array it calls an 'UpdateFragments' located on the main activity.
Here it is...

public void updateFragments() {
List<Fragment> allFragments = getSupportFragmentManager().getFragments();
if (allFragments == null || allFragments.isEmpty())
return;
for (Fragment fragment : allFragments)
if (fragment.isVisible())
((UpdatableFragment) fragment).updateView();
}


Every fragment implements the updateView() procedure... for now i use just one fragment, this is my adapter:

public class MainAdapter extends FragmentPagerAdapter {

MainAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
return FragmentDevices.newInstance();
}

@Override
public int getCount() {
return 1;
}
}


And now to the freaking part... with the following code (we are in the Fragment now) it just works, when running i have my blank fragment with the string:

private TextView tv;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.device_fragment, parent, false);
tv = (TextView) view.findViewById(R.id.room);
tv.setText("PRINT THIS");
return view;
}


If i put the same code on my updateView() procedure and call it INSIDE the onCreateView it also works:

@Override
public void updateView() {
tv.setText("PRINT THIS");
}


BUT... and here we have the big hairy BUT... if the updateView is called from the MainActivity when the async task ends as it should be... the text is never printed.
And the weirdness is just at the beginning... if I try to debug the code.. when i reach the tv.setText instruction the app just dies... without any error.

02-07 16:48:18.015 1649-3024/? I/ActivityManager: Force stopping XXX appid=10185 user=0: from pid 23193
02-07 16:48:18.015 1649-3024/? I/ActivityManager: Killing 22729:XXX/u0a185 (adj 0): stop XXX
02-07 16:48:18.027 1649-3440/? I/WindowState: WIN DEATH: Window{8db1796 u0 XXX/XXX.MainActivity}


Edit:
@nbokmans could be right? that is on MainActivity:

@Override
public void onStart() {
super.onStart();
mDataManager = new DataManager(this);
}


and the DataManager class is this:
constructor:

public DataManager(MainActivity context) {
super(context);
mHandle = context;
...
}


async task calls this:

public void onNewData(JSONObject data) {
...
mHandle.updateFragments();
}

Answer Source

You need to invoke mHandle.updateFragments() from the UI thread. Since you already pass the MainActivity instance to the constructor of DataManager, you can simply do this to run the code on the UI thread:

public void onNewData(JSONObject data) {
    mHandle.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mHandle.updateFragments();
        }
    }
}

Edit: you might also want to choose for actually wrapping the updateFragments code in a runOnUiThread block:

public void updateFragments() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            List<Fragment> allFragments = getSupportFragmentManager().getFragments();
            if (allFragments == null || allFragments.isEmpty())
                return;
            for (Fragment fragment : allFragments) {
                if (fragment.isVisible())
                    ((UpdatableFragment) fragment).updateView();
            }
        }
    });
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download