2012-01-21 18 views
21

Tengo un ViewPager y está usando un FragmentAdapter para mostrar varios fragmentos del mismo tipo. Aunque estos Fragmentos están básicamente instanciados de la misma clase, están usando un ListView para mostrar información diferente. (Obviamente, el ListView está siendo liberado por un ArrayAdapter).
También se está ejecutando un servicio en segundo plano que constantemente recibe datos de Internet. Quiero poder actualizar un Fragmento específico en el ViewPager cuando mi servicio en segundo plano me haya notificado un evento específico.
¿Cómo puedo hacer eso? ¡Un fragmento de código sería muy apreciado!ViewPager Actividad para notificar un Fragmento de un evento específico

(Por cierto, tengo sierra this similar question pero no tengo ni idea de cómo utilizar su sugerencia!)

Para hacer todo más sencillo: Mi actividad con el ViewPager:
[Fragmento 0] [Fragmento 1] [Fragmento 2]

el servicio fondo me dice (a través de una emisión) para actualizar la ListView en Fragmento 1.

EDIT: Éstos son los códigos de muestra:

public class ChatWindowPager extends FragmentActivity 
{ 
    private ViewPager mViewPager = null; 
    private ChatFragmentAdapter mAdapter = null; 
    @Override 
    protected void onCreate(final Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.chat_window_pager); 

     this.mViewPager = (ViewPager) findViewById(R.id.chatPager); 
     this.mAdapter = new ChatFragmentAdapter(getSupportFragmentManager()); 
     this.mViewPager.setAdapter(this.mAdapter); 
     . 
     . 
     . 
    } 

    class ChatFragmentAdapter extends FragmentPagerAdapter implements ViewProvider 
    { 

     public ChatFragmentAdapter(final FragmentManager fm) 
     { 
      super(fm); 
     } 

     @Override 
     public Fragment getItem(final int arg0) 
     { 
      String friendId = ..... // Some initializations 
      ChatWindowFragment f = ChatWindowFragment.newInstance(friendId); 
      return f; 
     } 

     @Override 
     public int getCount() 
     { 
      ... 
     } 

     @Override 
     public View getView(final int position) 
     { 
      View v = getLayoutInflater().inflate(R.layout.tab_holder, null); 
      . 
      . 
      . 
      return v; 
     } 
    } 
} 

Ahora los fragmentos se define así:

public class ChatWindowFragment extends Fragment 
{ 
    public String friendId; 
    private ListView lv; 

    public static ChatWindowFragment newInstance(final String friendId) 
    { 
     ChatWindowFragment chatWindowFragment = new ChatWindowFragment(); 
     Bundle bundle = new Bundle(); 
     bundle.putString("friendId", friendId); 
     chatWindowFragment.setArguments(bundle); 
     return chatWindowFragment; 
    } 

    @Override 
    public void onCreate(final Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     this.friendId = getArguments().getString("friendId"); 
    } 

    @Override 
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) 
    { 
     View v = inflater.inflate(R.layout.chat_window, container, false); 

     this.friendId = getArguments().getString("friendId"); 
     . 
     . 
     . 
     return v; 
    } 

    //The rest of the class 

} 

Como estoy usando un FragmentPagerAdapter No veo cómo puedo establece la etiqueta de cada fragmento! (Obviamente, no estoy usando transacciones para agregar los fragmentos!)

EDIT 2: me gustaría saber si lo que estoy haciendo, es la forma correcta de manejar lo que yo quiero hacer .. ¡Cualquier otra solución también es bienvenida!

+0

intenté con lo que sugerí .... –

Respuesta

38

Prueba de esto,

El registro de un receptor de radiodifusión en todas sus fragmentos como éste ...

crear una clase que se extiende un receptor de radiodifusión en todas las clases, por ejemplo:

public class FragmentReceiver1 extends BroadcastReceiver { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
     }  
} 

y registre este receptor en su fragmento onCreate ...

por ej. getActivity().registerReceiver(new FragmentReceiver1(), new IntentFilter("fragmentupdater"));

Ahora asignar un identificador único a cada uno de ustedes fragmento como 1 para Fragment1, 2 para Fragment2 y del mismo modo

ahora cada vez que desee transmitir los datos y actualizar cualquiera de los fragmentos simplemente enviar una difusión con los datos en intención y "fragmentupdater" como el filtro intención ...

por ejemplo:

Intent data = new Intent("fragmentupdater"); 
data.putString("key","data"); 
data.putInt("fragmentno",1); // Pass the unique id of fragment we talked abt earlier 
activity.sendBroadcast(data); 

Ahora cada uno de sus fragmentos recibirán los datos pero se puede verificar si los datos si por el mismo fragmento de la identificación única que pasó en ella en la función onReceive ..., la intención que se obtiene, es la intención que pasamos por encima de

+13

Si no está utilizando procesos múltiples, considere usar http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html en lugar de transmisiones globales. Por supuesto, siempre puede implementar su propio patrón de observador para que el fragmento se registre con el servicio y se le informe cuando ocurra un cambio en el que esté interesado. – hackbod

+1

