Вопрос по android-fragments, android, android-viewpager – Обновить ViewPager динамически?

285

Я не могу обновить содержимое в ViewPager.

Вопрос: Какова взаимосвязь и правильное использование методов instantiateItem () и getItem () в классе FragmentPagerAdapter?

Я использовал только getItem () для создания экземпляров и возврата моих фрагментов:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

Это работало хорошо (но, как я уже сказал, я не могу изменить содержание).

Итак, я нашел это:ViewPager PagerAdapter не обновляет представление

В частности, в котором говорится о методе instantiateItem ():

"My approach is to use the setTag() method for any instantiated view in the instantiateItem() method"

Так что теперь я хочу реализовать instantiateItem () для этого. Но я не знаю, что мне нужно вернуть (return is Object) и какова связь с getItem (int position)?

В настоящее время я использую getItem для создания экземпляра фрагмента, это неправильно? Но тогда нужно ли помещать фрагменты в переменную экземпляра или вообще не реализовывать getItem () ...? Я просто не понимаю этого.

Я пытался читатьссылка:

public abstract Fragment getItem (int position)

Return the Fragment associated with a specified position.

public Object instantiateItem (ViewGroup container, int position)

Create the page for the given position. The adapter is responsible for adding the view to the container given here, although it only must ensure this is done by the time it returns from finishUpdate(ViewGroup). Parameters

container The containing View in which the page will be shown. position The page position to be instantiated.

Returns

Returns an Object representing the new page. This does not need to be a View, but can be some other container of the page.

... но я до сих пор не понимаю, как они связаны и что я должен делать.

Вот мой код. Я использую пакет поддержки v4.

