I've been going around in circles trying to do something that seems pretty basic. I have a DialogFragment
that accepts a users input, then, on submission, refreshes a ListView
in a Fragment
that is part of a ViewPager
.
I have everything working except the Fragment
with the ListView
does not refresh itself. It's a little confusing though, because it does refresh the data, but I have to swipe a couple views, then back again to see the updated data.
After doing some research, I'm supposed to use getItemPosition
and notifyDataSetChanged
on the ViewPager
and it should work. The problem is that calling notifyDataSetChanged
results in a Recursive entry to executePendingTransactions
exception being thrown:
Main Activity
public class Main extends SherlockFragmentActivity implements MyListFragment.OnRefreshAdapterListener, DialogConfirmation.OnRefreshKeywordsListener //Updated Code
{
private static List<Fragment> fragments;
@Override
public void onCreate(final Bundle icicle)
{
setContentView(R.layout.main);
}
@Override
public void onResume()
{
mViewPager = (ViewPager)findViewById(R.id.viewpager);
fragments = new ArrayList<Fragment>();
fragments.add(new MyListFragment()); //fragment with the ListView
fragments.add(MyDetailFragment.newInstance(0));
fragments.add(MyDetailFragment.newInstance(1));
fragments.add(MyDetailFragment.newInstance(2));
mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mMyFragmentPagerAdapter);
}
private static class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int index) {
return fragments.get(index);
}
@Override
public int getCount() {
return 4;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
@Override
public void onRefreshAdapterListener() {
this.mMyFragmentPagerAdapter.notifyDataSetChanged();
}
//Updated Code
@Override
public void onRefreshTextListener() {
MyListFragment tf = (MyListFragment)getSupportFragmentManager().findFragmentById(R.id.fragmentText);
if (tf == null)
tf = (MyListFragment)this.fragments.get(0);
tf.RefreshText();
}
}
ListFragment
public class MyListFragment extends SherlockListFragment
{
OnRefreshAdapterListener mRefreshAdapter;
@Override
public void onActivityCreated(Bundle savedState) {
adapter = new CustomAdapter();
/*code to add items to adapter */
this.setListAdapter(adapter);
adapter.notifyDataSetChanged();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
if (getArguments() != null && getArguments().getString("text").length() > 0)
{
SaveText(getArguments().getString("text"));
this.mRefreshAdapter.onRefreshAdapterListener(); //this line causes a "java.lang.IllegalStateException: Recursive entry to executePendingTransactions" exception
}
return inflater.inflate(R.layout.listing, container, false);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mRefreshAdapter = (OnRefreshAdapterListener)activity;
}
public interface OnRefreshAdapterListener {
public void onRefreshAdapterListener();
}
@Override
public void onDialogTextAdd(final String text) {
}
}
DialogFragment
public class DialogTextAdd extends DialogFragment implements OnEditorActionListener {
private EditText mText;
OnRefreshTextListener mTextKeywords; //Updated Code
public interface DialogTextAddListener {
void onDialogTextAdd(final String inputText);
}
public DialogTextAdd() {
// Empty constructor required for DialogFragment
}
//Updated Code
@Override
public void onAttach(Activity act) {
super.onAttach(act);
mTextKeywords = (OnRefreshTextListener)act;
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.dialog_edit, container);
mText = (EditText)view.findViewById(R.id.text_add);
getDialog().setTitle("Add Text");
// Show soft keyboard automatically
mText.requestFocus();
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
mText.setOnEditorActionListener(this);
return view;
}
@Override
public boolean onEditorAction(final TextView v, final int actionId, final KeyEvent event) {
if (EditorInfo.IME_ACTION_DONE == actionId) {
MyListFragment mf = new MyListFragment();
Bundle args = new Bundle();
args.putString("text", mText.getText().toString());
mf.setArguments(args);
//this seems to be intefering with the notifyDataSetChanged in the listing fragment
getActivity().getSupportFragmentManager().beginTransaction().add(mf, "my_fragment").commit();
mTextKeywords.onRefreshTextListener(); //Updated Code
this.dismiss();
return true;
}
return false;
}
}
I have everything working except the Fragment with the ListView does not refresh itself.
There is no point on creating and adding to the FragmentActivity
a new instance of MyListFragment
. From your code it appears that you store the fragments that you use in a list so you have references to them(also, just out of curiosity, did you setup the fragments in portrait, did a rotation of the phone and retried to use the DialogFragment
?). Having references to those fragment means you could always get them from the list and use them to call a refresh/update method.