обновлять viewpager динамически?

<p>я не могу обновить содержимое в viewpager.</p><p>вопрос: какова взаимосвязь и правильное использование методов instantiateitem () и getitem () в классе fragmentpageradapter?</p><p>я использовал только getitem () для создания экземпляров и возврата моих фрагментов:</p><pre><code>@override public fragment getitem(int position) { return new myfragment(context, paramters); } </code></pre><p>это работало хорошо (но, как сказано, я не могу изменить содержание).</p><p>итак, я нашел это: <a href="https://stackoverflow.com/questions/7263291/viewpager-pageradapter-not-updating-the-view">viewpager pageradapter не обновляет представление</a> </p><p>в частности, в нем говорится о методе instantiateitem ():</p><blockquote> <p>«мой подход заключается в использовании метода settag () для любого экземпляра представления в методе instantiateitem ()»</p> </blockquote><p>так что теперь я хочу реализовать instantiateitem () для этого. но я не знаю, что мне нужно вернуть (return is object) и какова связь с getitem (int position)?</p><p>в настоящее время я использую getitem для создания экземпляра фрагмента, это неправильно? но тогда я должен поместить фрагменты в переменную экземпляра, или вообще не реализовывать getitem () ...? я просто не понимаю этого.</p><p>я попытался прочитать <a href="http://developer.android.com/reference/android/support/v4/app/fragmentpageradapter.html">ссылку</a> :</p><blockquote> <ul> <li><p>публичный абстрактный фрагмент getitem (int position)</p> <p>вернуть фрагмент, связанный с указанной позицией.</p></li> <li><p>открытый объект instantiateitem (контейнер viewgroup, позиция int)</p> <p>создайте страницу для данной позиции. адаптер отвечает за добавление представления к указанному здесь контейнеру, хотя он должен только гарантировать, что это будет сделано к тому времени, когда он вернется из finishupdate (viewgroup) . параметры</p> <p>контейнер содержащий вид, в котором будет отображаться страница . position позиция страницы, которую нужно создать.</p> <p>возвращает</p> <p>возвращает объект, представляющий новую страницу. это не обязательно должен быть view, но может быть другой контейнер страницы.</p></li> </ul> </blockquote><p>... но я до сих пор не понимаю, как они связаны и что я должен делать.</p><p>вот мой код я использую пакет поддержки v4.</p><p>viewpagertest </p><pre><code>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); } } </code></pre><p>myfragmentadapter</p><pre><code>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; } } </code></pre><p>myfragment</p><pre><code>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; } } </code></pre><p>вот также кто-то с похожей проблемой, без ответов ...</p><p> <a href="http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html">http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html</a> </p>