ViewPagerTest

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

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

    public void setData(String[] data) {
        this.data = data;
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

MyFragment

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

Вот еще кто-то с похожей проблемой, без ответов ...

http://www.mail-archive.com/[email protected]/msg200477.html

Хорошее простое решение: stackoverflow.com/a/35450575/2162226 Gene Bo
Вы можете проверить этоexample in GitHub, Я надеюсь, что этот пример поможет вам. Cabezas
Чтобы получить лучшее представление о задействованных компонентах, это может помочь прочитать мой учебник о ViewPager с вкладками с отдельной историей обратной навигации. Он поставляется с рабочим примером на GitHub и дополнительными ресурсами:medium.com/@nilan/… marktani
есть проблемаstackoverflow.com/questions/40149039/… albert

Ваш Ответ

19   ответов
571

При использовании FragmentPagerAdapter или FragmentStatePagerAdapter лучше всего иметь дело только сgetItem() и не трогайinstantiateItem() совсем.instantiateItem()-destroyItem()-isViewFromObject() Интерфейс в PagerAdapter - это интерфейс более низкого уровня, который FragmentPagerAdapter использует для реализации гораздо более простогоgetItem() интерфейс.

Прежде чем углубляться в это, я должен уточнить, что

if you want to switch out the actual fragments that are being displayed, you need to avoid FragmentPagerAdapter and use FragmentStatePagerAdapter.

В более ранней версии этого ответа была допущена ошибка использования FragmentPagerAdapter для его примера - это не сработает, поскольку FragmentPagerAdapter никогда не уничтожает фрагмент после того, как он был отображен в первый раз.

Я не рекомендуюsetTag() а такжеfindViewWithTag() Обходной путь предоставлен в сообщении, которое вы связали. Как вы обнаружили, используяsetTag() а такжеfindViewWithTag() не работает с фрагментами, так что это не очень хорошее соответствие.

Правильное решение - переопределитьgetItemPosition(), когдаnotifyDataSetChanged() называется, ViewPager вызываетgetItemPosition() на все элементы в своем адаптере, чтобы увидеть, должны ли они быть перемещены в другую позицию или удалены.

По умолчанию,getItemPosition() возвращаетсяPOSITION_UNCHANGED, что означает: «Этот объект хорош там, где он есть, не разрушайте и не удаляйте его». возвратеPOSITION_NONE устраняет проблему, вместо этого говоря: «Этот объект больше не является элементом, который я отображаю, удалите его». Таким образом, он имеет эффект удаления и воссоздания каждого элемента в вашем адаптере.

Это совершенно законное решение! Это исправление заставляет notifyDataSetChanged вести себя как обычный адаптер без повторного использования представления. Если вы реализуете это исправление и производительность удовлетворительная, вы отправляетесь в гонки. Работа выполнена.

Если вам нужна лучшая производительность, вы можете использовать любителяgetItemPosition() реализация. Вот пример того, как пейджер создает фрагменты из списка строк:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

В этой реализации будут отображаться только фрагменты с новыми заголовками. Любые фрагменты, отображающие заголовки, которые все еще находятся в списке, вместо этого будут перемещены на новую позицию в списке, а фрагменты с заголовками, которых больше нет в списке, будут уничтожены.

Что если фрагмент не был воссоздан, но все равно нуждается в обновлении? Обновления живого фрагмента лучше всего обрабатываются самим фрагментом. Это преимущество наличия фрагмента, в конце концов - это его собственный контроллер. Фрагмент может добавить слушателя или наблюдателя к другому объекту вonCreate(), а затем удалите его вonDestroy()Таким образом, управление обновлениями само. Вам не нужно помещать весь код обновления внутрьgetItem() как вы делаете в адаптере для ListView или других типов AdapterView.

И последнее: только то, что FragmentPagerAdapter не уничтожает фрагмент, не означает, что getItemPosition совершенно бесполезно в FragmentPagerAdapter. Вы все еще можете использовать этот обратный вызов для изменения порядка фрагментов в ViewPager. Однако он никогда не удалит их полностью из FragmentManager.

Вы правы, изменение класса адаптера на FragmentStatePagerAdapter решило все мои проблемы. Спасибо! Ixx
Я рассмотрю это в какой-то момент позже ... спасибо за ваш ответ. И тогда я принимаю ваш ответ, если он работает. Перед вашим последним комментарием я реализовал удаление и добавление нового ViewPager каждый раз, и это работает. Не очень хорошее решение, но у меня сейчас нет времени его менять. Ixx
Не работает, все еще ничего не обновляет ... опубликовал мой код. Ixx
Я думаю, что вы получите более качественную обратную связь, если ответите на этот вопрос отдельно, даркраведев.
Ладно, разобрался с проблемой - нужно использовать FragmentStatePagerAdapter, а не FragmentPagerAdapter. FragmentPagerAdapter никогда не удаляет фрагменты из FragmentManager, он только отсоединяет и присоединяет их. Проверьте документы для получения дополнительной информации - в общем, вы хотите использовать FragmentPagerAdapter только для фрагментов, которые являются постоянными. Я отредактировал мой пример с исправлением.
0

Используйте FragmentStatePagerAdapter вместо FragmentPagerAdapter если вы хотите воссоздать или перезагрузить фрагмент на основе индекса Например, если вы хотите перезагрузить фрагмент, отличный от FirstFragment, вы можете проверить экземпляр и вернуть позицию следующим образом

 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }
0

Я знаю, что опаздываю на вечеринку. Я исправил проблему, позвонивTabLayout#setupWithViewPager(myViewPager); сразу послеFragmentPagerAdapter#notifyDataSetChanged();

3

Я немного изменил решение, предоставленное Биллом Филлипсом, чтобы удовлетворить мои потребности

private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}

таким образомgetItemPosition() возвращаетсяPOSITION_NONE только для тех фрагментов, которые в настоящее время находятся вFragmentManager когдаgetItemPosition называется. (Обратите внимание, что этоFragmentStatePager иViewPager связанные с ним содержатся во Фрагменте, а не в Деятельности)

20

для тех, кто все еще сталкивается с той же проблемой, с которой я сталкивался раньше, когда у меня есть ViewPager с 7 фрагментами. по умолчанию для этих фрагментов загружается английский контент из API-сервиса, но проблема здесь в том, что я хочу изменить язык из настроек деятельности и после окончания действие настройки Я хочу, чтобы ViewPager в основном действии обновлял фрагменты в соответствии с выбранным пользователем языком и загружал арабский контент, если пользователь выбрал арабский здесь, что я сделал, чтобы работать с первого раза

