millinet millinet - 3 months ago 27
Android Question

Refresh Viewpager from within the DrawerLayout

Context:
I have a drawerLayout that contains a list of cities that I get from Realm. The ViewPager is already displaying that list. You can delete a city directly from the DrawerLayout

Problem: When I delete a city from the DrawerLayout, I call mViewPager.getAdapter().notifyDataSetChanged, the viewPager is not reloaded. Since the drawerLayout is displayed over the ViewPager, there is no reload when you close it and the ViewPager / Realm returns a

java.lang.ArrayIndexOutOfBoundsException: rowIndex > available rows: 4 > 4
when I navigate back in it.

Do you have any clue on how I could solve that?

For information purpose, here is how it works:
**In the BaseActivity, that contains the DrawerLayout **

mCityListAdapter = new CityListAdapter(getBaseContext(), RealmHelper.getStoredCities(), new CityListAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position) {
mPager.setCurrentItem(position);
mDrawerLayout.closeDrawers();
}
}, new CityListAdapter.OnItemLongClickListener() {
@Override
public void onItemLongClick(final int position) {
final CharSequence[] items = {getString(R.string.action_delete_city)};
AlertDialog.Builder builder = new AlertDialog.Builder(BaseActivity.this);
builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
RealmHelper.removeCity(RealmHelper.getStoredCities().get(position));
mPager.getAdapter().notifyDataSetChanged();
}
});
builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});

builder.setTitle(getString(R.string.delete_city_label));
builder.show();
}
});


In the activity that contains the viewPager

@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

getLayoutInflater().inflate(R.layout.fragment_pager, mFrameLayout);

mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.addOnPageChangeListener(this);

mAdapter = new FragmentStatePageSupportAdapter(getSupportFragmentManager(), RealmHelper.getStoredCities().size(), this, RealmHelper.getStoredCities());
mPager.setAdapter(mAdapter);
mPager.setOffscreenPageLimit(0);

}


Edit

I did override getItemPosition and it's called. So not the issue.

The @Override
public int getItemPosition(Object object) {
Log.v("results", "called getitempostion");
return POSITION_NONE;
}

Answer

You should notify the data set only when a change actually occurs, like so

mRealmChangeListener = new RealmChangeListener() {
    @Override
    public void onChange(Object element) {
        mCityListAdapter.notifyDataSetChanged();
    }
}

RealmHelper.getStoredCities().addChangeListener(mRealmChangeListener);

And

mCityListAdapter = new CityListAdapter(getBaseContext(), RealmHelper.getStoredCities(), new CityListAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(int position) {
       ...
    }
}, new CityListAdapter.OnItemLongClickListener() {
    @Override
    public void onItemLongClick(final int position) {
        ...
        AlertDialog.Builder builder = new AlertDialog.Builder(BaseActivity.this);
        builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                RealmHelper.removeCity(RealmHelper.getStoredCities().get(position));
                ////mPager.getAdapter().notifyDataSetChanged(); // remove this
            }
        });
        ...
    }
});

EDIT: okay, I guess in that case you should go the longer route:

mRealmChangeListener = new RealmChangeListener() {
    @Override
    public void onChange(Object element) {
        mCityListAdapter.notifyDataSetChanged();
    }
}

RealmResults<City> listenerSet;
Realm realm;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    realm = Realm.getDefaultInstance();
    listenerSet = realm.where(City.class).findAll();
    listenerSet.addChangeListener(mRealmChangeListener);
}

Or something of this sort.