<p>при использовании fragmentpageradapter или fragmentstatepageradapter лучше всего иметь дело только с <code>getitem()</code> и вообще не касаться <code>instantiateitem()</code>. интерфейс <code>instantiateitem()</code>-<code>destroyitem()</code>-<code>isviewfromobject()</code> в pageradapter - это интерфейс более низкого уровня, который fragmentpageradapter использует для реализации гораздо более простого интерфейса <code>getitem()</code>.</p><p>прежде чем углубляться в это, я должен уточнить, что </p><blockquote> <p><strong> если вы хотите отключить фактические фрагменты, которые отображаются, вы должны избегать fragmentpageradapter и использовать fragmentstatepageradapter. </strong></p> </blockquote><p>в более ранней версии этого ответа была допущена ошибка использования fragmentpageradapter в качестве примера - это не сработает, поскольку fragmentpageradapter никогда не удаляет фрагмент после его отображения в первый раз.</p><p>я не рекомендую обходные пути <code>settag()</code> и <code>findviewwithtag()</code>, представленные в сообщении, которое вы связали. как вы обнаружили, использование <code>settag()</code> и <code>findviewwithtag()</code> не работает с фрагментами, поэтому это не очень хорошее совпадение.</p><p>правильное решение - переопределить функцию <code>getitemposition()</code>. когда вызывается <code>notifydatasetchanged()</code>, viewpager вызывает <code>getitemposition()</code> для всех элементов в своем адаптере, чтобы узнать, нужно ли их переместить в другое положение или удалить. </p><p>по умолчанию, <code>getitemposition()</code> возвращает <code>position\_unchanged</code>, что означает: «этот объект в порядке, не разрушайте и не удаляйте его». возвращение <code>position\_none</code> устраняет проблему, говоря: «этот объект больше не является элементом, который я отображаю, удалите его». таким образом, он имеет эффект удаления и воссоздания каждого элемента в вашем адаптере. </p><p>это абсолютно законное решение! это исправление заставляет notifydatasetchanged вести себя как обычный адаптер без повторного использования представления. если вы реализуете это исправление и производительность удовлетворительная, вы отправляетесь в гонки. работа выполнена.</p><p>если вам нужна лучшая производительность, вы можете использовать более привлекательную реализацию <code>getitemposition()</code>. вот пример для пейджера, создающего фрагменты из списка строк:</p><pre><code>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; } } }); </code></pre><p>в этой реализации будут отображаться только фрагменты с новыми заголовками. любые фрагменты, отображающие заголовки, которые все еще находятся в списке, вместо этого будут перемещены на новую позицию в списке, а фрагменты с заголовками, которых больше нет в списке, будут уничтожены.</p><p>что, если фрагмент не был воссоздан, но все равно нуждается в обновлении? обновления живого фрагмента лучше всего обрабатываются самим фрагментом. в конце концов, это преимущество наличия фрагмента - это его собственный контроллер. фрагмент может добавить слушателя или наблюдателя к другому объекту в <code>oncreate()</code>, а затем удалить его в <code>ondestroy()</code>, тем самым управляя самими обновлениями. вам не нужно помещать весь код обновления в <code>getitem()</code>, как это делается в адаптере для listview или других типов adapterview.</p><p>и последнее: только то, что fragmentpageradapter не уничтожает фрагмент, не означает, что getitemposition совершенно бесполезно в fragmentpageradapter. вы все еще можете использовать этот обратный вызов для изменения порядка фрагментов в viewpager. однако он никогда не удалит их полностью из fragmentmanager.</p>

<p>вместо того, чтобы возвращать <code>position\_none</code> из <code>getitemposition()</code> и вызывать полный просмотр, сделайте это:</p><pre><code>//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); } </code></pre><p>ваши фрагменты должны реализовывать интерфейс <code>updateablefragment</code>:</p><pre><code>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 } } } </code></pre><p>и интерфейс:</p><pre><code>public interface updateablefragment { public void update(updatedata xyzdata); } </code></pre><p>ваш класс данных:</p><pre><code>public class updatedata { //whatever you want here } </code></pre>

<p>для тех, кто все еще сталкивается с той же проблемой, с которой я сталкивался раньше, когда у меня есть viewpager с 7 фрагментами. по умолчанию для этих фрагментов загружается английский контент из api-сервиса, но проблема здесь в том, что я хочу сменить язык из настройки параметров и после завершения настройки активности. я хочу, чтобы viewpager в основной операции обновлял фрагменты в соответствии с выбором языка. от пользователя и загрузить арабский контент, если пользователь выбрал арабский здесь, что я сделал, чтобы работать с первого раза </p><p><strong> 1- вы должны использовать fragmentstatepageradapter, как указано выше. </strong></p><p>2-на mainactivity я переопределил onresume и сделал следующее </p><pre><code> if (!(mpageradapter == null)) { mpageradapter.notifydatasetchanged(); } </code></pre><p>3-я переопределяет getitemposition () в mpageradapter и заставляет его возвращать position\_none.</p><pre><code> @override public int getitemposition(object object) { return position\_none; } </code></pre><p>работает как шарм</p>