@King RV ¡Te he otorgado la recompensa y sugerido una edición para tu publicación! Gracias ... Lo que sugirió hace el trabajo, me pregunto si hay una solución mejor/más simple para este problema. Gracias de nuevo – M2X

+0

Esta es una solución realmente complicada (aunque funciona). ¿Hay alguna solución más simple para volver a cargar el contenido del visor? Como eliminar todas las vistas secundarias y volver a cargarlas. –

5

Ha intentado FragmentManager.findFragmentByTag()

FragmentManager manager = getSupportedFragmentManager(); 
//with support package, else 
//FragmentManager manager = getFragmentManager() 
Fragment fragment = manager.findFragmentByTag("Tag You Created the Fragment"); 
if (fragment instanceof Fragment1){ 
    Fragment1 fr = (Fragment1)fragment 
    fr.updateData(DATA) 
    //or any method of your choice 
} 

EDIT: leí con cuidado! El instanceOf arrojará un Fragment en su clase Fragment. Fuiste tú quien sugirió Fragment1 como nombre para Simplicity. Además, no proporcionó ninguna fuente para ayudarnos. Es cierto, que no puede establecer una etiqueta Fragment, pero ¿por qué cree que puede obtener su etiqueta? Por lo general, se añade un Fragment través FragmentManagers como

FragmentManager manager = getSupportedFragmnentManager() 
FragmentTransaction transaction = manager.beginTransaction(); 
transaction.add(int containerViewId, Fragment fragment, String tag); 
// or transaction.add(Fragment fragment, String tag) 
// ...other transactions 
transaction.commit() 

Edit2: Es muy fácil, sin embargo. de acuerdo con su código sólo podría llamar

Fragment fragment = mAdapter.getItem(0) // 0||1||2 

debería considerar leer los documentos (es decir, sobre FragmenPagerAdapter) y publicar su código fuente, de modo que no tenemos que adivinar lo que necesita.

+0

¿Has leído mi pregunta con cuidado? ¡Dije, todos los fragmentos son instanciados de la misma clase! Entonces obviamente no puedo usar "instanceof". Además, hasta donde yo sé, no hay ningún método "setTag()" disponible en el fragmento. ¡Entonces no podría inicializar un fragmento usando una etiqueta! ¡Cualquier ayuda es muy apreciada! – M2X

+0

¡Mira la parte de edición! Todavía no sé qué hacer, ¡cualquier sugerencia es muy apreciada! – M2X

0

No sé lo suficiente de lo que está haciendo, pero parece que necesita utilizar un patrón Observer, Callbacks o Listeners. ¿No puede su fragmento hacer algo como:

myservice.addMyEventListener(myFragInstance); 

y luego puede ser "notificado de un evento específico".

+0

Suena bien ... ¿Cuidar para elaborar? – M2X

0

Basta con mirar a esta respuesta https://stackoverflow.com/a/16388650

Ha utilizado yourAdapter.notifyDataSetChanged() que es un método predefinido. Compruebe el enlace para ver cómo se hace

Editar: Cuando se realiza el AsyncTask, usted debe hacer algo como este método onPostExecute:

ResultFragment resultFrag = (ResultFragment) getSupportFragmentManager() 
           .findFragmentByTag("FragToRefresh"); 
if (resultFrag != null) { 
    resultFrag.refreshData(refreshedArray); 
} 

Y en su ResultFragment es necesario tener método RefreshData, que es algo como esto:

public void refreshData(ArrayList<YourObject> data) { 
    yourArray = new ArrayList<YourObject>(data); 
    yourAdapter.notifyDataSetChanged(); 
} 
+0

Siempre se recomienda escribir respuestas posiblemente "autónomas", que contengan una solución al problema, y ​​no meramente vincular a otra respuesta. ¿Quizás una edición para incluir el fragmento más relevante? :) – bardzusny

2

he tenido el mismo problema, pero lo arreglaron con una localBroadcastReceiver así:

Crear un receptor en su actividad y registrarlo:

/** 
* ****************************** 
* Receiver to process the message 
* ******************************* 
*/ 
private BroadcastReceiver onNotice = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     //You can send any extra data if you need like this 
     final int type = intent.getIntExtra("fragment.data", -1); 
     Log.d(tag, "main class: " + type); 
     //also refresh your fragment like this 
     mViewPager.getViewPager().getAdapter().notifyDataSetChanged(); 
    } 
};  

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

    //Register a localbroadCast with the your filter 
    IntentFilter thinaireFilter = new IntentFilter("your.filter"); 
    LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, thinaireFilter); 
} 

no olvide quitar LocalBroadCast

//remove the LocalBroadCast when no need it 
@Override 
protected void onPause() { 
    super.onPause(); 
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice); 
} 
@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice); 
} 

Envíe su difusión desde cualquier lugar que desee adaptadores, servicios, etc.

Intent sendBroadCastData = new Intent("your.filter"); 
sendBroadCastData.putExtra("fragment.data", myData); 
LocalBroadcastManager.getInstance(context).sendBroadcast(sendBroadCastData); 

Espero que ayude a los demás.

Cuestiones relacionadas