1- You must use FragmentStatePagerAdapter as mentioned above.

2-on mainActivity я переопределил onResume и сделал следующее

 if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}

3-я переопределяет getItemPosition () в mPagerAdapter и заставляет его возвращать POSITION_NONE.

 @Override
   public int getItemPosition(Object object) {
     return POSITION_NONE;
    }

работает как шарм

Я динамически добавлял фрагменты в левую и правую части текущего фрагмента в окне просмотра. Этот работал! Благодарю.
Работает кроме как в одной ситуации. Когда вы удаляете последний элемент в viewPager. Затем он не удаляется из списка.
0

Вот моя реализация, которая включает в себя информацию от @Bill Phillips Кэширование фрагментов происходит чаще всего, кроме случаев, когда данные изменились. Просто, и, кажется, работает нормально.

MyFragmentStatePagerAdapter.java

private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
        this.mIsUpdating = mIsUpdating;
    }


@Override
public int getItemPosition(@NonNull Object object) {

    if (mIsUpdating) {
        return POSITION_NONE;
    }
    else {
        return super.getItemPosition(object);
    }
}

MyActivity.java

mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
132

Вместо возвращенияPOSITION_NONE отgetItemPosition() и вызывая полноценный вид отдыха, сделайте это:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

Ваши фрагменты должны реализоватьUpdateableFragment интерфейс:

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

и интерфейс:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

Ваш класс данных:

public class UpdateData {
    //whatever you want here
}
среди всего, что я видел за последние 2,5 дня моей трудовой жизни ... это единственный, который работал на меня ... всевозможные аригато, спасибо, spaciba, sukran .. n.
Хорошо, я ответил в другом месте с полной реализацией, где я обновляюFragment динамически, посмотрите:stackoverflow.com/questions/19891828/…
Мать Драконов !, это работает как шарм, единственное решение сработало для меня ... спасибо очень много !!
Означает ли это, что вашей MainActivity также необходимо реализовать интерфейс ??? Пожалуйста, помогите мне здесь. В моей текущей реализации я использую свой класс MainActivity в качестве коммуникатора между фрагментами, поэтому я был озадачен этим решением.
@ M-WaJeEh может быть, какой-нибудь пример, пожалуйста! У меня есть список со списком городов и после выбора города открывается окно просмотра (3 страницы) с информацией об этом городе. все работает нормально но после выбора другого города в окне просмотра отображается только 3d page on refreshes the 1-st page only after swiping pages? thw 2Страница d всегда пуста. Спасибо
0

Это может кому-то помочь - в моем случае при вставке новой страницы пейджер просмотра дважды запрашивал позицию существующего фрагмента, но не спрашивал позицию нового элемента, вызывая некорректное поведение и не отображая данные.

  1. Copy the source for for FragmentStatePagerAdapter (seems to have not been updated in ages).

  2. Override notifyDataSetChanged()

    @Override
    public void notifyDataSetChanged() {
        mFragments.clear();
        super.notifyDataSetChanged();
    }
    
  3. Add a sanity check to destroyItem() to prevent crashes:

    if (position < mFragments.size()) {
        mFragments.set(position, null);
    }
    
1

Я жил той же проблемой, и я искал слишком много раз. Любой ответ, данный в stackoverflow или через Google, не был решением для моей проблемы. Моя проблема была легкой. У меня есть список, я показываю этот список с ViewPager. Когда я добавляю новый элемент в заголовок списка и обновляю ничего не изменилось. Мое окончательное решение было очень простым для любого. Когда новый элемент добавлен в список и хотите обновить список. Сначала установите для адаптера viewpager значение null, затем заново создайте адаптер и установите для него значение viewpager.

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

Убедитесь, что ваш адаптер должен расширять FragmentStatePagerAdapter

0