<p>я столкнулся с этой проблемой и, наконец, решил ее сегодня, поэтому я записываю то, что узнал, и надеюсь, что она будет полезна для тех, кто не знаком с android <code>viewpager</code>, и обновляю, как и я. я использую <code>fragmentstatepageradapter</code> на уровне api 17 и в настоящее время есть только 2 фрагмента. я думаю, что должно быть что-то не так, пожалуйста, поправьте меня, спасибо ...<img src="https://i.stack.imgur.com/cox7r.png" alt="enter image description here"></p><ol> <li><p>сериализованные данные должны быть загружены в память. это можно сделать с помощью <code>cursorloader</code>/<code>asynctask</code>/<code>thread</code>. будет ли он загружен автоматически, зависит от вашего кода. если вы используете <code>cursorloader</code>, он загружается автоматически, поскольку есть зарегистрированный наблюдатель данных.</p></li> <li><p>после вызова <code>viewpager.setadapter(pageradapter)</code> адаптер <code>getcount()</code> постоянно вызывается для создания фрагментов. таким образом, если данные загружаются, <code>getcount()</code> может вернуть 0, поэтому вам не нужно создавать фиктивные фрагменты, если данные не отображаются.</p></li> <li><p>после загрузки данных адаптер не будет автоматически собирать фрагменты, поскольку <code>getcount()</code> по-прежнему равен 0, поэтому мы можем установить фактически загруженный номер данных, возвращаемый <code>getcount()</code>, а затем вызвать <code>notifydatasetchanged()</code> адаптера. <code>viewpager</code> начинают создавать фрагменты (только первые 2 фрагмента) по данным в памяти. это делается до того, как возвращается функция <code>notifydatasetchanged()</code>. тогда <code>viewpager</code> содержит нужные вам фрагменты.</p></li> <li><p>если данные в базе данных и памяти оба обновлены (запись через), или только данные в памяти обновлены (обратная запись), или обновлены только данные в базе данных. в последних двух случаях, если данные не загружаются автоматически из базы данных в память (как упомянуто выше) . адаптер <code>viewpager</code> и пейджер просто обрабатывают данные в памяти.</p></li> <li><p>поэтому, когда данные в памяти обновляются, нам просто нужно вызвать функцию <code>notifydatasetchanged()</code> адаптера. поскольку фрагмент уже создан, функция <code>onitemposition()</code> адаптера будет вызвана до возврата <code>notifydatasetchanged(）</code>. ничего не нужно делать в <code>getitemposition()</code>. затем данные обновляются.</p></li> </ol>

<p>попробуйте <code>destroydrawingcache()</code> на viewpager после <code>notifydatasetchanged()</code> в вашем коде.</p>

<p>после нескольких часов разочарования, когда вы пытались решить все вышеперечисленные решения, чтобы преодолеть эту проблему, а также пытались найти множество решений по другим подобным вопросам, таким как <a href="https://stackoverflow.com/questions/10849552/android-viewpager-cant-update-dynamically">это</a> , <a href="https://stackoverflow.com/questions/11736953/viewpager-does-not-redraw-content-remains-turns-blank">это</a> и <a href="https://stackoverflow.com/questions/10611018/how-to-update-viewpager-content">это</a> которые все не смогли со мной решить эту проблему и заставить <code>viewpager</code> уничтожить старую <code>fragment</code> и заполнить <code>pager</code> новыми <code>fragment</code>s. я решил проблему следующим образом:</p><p><strong>1)</strong> сделайте класс <code>viewpager</code> расширяющим <code>fragmentpageradapter</code> следующим образом:</p><pre><code> public class mypageradapter extends fragmentpageradapter { </code></pre><p><strong>2)</strong> создайте элемент для <code>viewpager</code>, в котором хранятся <code>title</code> и <code>fragment</code>, следующим образом:</p><pre><code>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; } } </code></pre><p><strong>3)</strong> заставить конструктор <code>viewpager</code> взять мой экземпляр <code>fragmentmanager</code>, чтобы сохранить его в моем <code>class</code> следующим образом:</p><pre><code>private fragmentmanager mfragmentmanager; private arraylist<pageritem> mpageritems; public mypageradapter(fragmentmanager fragmentmanager, arraylist<pageritem> pageritems) { super(fragmentmanager); mfragmentmanager = fragmentmanager; mpageritems = pageritems; } </code></pre><p><strong>4)</strong> создайте метод для переустановки данных <code>adapter</code> с новыми данными, удалив все предыдущие <code>fragment</code> из самого <code>fragmentmanager</code> напрямую, чтобы сделать <code>adapter</code> для установки нового <code>fragment</code> из нового списка снова, как показано ниже:</p><pre><code>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; } </code></pre><p><strong>5)</strong> из контейнера <code>activity</code> или <code>fragment</code> не переинициализируйте адаптер с новыми данными. установите новые данные с помощью метода <code>setpageritems</code> с новыми данными следующим образом:</p><pre><code>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(); </code></pre><p>я надеюсь, что это помогает.</p>

