android- 从 NavigationBar 替换 ViewPager 中的片段
android- Replacing fragment in ViewPager from NavigationBar
我正在开发一个 Android 应用程序,可以查看曲棍球比赛的结果。
我正在使用带有自定义 FragmentPagerAdapter
的 ViewPager
来显示三个片段,并使用带有 ExpandableListView
的 NavigationDrawer
来显示锦标赛。
当我点击 ExpandableListView
childrens 时,我想用所选锦标赛的数据更新三个片段。
我在 NavigationDrawer
中设置了一个 OnchildClickListener
,其中我实例化了一个 FragmentManager
并调用了 replace()
方法。但它只是 returns 一个空白屏幕。
我在各个论坛都搜索过,尝试过不同的解决方案,但没有一个有效
当我使用 ft.add()
而不是 ft.replace()
并使用 SwipeRefreshLayout
刷新页面时,我得到了正确的结果,但我想在不手动刷新页面的情况下获得它。
我也尝试用 FragmentStatePagerAdapter
替换 FragmentPagerAdapter
,但没有任何改变。
NavigationDrawerFragment
package com.dcdeveloper.fihresults;
public class NavigationDrawerFragment extends Fragment {
/**
* Immagazzina lo stato della posizione dell'elemento selezionato.
*/
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
/**
* Per the design guidelines, you should show the drawer on launch until the user manually
* expands it. This shared preference tracks this.
*/
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
/**
* A pointer to the current callbacks instance (the Activity).
*/
private NavigationDrawerCallbacks mCallbacks;
/**
* Helper component that ties the action bar to the navigation drawer.
*/
private ActionBarDrawerToggle mDrawerToggle;
/**
* Memorizza l'istanza del DrawerLayout
*/
private DrawerLayout mDrawerLayout;
/**View di questa barra di navigazione*/
private View mFragmentContainerView;
/**Posizione dell'elemento selezionato all'interno della lista*/
private int mCurrentSelectedPosition = 0;
private boolean mFromSavedInstanceState;
/**Boolean che indica se l'utente è venuto a conoscenza dell'utilizzo della barra laterale.Utilizzato per accessibilità.*/
private boolean mUserLearnedDrawer;
private ActionBarDrawerToggle actionBarDrawerToggle;
/**Lista con elementi espandibili,contiene i dati relativi ai campionati*/
ExpandableListView expListView;
/**adapter per inserire i dati nella ExpandableListView*/
MyExpandableListAdapter expandableListAdapter;
/*ArrayList dei titoli dei campionati*/
List<String> listDataHeader;
/**Hashmap contenente i dati relativi ai campionati,collegati ai relativi titoli*/
HashMap<String, List<String>> listDataChild;
HashMap<Campionato,Integer>listaCampionati;
/**Stringa contenente l'url del WS a cui si effettueranno le richieste HTTP per ricevere i dati dei campionati*/
String wsURL;
/**ID del campionato,utilizzato per aggiornare le pagine una volta premuto l'elemento di un campionato nella lista*/
protected int key;
/**Memorizza il titolo dell'Activity,in modo da cambiare il titolo della MainActivity*/
CharSequence mDrawerTitle;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Read in the flag indicating whether or not the user has demonstrated awareness of the
// drawer. See PREF_USER_LEARNED_DRAWER for details.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
if (savedInstanceState != null) {
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
mFromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(mCurrentSelectedPosition);
//Stringa contenente l'url del Web Service
wsURL = "http://fihresults.altervista.org/WebServiceFihResults/service.php";
//Prepara le intestazioni standard dei campionati
prepareHeaderData();
}
/**
* Metodo costruttore della view.Utilizza il layout predefinito del frammento.
* I dati inseriti all'interno del ListLayout vengono ricevuti dal server ed organizzati
* all' interno della lista.
*
*/
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
expListView = (ExpandableListView) inflater.inflate(
R.layout.fragment_navigation_campionati, container, false);
expListView .setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
mDrawerTitle= getActionBar().getTitle();
}
});
/**
* Definisce una nuova richiesta HTTP. Essa preleva i nomi ed i dati dei vari campionati,
* riempiendo degli ArrayList che saranno poi usati per creare l'ExpandableListView
*/
if(hasConnection(getActivity())) {
HTTPRequest http=new HTTPRequest() {
@Override
protected void onPostExecute(String result) {
//ArrayList di tutti i children che saranno inseriti nell'ExpandableListView
ArrayList<String>A1M=new ArrayList();
ArrayList<String>A1F=new ArrayList();
ArrayList<String>A2M=new ArrayList();
ArrayList<String>A2F=new ArrayList();
ArrayList<String>B=new ArrayList();
ArrayList<String>U21M=new ArrayList();
ArrayList<String>U19F=new ArrayList();
ArrayList<String>U17M=new ArrayList();
ArrayList<String>U16F=new ArrayList();
ArrayList<String>U14M=new ArrayList();
ArrayList<String>U14F=new ArrayList();
ArrayList<String>U12X=new ArrayList();
super.onPostExecute(result);
try {
//Formatta il risultato in un JSONArray
JSONArray dati = new JSONArray(result);
Log.i("INFO",result);
String categoria; //Categoria del campionato
String genere; //Genere (Maschile,Femminile,Misto)
String girone; //Girone del campionato
String idcampionato;
for(int i=0;i<dati.length();i++)
{
JSONObject jsonobject = dati.getJSONObject(i);
categoria=jsonobject.getString("Categoria");
genere= jsonobject.getString("Genere");
girone= jsonobject.getString("Girone");
idcampionato= jsonobject.getString("IDCampionato");
switch (categoria){
case "A1":
if(genere.equals("Maschile")) {
A1M.add(idcampionato+" Serie " + categoria + " " + genere + " " + girone);
}
else {
A1F.add(idcampionato+" Serie " + categoria + " " + genere + " " + girone);
}
break;
case "A2":
if(genere.equals("Maschile")) {
A2M.add(idcampionato+" Serie " +categoria + " " + genere + " " + girone);
}
else {
A2F.add(idcampionato+" Serie " +categoria + " " + genere + " " + girone);
}
break;
case "B":
B.add(idcampionato+" Serie " +categoria + " " + genere + " "+girone);
break;
case "UNDER 21":
U21M.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 19":
U19F.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 17":
U17M.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 16":
U16F.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 14":
if(genere.equals("Maschile")) {
U14M.add(categoria + " " + genere + " " + girone);
}
else {
U14F.add(categoria + " " + genere + " " + girone);
}
break;
case "UNDER 12":
U12X.add(categoria + " " + genere + " "+girone);
break;
}
setChildGroupData(A1M, A1F, A2M, A2F, B, U21M, U19F, U17M, U16F, U14M
, U14F, U12X);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected String doInBackground(String... params) {
return super.doInBackground(params);
}
};
//Effettua richiesta HTTP al WS
http.execute(wsURL, "0", "mostraCampionati");
//Crea un adapter per inserire gli ArrayList nell'ExpandableListView
Log.i("INFO", String.valueOf(listDataChild.size()));
expandableListAdapter = new MyExpandableListAdapter(getActivity().getBaseContext(), listDataHeader, listDataChild);
//Sets the adapter for ExpandableList
expListView.setAdapter(expandableListAdapter);
//Sets the OnClickListener for childrens of the list
expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
String child = (String) parent.getExpandableListAdapter().getChild(groupPosition, childPosition);
String[] parti = child.split(" ");
key = Integer.parseInt(parti[0]); //gets the key of tuple which is the first part of the string
//gets Fragment Manager
FragmentManager fragmentManager = getFragmentManager();
//starts the transaction
android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.viewpager, PagePartite.newInstance(key)); //first page
ft.replace(R.id.viewpager, PageClassifica.newInstance(key)); //second page
ft.replace(R.id.viewpager, PageStatistiche.newInstance(key));
ft.addToBackStack(null);
ft.commit();
mDrawerTitle = (child);
return true;
}
});
}
else
Toast.makeText(getActivity(),"Connessione Internet assente",Toast.LENGTH_LONG).show();
return expListView ;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallbacks = (NavigationDrawerCallbacks) activity;
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
/**
* Per the navigation drawer design guidelines, updates the action bar to show the global app
* 'context', rather than just what's in the current screen.
*/
private void showGlobalContextActionBar() {
ActionBar actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(true);
}
private ActionBar getActionBar() {
return ((ActionBarActivity) getActivity()).getSupportActionBar();
}
/**
* Funzione che riempie l'HashMap ListDataChild con i dati ricevuti tramite richiesta HTTP.
* @param par ArrayList contenente i dati per ogni campionato
*/
protected void setChildGroupData(ArrayList<String> ... par){
//inserisce i dati dei Children e dei parent in un HashMap
listDataChild.put(listDataHeader.get(0), par[0]);
listDataChild.put(listDataHeader.get(1),par[1]);
listDataChild.put(listDataHeader.get(2),par[2]);
listDataChild.put(listDataHeader.get(3),par[3]);
listDataChild.put(listDataHeader.get(4),par[4]);
listDataChild.put(listDataHeader.get(5),par[5]);
listDataChild.put(listDataHeader.get(6),par[6]);
listDataChild.put(listDataHeader.get(7),par[7]);
listDataChild.put(listDataHeader.get(8),par[8]);
listDataChild.put(listDataHeader.get(9),par[9]);
listDataChild.put(listDataHeader.get(10),par[10]);
listDataChild.put(listDataHeader.get(11),par[11]);
}
/**
* Lista che inserisce i titoli dei campionati all'interno di una HashMap
*/
private void prepareHeaderData() {
listDataHeader = new ArrayList<String>();
listDataChild = new HashMap<String, List<String>>();
//Titoli delle sezioni
listDataHeader.add("Serie A1 Maschile");
listDataHeader.add("Serie A1 Femminile");
listDataHeader.add("Serie A2 Maschile");
listDataHeader.add("Serie A2 Femminile");
listDataHeader.add("Serie B Maschile");
listDataHeader.add("Under 21 Maschile");
listDataHeader.add("Under 19 Femminile");
listDataHeader.add("Under 17 Maschile");
listDataHeader.add("Under 16 Femminile");
listDataHeader.add("Under 14 Maschile");
listDataHeader.add("Under 14 Femminile");
listDataHeader.add("Under 12 Mista");
}
/**
* Callbacks interface that all activities using this fragment must implement.
*/
public static interface NavigationDrawerCallbacks {
/**
* Called when an item in the navigation drawer is selected.
*/
void onNavigationDrawerItemSelected(int position);
}
第一个片段
package com.dcdeveloper.fihresults;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
/**
* Fragment contenente le partite del campionato,disposte in giornate
* Use the {@link PagePartite#newInstance} factory method to
* create an instance of this fragment.
*/
// In this case, the fragment displays simple text based on the page
public class PagePartite extends Fragment implements AdapterView.OnItemSelectedListener{
/** View del frammento*/
protected View view;
private int mPage;
/**URL del WEB Service a cui effettuare richieste HTTP per ottenere i risultati delle partite*/
private String wsURL;
/**ID del campionato scelto*/
private static int idcampionato;
/**Layout che consente l'aggiornamento della pagina tramite swipe verticale*/
SwipeRefreshLayout mSwipeRefreshLayout;
/**Barra di progresso mostrata quando c'e una attesa nel caricamento dei dati*/
ProgressBar progressBar;
/**Spinner per scegliere la giornata del campionato di cui visualizzare le partite*/
Spinner spinner;
/**RecyclerView contenente le Card delle partite*/
RecyclerView recyclerList;
/**Giornata del campionato scelta*/
private int giornata;
/**
* Inizializza il fragment con il campionato scelto.
* @param IDCampionato Il campionato scelto
* @return Fragment il fragment PagePartite
*/
public static Fragment newInstance(int IDCampionato) {
PagePartite fragment = new PagePartite();
idcampionato=IDCampionato;
return fragment;
}
/**
* Costruttore vuoto richiesto
*/
public PagePartite(){
//required empty public constructor
}
/**
* Funzione che inizializza i dati del Fragment
* @param savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* Funzione che crea la grafica del Fragment definito nella funzione newIstance.Inizializza la RecyclerView con le View delle Card, lo SwipeRefreshLayout
* @param inflater Layout utilizzato per creare la grafica
* @param container Container del Fragment
* @param savedInstanceState
* @return View rappresentante il fragment
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//inflates the view inside ViewPager
view = inflater.inflate(R.layout.fragment_partite, container, false);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.partite_swipe_refresh_layout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.colore_sfondo_menu, R.color.indicator_color, R.color.colore_menu);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
refresh();
}
});
giornata=1;
spinner = (Spinner) view.findViewById(R.id.spinner);
//adding recyclerList and setting its layout
recyclerList = (RecyclerView) view.findViewById(R.id.cardList);
recyclerList.setHasFixedSize(true);
LinearLayoutManager layout = new LinearLayoutManager(view.getContext());
layout.setOrientation(LinearLayoutManager.VERTICAL);
recyclerList.setLayoutManager(layout);
getGiornate();
getPartite();
return view;
}
/**
* Funzione che riceve i risultati delle partite dopo aver effettuato una Richiesta HTTP,e li formatta all'interno di Card
*/
public void getPartite(){
wsURL = "http://fihresults.altervista.org/WebServiceFihResults/service.php";
if(hasConnection(view.getContext())) {
HTTPRequest http=new HTTPRequest() {
@Override
protected void onPreExecute() {
mSwipeRefreshLayout.setRefreshing(true);
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return super.doInBackground(params);
}
@Override
protected void onPostExecute(String result) {
mSwipeRefreshLayout.setRefreshing(false);
super.onPostExecute(result);
Log.i("INFO getPartite", result);
JSONArray dati = null;
ArrayList partite = new ArrayList();
try {
dati = new JSONArray(result);
for(int i=0;i<dati.length();i++) {
JSONObject jsonobject = dati.getJSONObject(i);
partite.add(new Partita(jsonobject));
}
} catch (JSONException e) {
e.printStackTrace();
}
CardAdapter cardadapt = new CardAdapter(0,partite);
recyclerList.setAdapter(cardadapt);
}
};
http.execute(wsURL, "4", "mostraPartite", "IDCampionato", String.valueOf(idcampionato), "NumGiornata", String.valueOf(giornata));
}
else
Toast.makeText(view.getContext(),"Connessione Internet assente",Toast.LENGTH_LONG).show();
}
/**
* Funzione che effettua una richiesta HTTP per ricevere il numero di giornate del campionato,quindi inserisce tali dati all'interno dello Spinner
*/
public void getGiornate() {
Log.i("INFO PagePartite", "ESEGUO getGiornate()");
wsURL = "http://fihresults.altervista.org/WebServiceFihResults/service.php";
if(hasConnection(view.getContext())) {
HTTPRequest http=new HTTPRequest() {
@Override
protected void onPreExecute() {
if(!mSwipeRefreshLayout.isRefreshing())
mSwipeRefreshLayout.setRefreshing(true);
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return super.doInBackground(params);
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i("INFO getGiornate",result);
int numgiornate;
ArrayList<String> giornate = new ArrayList();
JSONArray dati = null;
try {
dati = new JSONArray(result);
JSONObject jsonobject = dati.getJSONObject(0);
numgiornate= jsonobject.getInt("NumGiornate");
for(int i=1;i<=numgiornate;i++) {
String riga = "Giornata "+i;
giornate.add(riga);
}
} catch (JSONException e) {
e.printStackTrace();
}
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(view.getContext(),
android.R.layout.simple_list_item_1,giornate);
spinner.setAdapter(adapter);
}
};
http.execute(wsURL, "2", "getMaxGiornate", "IDCampionato", String.valueOf(idcampionato));
spinner.setOnItemSelectedListener(this);
}
else
Toast.makeText(view.getContext(),"Connessione Internet assente",Toast.LENGTH_LONG).show();
}
/**
* Funzione che cambia i dati a seconda della giornata selezionata all'interno dello spinner
* @param parent Parent dello Spinner
* @param view View
* @param position Posizione selezionata all'interno dello spinner
* @param id
*/
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
giornata=position+1;
getPartite();
}
/**
* Funzione che effettua il refresh dei dati della pagina
*/
public void refresh(){
getGiornate();
getPartite();
}
}
编辑:
FragmentPagerAdapter
package com.dcdeveloper.fihresults;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.Log;
import android.view.View;
/**
* Adapter per l'inserimento del frammento in un ViewPager.
* Settato per contenere tre pagine, "Partite","Classifica" e "Statistiche"
* Created by Dario on 06/06/2015.
*
*/
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Partite", "Classifica", "Statistiche" };
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
protected int idcampionato=1; //default value
@Override
public int getCount() {
return PAGE_COUNT;
}
/**
* Funzione richiamata quando un Fragment non è inizializzato,come all'avvio dell'applicazione.Restituisce il Fragment creato.
* @param position Posizione in cui creare il Fragment
* @return Fragment appena creato ed inserito nell'Adapter
*/
@Override
public Fragment getItem(int position) {
Fragment fragment=null;
Log.i("MyFragmentPagerAdapter "+(String)getPageTitle(position),Integer.toString(position));
switch(position) {
//when created,cards will get the default value (idcampionato=1)
case 0:
fragment = PagePartite.newInstance(idcampionato);
break;
case 1:
fragment = PageClassifica.newInstance(idcampionato);
break;
case 2:
fragment = PageStatistiche.newInstance(idcampionato);
break;
}
return fragment;
}
/**
* Ritorna il titolo della pagina corrente
* @param position posizione corrente
* @return Charsequence che rappresenta il titolo
*/
@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
我要向您展示的是一种非常基本的更新 ViewPager
片段的方法,方法是每次数据更改时用新实例替换现有片段。
这是公式:
- 允许
FragmentPagerAdapter
获取一些更新的数据。在您的情况下,您有一个名为 "key" 的 int 值,当用户从导航抽屉中选择一个项目时,该值会更新。我们将在您的 FragmentPagerAdapter
上放置一个方法,该方法将采用键值参数并开始更新。
- 在
FragmentPagerAdapter
到 return POSITION_NONE
上实施 getItemPosition()
。这将告诉 ViewPager
当前片段已过期,需要用另一个片段替换。
- 在适配器的
getItem()
方法中,实例化新片段时使用当前键值。 (你已经有了这部分。)
这是我建议的代码更改:
修改您的 Activity
以便您拥有对 FragmentPagerAdapter
实例的引用。
private MyFragmentPagerAdapter mAdapter;
在您的 Activity
中,确保您的 ViewPager
已与您的 FragmentPagerAdapter
一起设置。 (你没有 post 你的 Activity
代码,所以只要确保你没有错过这个。)这可能会发生在 onCreate()
.
mAdapter = new MyFragmentPagerAdapter();
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
向您的 Activity
添加一个方法以接受来自导航抽屉的键值并将其传递给适配器(我们将在一分钟内处理适配器):
public void select(int key) {
mAdapter.setKey(key);
}
从导航抽屉中删除此 FragmentTransaction
代码 onChildClick()
:
//gets Fragment Manager
FragmentManager fragmentManager = getFragmentManager();
//starts the transaction
android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.viewpager, PagePartite.newInstance(key)); //first page
ft.replace(R.id.viewpager, PageClassifica.newInstance(key)); //second page
ft.replace(R.id.viewpager, PageStatistiche.newInstance(key));
ft.addToBackStack(null);
ft.commit();
您的 MyFragmentPagerAdapter
将为您完成所有这些片段管理。因此,将该代码替换为:
((MainActivity) getActivity()).select(key);
(我不知道你的activity叫什么所以我就用了MainActivity
来举例。)
在您的 FragmentPagerAdapter
上覆盖并实施 getItemPosition()
,以便它始终 returns POSITION_NONE
:
public int getItemPosition(Object object) {
return POSITION_NONE;
}
您必须覆盖此方法,因为基础 class 方法只是 returns POSITION_UNCHANGED
,这导致 getItem()
永远不会被调用。
最后,在FragmentPagerAdapter
上添加获取键值的方法。您已经有一个键变量,因此您可以使用它来存储值:
public void setKey(int key) {
idcampionato = key;
notifyDataSetChanged();
}
事件顺序如下:
- 用户从导航抽屉中选择项目。
onChildClick()
用值调用 Activity.select()
。
select()
在适配器上调用 setKey()
。
- 适配器存储键值并调用
notifyDataSetChanged()
。
ViewPager
注意到适配器已更改并通过调用适配器的 getCount()
开始查看片段数是否已更改。
ViewPager
在每个页面位置调用 getItemPosition()
。 POSITION_NONE
是 returned,它告诉 ViewPager
该页面的片段需要删除并替换为新片段。
ViewPager
然后在每个页面位置上调用 getItem()
。这将调用片段的 newInstance
方法。由于您的 idcampionato
值已更新,因此将使用新键创建片段。
ViewPager
显示具有更新数据的新片段。
这不像我最初建议的方法那么优雅,即只创建一次片段,然后在片段上有一个自定义方法来更新键并刷新片段视图。但该方法需要为您更改更多代码,因此我决定采用更简单的解决方案。
我正在开发一个 Android 应用程序,可以查看曲棍球比赛的结果。
我正在使用带有自定义 FragmentPagerAdapter
的 ViewPager
来显示三个片段,并使用带有 ExpandableListView
的 NavigationDrawer
来显示锦标赛。
当我点击 ExpandableListView
childrens 时,我想用所选锦标赛的数据更新三个片段。
我在 NavigationDrawer
中设置了一个 OnchildClickListener
,其中我实例化了一个 FragmentManager
并调用了 replace()
方法。但它只是 returns 一个空白屏幕。
我在各个论坛都搜索过,尝试过不同的解决方案,但没有一个有效
当我使用 ft.add()
而不是 ft.replace()
并使用 SwipeRefreshLayout
刷新页面时,我得到了正确的结果,但我想在不手动刷新页面的情况下获得它。
我也尝试用 FragmentStatePagerAdapter
替换 FragmentPagerAdapter
,但没有任何改变。
NavigationDrawerFragment
package com.dcdeveloper.fihresults;
public class NavigationDrawerFragment extends Fragment {
/**
* Immagazzina lo stato della posizione dell'elemento selezionato.
*/
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
/**
* Per the design guidelines, you should show the drawer on launch until the user manually
* expands it. This shared preference tracks this.
*/
private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned";
/**
* A pointer to the current callbacks instance (the Activity).
*/
private NavigationDrawerCallbacks mCallbacks;
/**
* Helper component that ties the action bar to the navigation drawer.
*/
private ActionBarDrawerToggle mDrawerToggle;
/**
* Memorizza l'istanza del DrawerLayout
*/
private DrawerLayout mDrawerLayout;
/**View di questa barra di navigazione*/
private View mFragmentContainerView;
/**Posizione dell'elemento selezionato all'interno della lista*/
private int mCurrentSelectedPosition = 0;
private boolean mFromSavedInstanceState;
/**Boolean che indica se l'utente è venuto a conoscenza dell'utilizzo della barra laterale.Utilizzato per accessibilità.*/
private boolean mUserLearnedDrawer;
private ActionBarDrawerToggle actionBarDrawerToggle;
/**Lista con elementi espandibili,contiene i dati relativi ai campionati*/
ExpandableListView expListView;
/**adapter per inserire i dati nella ExpandableListView*/
MyExpandableListAdapter expandableListAdapter;
/*ArrayList dei titoli dei campionati*/
List<String> listDataHeader;
/**Hashmap contenente i dati relativi ai campionati,collegati ai relativi titoli*/
HashMap<String, List<String>> listDataChild;
HashMap<Campionato,Integer>listaCampionati;
/**Stringa contenente l'url del WS a cui si effettueranno le richieste HTTP per ricevere i dati dei campionati*/
String wsURL;
/**ID del campionato,utilizzato per aggiornare le pagine una volta premuto l'elemento di un campionato nella lista*/
protected int key;
/**Memorizza il titolo dell'Activity,in modo da cambiare il titolo della MainActivity*/
CharSequence mDrawerTitle;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Read in the flag indicating whether or not the user has demonstrated awareness of the
// drawer. See PREF_USER_LEARNED_DRAWER for details.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
if (savedInstanceState != null) {
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
mFromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(mCurrentSelectedPosition);
//Stringa contenente l'url del Web Service
wsURL = "http://fihresults.altervista.org/WebServiceFihResults/service.php";
//Prepara le intestazioni standard dei campionati
prepareHeaderData();
}
/**
* Metodo costruttore della view.Utilizza il layout predefinito del frammento.
* I dati inseriti all'interno del ListLayout vengono ricevuti dal server ed organizzati
* all' interno della lista.
*
*/
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
expListView = (ExpandableListView) inflater.inflate(
R.layout.fragment_navigation_campionati, container, false);
expListView .setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
mDrawerTitle= getActionBar().getTitle();
}
});
/**
* Definisce una nuova richiesta HTTP. Essa preleva i nomi ed i dati dei vari campionati,
* riempiendo degli ArrayList che saranno poi usati per creare l'ExpandableListView
*/
if(hasConnection(getActivity())) {
HTTPRequest http=new HTTPRequest() {
@Override
protected void onPostExecute(String result) {
//ArrayList di tutti i children che saranno inseriti nell'ExpandableListView
ArrayList<String>A1M=new ArrayList();
ArrayList<String>A1F=new ArrayList();
ArrayList<String>A2M=new ArrayList();
ArrayList<String>A2F=new ArrayList();
ArrayList<String>B=new ArrayList();
ArrayList<String>U21M=new ArrayList();
ArrayList<String>U19F=new ArrayList();
ArrayList<String>U17M=new ArrayList();
ArrayList<String>U16F=new ArrayList();
ArrayList<String>U14M=new ArrayList();
ArrayList<String>U14F=new ArrayList();
ArrayList<String>U12X=new ArrayList();
super.onPostExecute(result);
try {
//Formatta il risultato in un JSONArray
JSONArray dati = new JSONArray(result);
Log.i("INFO",result);
String categoria; //Categoria del campionato
String genere; //Genere (Maschile,Femminile,Misto)
String girone; //Girone del campionato
String idcampionato;
for(int i=0;i<dati.length();i++)
{
JSONObject jsonobject = dati.getJSONObject(i);
categoria=jsonobject.getString("Categoria");
genere= jsonobject.getString("Genere");
girone= jsonobject.getString("Girone");
idcampionato= jsonobject.getString("IDCampionato");
switch (categoria){
case "A1":
if(genere.equals("Maschile")) {
A1M.add(idcampionato+" Serie " + categoria + " " + genere + " " + girone);
}
else {
A1F.add(idcampionato+" Serie " + categoria + " " + genere + " " + girone);
}
break;
case "A2":
if(genere.equals("Maschile")) {
A2M.add(idcampionato+" Serie " +categoria + " " + genere + " " + girone);
}
else {
A2F.add(idcampionato+" Serie " +categoria + " " + genere + " " + girone);
}
break;
case "B":
B.add(idcampionato+" Serie " +categoria + " " + genere + " "+girone);
break;
case "UNDER 21":
U21M.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 19":
U19F.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 17":
U17M.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 16":
U16F.add(categoria + " " + genere + " "+girone);
break;
case "UNDER 14":
if(genere.equals("Maschile")) {
U14M.add(categoria + " " + genere + " " + girone);
}
else {
U14F.add(categoria + " " + genere + " " + girone);
}
break;
case "UNDER 12":
U12X.add(categoria + " " + genere + " "+girone);
break;
}
setChildGroupData(A1M, A1F, A2M, A2F, B, U21M, U19F, U17M, U16F, U14M
, U14F, U12X);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected String doInBackground(String... params) {
return super.doInBackground(params);
}
};
//Effettua richiesta HTTP al WS
http.execute(wsURL, "0", "mostraCampionati");
//Crea un adapter per inserire gli ArrayList nell'ExpandableListView
Log.i("INFO", String.valueOf(listDataChild.size()));
expandableListAdapter = new MyExpandableListAdapter(getActivity().getBaseContext(), listDataHeader, listDataChild);
//Sets the adapter for ExpandableList
expListView.setAdapter(expandableListAdapter);
//Sets the OnClickListener for childrens of the list
expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
String child = (String) parent.getExpandableListAdapter().getChild(groupPosition, childPosition);
String[] parti = child.split(" ");
key = Integer.parseInt(parti[0]); //gets the key of tuple which is the first part of the string
//gets Fragment Manager
FragmentManager fragmentManager = getFragmentManager();
//starts the transaction
android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.viewpager, PagePartite.newInstance(key)); //first page
ft.replace(R.id.viewpager, PageClassifica.newInstance(key)); //second page
ft.replace(R.id.viewpager, PageStatistiche.newInstance(key));
ft.addToBackStack(null);
ft.commit();
mDrawerTitle = (child);
return true;
}
});
}
else
Toast.makeText(getActivity(),"Connessione Internet assente",Toast.LENGTH_LONG).show();
return expListView ;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallbacks = (NavigationDrawerCallbacks) activity;
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
/**
* Per the navigation drawer design guidelines, updates the action bar to show the global app
* 'context', rather than just what's in the current screen.
*/
private void showGlobalContextActionBar() {
ActionBar actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(true);
}
private ActionBar getActionBar() {
return ((ActionBarActivity) getActivity()).getSupportActionBar();
}
/**
* Funzione che riempie l'HashMap ListDataChild con i dati ricevuti tramite richiesta HTTP.
* @param par ArrayList contenente i dati per ogni campionato
*/
protected void setChildGroupData(ArrayList<String> ... par){
//inserisce i dati dei Children e dei parent in un HashMap
listDataChild.put(listDataHeader.get(0), par[0]);
listDataChild.put(listDataHeader.get(1),par[1]);
listDataChild.put(listDataHeader.get(2),par[2]);
listDataChild.put(listDataHeader.get(3),par[3]);
listDataChild.put(listDataHeader.get(4),par[4]);
listDataChild.put(listDataHeader.get(5),par[5]);
listDataChild.put(listDataHeader.get(6),par[6]);
listDataChild.put(listDataHeader.get(7),par[7]);
listDataChild.put(listDataHeader.get(8),par[8]);
listDataChild.put(listDataHeader.get(9),par[9]);
listDataChild.put(listDataHeader.get(10),par[10]);
listDataChild.put(listDataHeader.get(11),par[11]);
}
/**
* Lista che inserisce i titoli dei campionati all'interno di una HashMap
*/
private void prepareHeaderData() {
listDataHeader = new ArrayList<String>();
listDataChild = new HashMap<String, List<String>>();
//Titoli delle sezioni
listDataHeader.add("Serie A1 Maschile");
listDataHeader.add("Serie A1 Femminile");
listDataHeader.add("Serie A2 Maschile");
listDataHeader.add("Serie A2 Femminile");
listDataHeader.add("Serie B Maschile");
listDataHeader.add("Under 21 Maschile");
listDataHeader.add("Under 19 Femminile");
listDataHeader.add("Under 17 Maschile");
listDataHeader.add("Under 16 Femminile");
listDataHeader.add("Under 14 Maschile");
listDataHeader.add("Under 14 Femminile");
listDataHeader.add("Under 12 Mista");
}
/**
* Callbacks interface that all activities using this fragment must implement.
*/
public static interface NavigationDrawerCallbacks {
/**
* Called when an item in the navigation drawer is selected.
*/
void onNavigationDrawerItemSelected(int position);
}
第一个片段
package com.dcdeveloper.fihresults;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
/**
* Fragment contenente le partite del campionato,disposte in giornate
* Use the {@link PagePartite#newInstance} factory method to
* create an instance of this fragment.
*/
// In this case, the fragment displays simple text based on the page
public class PagePartite extends Fragment implements AdapterView.OnItemSelectedListener{
/** View del frammento*/
protected View view;
private int mPage;
/**URL del WEB Service a cui effettuare richieste HTTP per ottenere i risultati delle partite*/
private String wsURL;
/**ID del campionato scelto*/
private static int idcampionato;
/**Layout che consente l'aggiornamento della pagina tramite swipe verticale*/
SwipeRefreshLayout mSwipeRefreshLayout;
/**Barra di progresso mostrata quando c'e una attesa nel caricamento dei dati*/
ProgressBar progressBar;
/**Spinner per scegliere la giornata del campionato di cui visualizzare le partite*/
Spinner spinner;
/**RecyclerView contenente le Card delle partite*/
RecyclerView recyclerList;
/**Giornata del campionato scelta*/
private int giornata;
/**
* Inizializza il fragment con il campionato scelto.
* @param IDCampionato Il campionato scelto
* @return Fragment il fragment PagePartite
*/
public static Fragment newInstance(int IDCampionato) {
PagePartite fragment = new PagePartite();
idcampionato=IDCampionato;
return fragment;
}
/**
* Costruttore vuoto richiesto
*/
public PagePartite(){
//required empty public constructor
}
/**
* Funzione che inizializza i dati del Fragment
* @param savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* Funzione che crea la grafica del Fragment definito nella funzione newIstance.Inizializza la RecyclerView con le View delle Card, lo SwipeRefreshLayout
* @param inflater Layout utilizzato per creare la grafica
* @param container Container del Fragment
* @param savedInstanceState
* @return View rappresentante il fragment
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//inflates the view inside ViewPager
view = inflater.inflate(R.layout.fragment_partite, container, false);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.partite_swipe_refresh_layout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.colore_sfondo_menu, R.color.indicator_color, R.color.colore_menu);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
refresh();
}
});
giornata=1;
spinner = (Spinner) view.findViewById(R.id.spinner);
//adding recyclerList and setting its layout
recyclerList = (RecyclerView) view.findViewById(R.id.cardList);
recyclerList.setHasFixedSize(true);
LinearLayoutManager layout = new LinearLayoutManager(view.getContext());
layout.setOrientation(LinearLayoutManager.VERTICAL);
recyclerList.setLayoutManager(layout);
getGiornate();
getPartite();
return view;
}
/**
* Funzione che riceve i risultati delle partite dopo aver effettuato una Richiesta HTTP,e li formatta all'interno di Card
*/
public void getPartite(){
wsURL = "http://fihresults.altervista.org/WebServiceFihResults/service.php";
if(hasConnection(view.getContext())) {
HTTPRequest http=new HTTPRequest() {
@Override
protected void onPreExecute() {
mSwipeRefreshLayout.setRefreshing(true);
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return super.doInBackground(params);
}
@Override
protected void onPostExecute(String result) {
mSwipeRefreshLayout.setRefreshing(false);
super.onPostExecute(result);
Log.i("INFO getPartite", result);
JSONArray dati = null;
ArrayList partite = new ArrayList();
try {
dati = new JSONArray(result);
for(int i=0;i<dati.length();i++) {
JSONObject jsonobject = dati.getJSONObject(i);
partite.add(new Partita(jsonobject));
}
} catch (JSONException e) {
e.printStackTrace();
}
CardAdapter cardadapt = new CardAdapter(0,partite);
recyclerList.setAdapter(cardadapt);
}
};
http.execute(wsURL, "4", "mostraPartite", "IDCampionato", String.valueOf(idcampionato), "NumGiornata", String.valueOf(giornata));
}
else
Toast.makeText(view.getContext(),"Connessione Internet assente",Toast.LENGTH_LONG).show();
}
/**
* Funzione che effettua una richiesta HTTP per ricevere il numero di giornate del campionato,quindi inserisce tali dati all'interno dello Spinner
*/
public void getGiornate() {
Log.i("INFO PagePartite", "ESEGUO getGiornate()");
wsURL = "http://fihresults.altervista.org/WebServiceFihResults/service.php";
if(hasConnection(view.getContext())) {
HTTPRequest http=new HTTPRequest() {
@Override
protected void onPreExecute() {
if(!mSwipeRefreshLayout.isRefreshing())
mSwipeRefreshLayout.setRefreshing(true);
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
return super.doInBackground(params);
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.i("INFO getGiornate",result);
int numgiornate;
ArrayList<String> giornate = new ArrayList();
JSONArray dati = null;
try {
dati = new JSONArray(result);
JSONObject jsonobject = dati.getJSONObject(0);
numgiornate= jsonobject.getInt("NumGiornate");
for(int i=1;i<=numgiornate;i++) {
String riga = "Giornata "+i;
giornate.add(riga);
}
} catch (JSONException e) {
e.printStackTrace();
}
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(view.getContext(),
android.R.layout.simple_list_item_1,giornate);
spinner.setAdapter(adapter);
}
};
http.execute(wsURL, "2", "getMaxGiornate", "IDCampionato", String.valueOf(idcampionato));
spinner.setOnItemSelectedListener(this);
}
else
Toast.makeText(view.getContext(),"Connessione Internet assente",Toast.LENGTH_LONG).show();
}
/**
* Funzione che cambia i dati a seconda della giornata selezionata all'interno dello spinner
* @param parent Parent dello Spinner
* @param view View
* @param position Posizione selezionata all'interno dello spinner
* @param id
*/
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
giornata=position+1;
getPartite();
}
/**
* Funzione che effettua il refresh dei dati della pagina
*/
public void refresh(){
getGiornate();
getPartite();
}
}
编辑:
FragmentPagerAdapter
package com.dcdeveloper.fihresults;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.util.Log;
import android.view.View;
/**
* Adapter per l'inserimento del frammento in un ViewPager.
* Settato per contenere tre pagine, "Partite","Classifica" e "Statistiche"
* Created by Dario on 06/06/2015.
*
*/
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Partite", "Classifica", "Statistiche" };
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
protected int idcampionato=1; //default value
@Override
public int getCount() {
return PAGE_COUNT;
}
/**
* Funzione richiamata quando un Fragment non è inizializzato,come all'avvio dell'applicazione.Restituisce il Fragment creato.
* @param position Posizione in cui creare il Fragment
* @return Fragment appena creato ed inserito nell'Adapter
*/
@Override
public Fragment getItem(int position) {
Fragment fragment=null;
Log.i("MyFragmentPagerAdapter "+(String)getPageTitle(position),Integer.toString(position));
switch(position) {
//when created,cards will get the default value (idcampionato=1)
case 0:
fragment = PagePartite.newInstance(idcampionato);
break;
case 1:
fragment = PageClassifica.newInstance(idcampionato);
break;
case 2:
fragment = PageStatistiche.newInstance(idcampionato);
break;
}
return fragment;
}
/**
* Ritorna il titolo della pagina corrente
* @param position posizione corrente
* @return Charsequence che rappresenta il titolo
*/
@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
我要向您展示的是一种非常基本的更新 ViewPager
片段的方法,方法是每次数据更改时用新实例替换现有片段。
这是公式:
- 允许
FragmentPagerAdapter
获取一些更新的数据。在您的情况下,您有一个名为 "key" 的 int 值,当用户从导航抽屉中选择一个项目时,该值会更新。我们将在您的FragmentPagerAdapter
上放置一个方法,该方法将采用键值参数并开始更新。 - 在
FragmentPagerAdapter
到 returnPOSITION_NONE
上实施getItemPosition()
。这将告诉ViewPager
当前片段已过期,需要用另一个片段替换。 - 在适配器的
getItem()
方法中,实例化新片段时使用当前键值。 (你已经有了这部分。)
这是我建议的代码更改:
修改您的
Activity
以便您拥有对FragmentPagerAdapter
实例的引用。private MyFragmentPagerAdapter mAdapter;
在您的
Activity
中,确保您的ViewPager
已与您的FragmentPagerAdapter
一起设置。 (你没有 post 你的Activity
代码,所以只要确保你没有错过这个。)这可能会发生在onCreate()
.mAdapter = new MyFragmentPagerAdapter(); ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
向您的
Activity
添加一个方法以接受来自导航抽屉的键值并将其传递给适配器(我们将在一分钟内处理适配器):public void select(int key) { mAdapter.setKey(key); }
从导航抽屉中删除此
FragmentTransaction
代码onChildClick()
://gets Fragment Manager FragmentManager fragmentManager = getFragmentManager(); //starts the transaction android.support.v4.app.FragmentTransaction ft = fragmentManager.beginTransaction(); ft.replace(R.id.viewpager, PagePartite.newInstance(key)); //first page ft.replace(R.id.viewpager, PageClassifica.newInstance(key)); //second page ft.replace(R.id.viewpager, PageStatistiche.newInstance(key)); ft.addToBackStack(null); ft.commit();
您的
MyFragmentPagerAdapter
将为您完成所有这些片段管理。因此,将该代码替换为:((MainActivity) getActivity()).select(key);
(我不知道你的activity叫什么所以我就用了
MainActivity
来举例。)在您的
FragmentPagerAdapter
上覆盖并实施getItemPosition()
,以便它始终 returnsPOSITION_NONE
:public int getItemPosition(Object object) { return POSITION_NONE; }
您必须覆盖此方法,因为基础 class 方法只是 returns
POSITION_UNCHANGED
,这导致getItem()
永远不会被调用。最后,在
FragmentPagerAdapter
上添加获取键值的方法。您已经有一个键变量,因此您可以使用它来存储值:public void setKey(int key) { idcampionato = key; notifyDataSetChanged(); }
事件顺序如下:
- 用户从导航抽屉中选择项目。
onChildClick()
用值调用Activity.select()
。select()
在适配器上调用setKey()
。- 适配器存储键值并调用
notifyDataSetChanged()
。 ViewPager
注意到适配器已更改并通过调用适配器的getCount()
开始查看片段数是否已更改。ViewPager
在每个页面位置调用getItemPosition()
。POSITION_NONE
是 returned,它告诉ViewPager
该页面的片段需要删除并替换为新片段。ViewPager
然后在每个页面位置上调用getItem()
。这将调用片段的newInstance
方法。由于您的idcampionato
值已更新,因此将使用新键创建片段。ViewPager
显示具有更新数据的新片段。
这不像我最初建议的方法那么优雅,即只创建一次片段,然后在片段上有一个自定义方法来更新键并刷新片段视图。但该方法需要为您更改更多代码,因此我决定采用更简单的解决方案。