Я просмотрел все ответы выше и ряд других постов, но так и не смог найти что-то, что сработало для меня (с разными типами фрагментов и динамическим добавлением и удалением вкладок). FWIW следующий подход - это то, что сработало для меня (в случае, если у кого-то еще есть такие же проблемы).

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


    public MyFragmentStatePageAdapter(FragmentManager fm) {
        super(fm);
    }


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


    @Override
    public int getCount() {
        return titles.size();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}
14

Я столкнулся с этой проблемой и, наконец, решил ее сегодня, поэтому я записываю то, что узнал, и надеюсь, что она будет полезна для тех, кто не знаком с Android.ViewPager и обновлять как я. Я используюFragmentStatePagerAdapter в уровне API 17 и в настоящее время есть только 2 фрагмента. Я думаю, что должно быть что-то не так, пожалуйста, поправьте меня, спасибо. enter image description here

  1. Serialized data has to be loaded into memory. This can be done using a CursorLoader/AsyncTask/Thread. Whether it's automatically loaded depends on your code. If you are using a CursorLoader, it's auto-loaded since there is a registered data observer.

  2. After you call viewpager.setAdapter(pageradapter), the adapter's getCount() is constantly called to build fragments. So if data is being loaded, getCount() can return 0, thus you don't need to create dummy fragments for no data shown.

  3. After the data is loaded, the adapter will not build fragments automatically since getCount() is still 0, so we can set the actually loaded data number to be returned by getCount(), then call the adapter's notifyDataSetChanged(). ViewPager begin to create fragments (just the first 2 fragments) by data in memory. It's done before notifyDataSetChanged() is returned. Then the ViewPager has the right fragments you need.

  4. If the data in the database and memory are both updated (write through), or just data in memory is updated (write back), or only data in the database is updated. In the last two cases if data is not automatically loaded from the database to memory (as mentioned above). The ViewPager and pager adapter just deal with data in memory.

  5. So when data in memory is updated, we just need to call the adapter's notifyDataSetChanged(). Since the fragment is already created, the adapter's onItemPosition() will be called before notifyDataSetChanged() returns. Nothing needs to be done in getItemPosition(). Then the data is updated.

где уведомить DataSetChanged (& # xFF09; ...
Кто-нибудь имеет представление о том, какой инструмент был использован для создания этой диаграммы?
я нашел, что ничего не нужно делать после обновления данных (в памяти), просто позвонитеnotifyDataSetChanged() затем просто обновляется автоматически, потому что фрагмент (с диаграммой), который я использую, обновится сам. если это не так, как статический фрагмент, мне придется вызватьonItemPositon() и возвращаетсяPOSITION_NONE  Извини за это
У вас есть пример кода этого?
0

Это решение не будет работать для всех, но в моем случае каждый фрагмент в моем ViewPager - это отдельный класс, и одновременно существует только один из них.

С этим ограничением это решение является безопасным и должно быть безопасным для использования в производстве.

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

Если у вас есть несколько версий одного и того же фрагмента, вы можете использовать эту же стратегию для вызова методов этих фрагментов, чтобы определить, является ли это фрагмент, который вы хотите обновить.

2

У меня была похожая проблема, но я не хочу доверять существующим решениям (жестко закодированные имена тегов и т. Д.), И я не мог заставить решение M-WaJeEh работать на меня. Вот мое решение:

Я храню ссылки на фрагменты, созданные в getItem в массиве. Это работает нормально, если действие не уничтожено из-за configurationChange или нехватки памяти или чего-либо еще (-> при возвращении к действию фрагменты возвращаются в свое последнее состояние без повторного вызова «getItem» и, следовательно, без обновления). массив).

Чтобы избежать этой проблемы, я реализовал instantiateItem (ViewGroup, int) и обновил там мой массив, например так:

        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }

Итак, с одной стороны, я рад, что нашел решение, которое работает для меня, и хотел бы поделиться им с вами, но я также хотел спросить, пробовал ли кто-то что-то подобное и есть ли причина, по которой я не должен был это делать. сделать это так? Пока это работает очень хорошо для меня ...