<p>по какой-то причине ни один из ответов не сработал для меня, поэтому мне пришлось переопределить метод restorestate, не вызывая super в моем fragstatepageradapter. код:</p><pre><code>private class myadapter extends fragmentstatepageradapter { // [rest of implementation] @override public void restorestate(parcelable state, classloader loader) {} } </code></pre>

<p>я немного изменил решение, предоставленное биллом филлипсом, чтобы удовлетворить мои потребности</p><pre><code>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; } } </code></pre><p>так что <code>getitemposition()</code> возвращает <code>position\_none</code> только для тех фрагментов, которые в данный момент находятся в <code>fragmentmanager</code>, когда вызывается <code>getitemposition</code> . (обратите внимание, что эта <code>fragmentstatepager</code> и связанная с ним <code>viewpager</code> содержатся во фрагменте, а не в activity)</p>

<p>у меня была похожая проблема, но я не хочу доверять существующим решениям (жестко закодированные имена тегов и т.д.), и я не мог заставить решение m-wajeeh работать на меня. вот мое решение:</p><p>я храню ссылки на фрагменты, созданные в getitem в массиве. это работает нормально, пока действие не уничтожено из-за configurationchange или нехватки памяти или чего-либо еще (-> при возврате к действию фрагменты возвращаются в свое последнее состояние без повторного вызова getitem и, следовательно, без обновления массива ).</p><p>чтобы избежать этой проблемы, я реализовал instantiateitem (viewgroup, int) и обновил там мой массив, например так:</p><pre><code> @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; } </code></pre><p>итак, с одной стороны, я рад, что нашел решение, которое работает для меня, и хотел бы поделиться им с вами, но я также хотел спросить, пробовал ли кто-то что-то подобное и есть ли причина, почему я не должен сделать это так? пока это работает очень хорошо для меня ...</p>

<p>я жил той же проблемой, и я искал слишком много раз. любой ответ, данный в stackoverflow или через google, не был решением для моей проблемы. моя проблема была легкой. у меня есть список, я показываю этот список с viewpager. когда я добавляю новый элемент в заголовок списка и обновляю ничего не изменилось. мое окончательное решение было очень простым для любого. когда новый элемент добавлен в список и хотите обновить список. сначала установите для адаптера viewpager значение null, затем заново создайте адаптер и установите для него значение viewpager.</p><pre><code>myvpager.setadapter(null); myfragmentadapter = new myfragmentadapter(getsupportfragmentmanager(),newlist); myvpager.setadapter(myfragmentadapter); </code></pre><p>убедитесь, что ваш адаптер должен расширять fragmentstatepageradapter</p>

<p>если вы хотите использовать fragmentstatepageradapter, ознакомьтесь с <a href="https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=id%20type%20status%20owner%20summary%20stars&groupby=&sort=&id=37990">https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=id%20type%20status%20owner% 20summary% 20stars & groupby = & sort = & id = 37990</a> . есть проблемы с fragmentstatepageradapter, которые могут вызывать или не беспокоить ваш вариант использования. </p><p>кроме того, ссылка имеет несколько решений .. мало кто может удовлетворить ваши требования.</p>

<p>я использую <a href="https://github.com/greenrobot/eventbus">eventbus</a> library для обновления <code>fragment</code> содержимого в <code>viewpager</code>. логика проста, как и <a href="https://github.com/greenrobot/eventbus/blob/master/howto.md">документ eventbus, как это сделать</a> . нет необходимости контролировать экземпляр <code>fragmentpageradapter</code>. код здесь:</p><p>1: определить события</p><p>определите, какое сообщение необходимо обновить. </p><pre><code>public class updatecountevent { public final int count; public updatecountevent(int count) { this.count = count; } } </code></pre><p>2. подготовить подписчиков</p><p>напишите ниже код во фрагменте, который необходимо обновить.</p><pre><code>@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(); } </code></pre><p>3.пост события</p><p>напишите ниже код в другой <code>activity</code> или другой <code>fragment</code>, который должен обновить параметр </p><pre><code>//input update message eventbus.getdefault().post(new updatecountevent(count)); </code></pre>

<p>я знаю, что опаздываю на вечеринку. я исправил проблему, вызвав <code>tablayout#setupwithviewpager(myviewpager);</code> сразу после <code>fragmentpageradapter#notifydatasetchanged();</code></p>

<p>это может кому-то помочь - в моем случае при вставке новой страницы пейджер просмотра дважды запрашивал позицию существующего фрагмента, но не спрашивал позицию нового элемента, вызывая некорректное поведение и не отображая данные.</p><ol> <li><p>скопируйте источник для fragmentstatepageradapter (кажется, не обновлялся в течение веков).</p></li> <li><p>переопределить notifydatasetchanged ()</p> <pre><code>@override public void notifydatasetchanged() { mfragments.clear(); super.notifydatasetchanged(); } </code></pre></li> <li><p>добавьте проверку работоспособности для destroyitem (), чтобы предотвратить сбои:</p> <pre><code>if (position < mfragments.size()) { mfragments.set(position, null); } </code></pre></li> </ol>

<p>вот моя реализация, которая включает информацию от @bill phillips one получает кэширование фрагментов большую часть времени, за исключением случаев, когда данные изменились. просто, и, кажется, работает нормально.</p><p>myfragmentstatepageradapter.java</p><pre><code>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); } } </code></pre><p>myactivity.java</p><pre><code>madapter.setisupdating(true); madapter.notifydatasetchanged(); madapter.setisupdating(false); </code></pre>

<p>я просмотрел все ответы выше и ряд других постов, но так и не смог найти что-то подходящее для меня (с разными типами фрагментов и динамическим добавлением и удалением вкладок). fwiw следующий подход - это то, что сработало для меня (в случае, если у кого-то еще есть такие же проблемы). </p><pre><code>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); } } </code></pre>

<p>используйте fragmentstatepageradapter вместо fragmentpageradapter , если вы хотите воссоздать или перезагрузить фрагмент на основе индекса например, если вы хотите перезагрузить фрагмент, отличный от firstfragment, вы можете проверить экземпляр и вернуть позицию следующим образом</p><pre><code> public int getitemposition(object item) { if(item instanceof firstfragment){ return 0; } return position\_none; } </code></pre>

<p>это решение не будет работать для всех, но в моем случае каждый фрагмент в моем viewpager - это отдельный класс, и одновременно может существовать только один из них. </p><p>с этим ограничением это решение является безопасным и должно быть безопасным для использования в производстве.</p><pre><code>private void updatefragment(item item) { list<fragment> fragments = getsupportfragmentmanager().getfragments(); for (fragment fragment : fragments) { if (fragment instanceof myitemfragment && fragment.isvisible()) { ((myitemfragment) fragment).update(item); } } } </code></pre><p>если у вас есть несколько версий одного и того же фрагмента, вы можете использовать эту же стратегию для вызова методов этих фрагментов, чтобы определить, является ли это фрагмент, который вы хотите обновить.</p>

<p>я пробовал так много разных подходов, и ни один из них не помог мне. ниже я расскажу, как я могу решить эту проблему с помощью набора решений, предоставленных всеми вами. спасибо всем.</p><pre><code>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); } } </code></pre><p>я только хочу обновить страницу 0 после onresume ().</p><pre><code> adapter=new pageradapter(getsupportfragmentmanager()); pager.setadapter(adapter); @override protected void onresume() { super.onresume(); if (adapter!=null) { adapter.flag\_refresh=true; adapter.notifydatasetchanged(); } } </code></pre><p>в моем fragmentsmain есть общедоступное целое число «страница», которое может сказать мне, является ли это страница, которую я хочу обновить.</p><pre><code>public class fragmentsmain extends fragment { private cursor cursor; private static context context; public int page=-1; </code></pre>