Я сделал что-то, связанное сstackoverflow.com/a/23427215/954643хотя вы, вероятно, должны удалить элемент изmyFragments вpublic void destroyItem(ViewGroup container, int position, Object object) а также, чтобы вы не брали заведомо устаревшую ссылку.
0

Я пробовал так много разных подходов, и ни один из них не помог мне. Ниже я расскажу, как я могу решить эту проблему с помощью набора решений, предоставленных всеми вами. Спасибо всем.

class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

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

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}

Я только хочу обновить страницу 0 после onResume ().

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

В моем FragmentsMain есть общедоступное целое число "page", которое может сказать мне, является ли это страница, которую я хочу обновить.

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;
1

я используюEventBus библиотека для обновленияFragment содержание вViewPager, Логика проста, какдокумент EventBus, как это сделать, Нет необходимости контролироватьFragmentPagerAdapter пример. Код здесь:

1: Определить события

Определите, какое сообщение необходимо обновить.

public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}

2. Подготовить подписчиков

Напишите ниже код во фрагменте, который необходимо обновить.

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

3.Пост события

Напишите ниже код в другомActivity или другойFragment который должен обновить параметр

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
10

После нескольких часов разочарования, пытаясь решить все вышеперечисленные решения, чтобы решить эту проблему, а также пытаясь найти множество решений по другим подобным вопросамэтот, этот а такжеэтот которые все не удалось со мной, чтобы решить эту проблему и сделатьViewPager уничтожить староеFragment и заполнитеpager с новымFragments. Я решил проблему следующим образом:

1) СделатьViewPager класс расширяетсяFragmentPagerAdapter следующим образом:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) Создать предмет дляViewPager которые хранятtitle иfragment следующим образом:

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) Сделать конструкторViewPager возьми мойFragmentManager экземпляр, чтобы сохранить его в моемclass следующим образом:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4) Создайте метод для переустановкиadapter данные с новыми данными, удалив все предыдущиеfragment отfragmentManager сам, чтобы сделатьadapter установить новыйfragment снова из нового списка следующим образом:

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) Из контейнераActivity или жеFragment не переинициализируйте адаптер с новыми данными. Установите новые данные через методsetPagerItems с новыми данными следующим образом:

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();

Я надеюсь, что это помогает.

можешь помочь мне в моем вопросеstackoverflow.com/questions/40149039/…
не могли бы вы помочь мне с этим вопросомstackoverflow.com/questions/41547995/…
7

По какой-то причине ни один из ответов не сработал для меня, поэтому мне пришлось переопределить метод restoreState, не вызывая super в моем fragStatePagerAdapter. Код:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}
После попытки всего остального в этом SO ответе, это тот, который работал для меня. Я заканчиваю () действие, которое возвращается к действию, в котором находится рассматриваемый PagerAdapter. Я хочу, чтобы все мои фрагменты были воссозданы в этом случае, потому что действие, которое я только что закончил, могло изменить состояние, используемое для рисования фрагментов.
OMG .. это работает .. это работает .. слава: D В моем случае мне нужно удалить объект текущего элемента viewpager. но текущий фрагмент не обновляется после попытки всех вышеуказанных методов / шагов.
12

ПытатьсяdestroyDrawingCache() на ViewPager послеnotifyDataSetChanged() в вашем коде.

Тоже самое. Работает отлично, спасибо. Мне было особенно тяжело, потому что я не используюFragments на мой взгляд пейджер. Так что спасибо тебе!
1

Если вы хотите использовать FragmentStatePagerAdapter, пожалуйста, посмотрите наhttps://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby= & амп; = & рода амп; ID = 37990. There are issues with FragmentStatePagerAdapter that may or may not trouble your use case.

Кроме того, ссылка имеет несколько решений .. мало кто может удовлетворить ваши требования.

Здорово. Да. У Link тоже есть несколько решений.
С этого URL я нашел решение. Я использовал измененный FragmentStatePagerAdapter из этого спискаgist.github.com/ypresto/8c13cb88a0973d071a64 в моем коде, и он начал работать, как и должно быть.

Похожие вопросы