studio - Enviar datos de actividad a fragmentar en Android.
navegar entre fragments android studio (19)
Tengo dos clases Primero es la actividad, segundo es un fragmento donde tengo algunos EditText
. En la actividad tengo una subclase con async-task y en el método doInBackground
obtengo algún resultado, que doInBackground
en la variable. ¿Cómo puedo enviar esta variable de la subclase "mi actividad" a este fragmento?
A veces puede recibir Intención en su actividad y necesita pasar la información a su fragmento de trabajo.
Las respuestas dadas están bien si necesita iniciar el fragmento, pero si aún funciona, setArguments()
no es muy útil.
Otro problema ocurre si la información pasada causará la interacción con su interfaz de usuario. En ese caso, no puede llamar a algo como myfragment.passData()
porque android le dirá rápidamente que solo el hilo que creó la vista puede interactuar.
Así que mi propuesta es usar un receptor. De esa manera, puede enviar datos desde cualquier lugar, incluida la actividad, pero el trabajo se realizará dentro del contexto del fragmento.
En tu fragmento está onCreate()
:
protected DataReceiver dataReceiver;
public static final String REC_DATA = "REC_DATA";
@Override
public void onCreate(Bundle savedInstanceState) {
data Receiver = new DataReceiver();
intentFilter = new IntentFilter(REC_DATA);
getActivity().registerReceiver(dataReceiver, intentFilter);
}
private class DataReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int data= intent.getIntExtra("data", -1);
// Do anything including interact with your UI
}
}
En tu actividad:
// somewhere
Intent retIntent = new Intent(RE_DATA);
retIntent.putExtra("data", myData);
sendBroadcast(retIntent);
Desde la Actividad se envían datos con Bundle como:
Bundle bundle = new Bundle();
bundle.putString("data", "Data you want to send");
// Your fragment
MyFragment obj = new MyFragment();
obj.setArguments(bundle);
Y en el método Fragment onCreateView obtén los datos:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,`Bundle savedInstanceState)
{
String data = getArguments().getString("data");// data which sent from activity
return inflater.inflate(R.layout.myfragment, container, false);
}
Desde la Actividad se envían datos con intención como:
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
y en el método Fragment onCreateView:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
return inflater.inflate(R.layout.fragment, container, false);
}
El enfoque mejor y conveniente es llamar a la instancia de fragmento y enviar datos en ese momento. Cada fragmento por defecto tiene método de instancia
Por ejemplo: si el nombre de tu fragmento es MyFragment
así que llamarás a tu fragmento de una actividad como esta:
getSupportFragmentManager().beginTransaction().add(R.id.container, MyFragment.newInstance("data1","data2"),"MyFragment").commit();
* R.id.container es un id de mi FrameLayout
así que en MyFragment.newInstance ("data1", "data2") puede enviar datos al fragmento y en su fragmento obtiene estos datos en MyFragment newInstance (String param1, String param2)
public static MyFragment newInstance(String param1, String param2) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
y luego en el método de fragmento onCreate obtendrás los datos:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
así que ahora mParam1 tiene datos1 y mParam2 tiene datos2
ahora puedes usar este mParam1 y mParam2 en tu fragmento.
En tu actividad declara variable estática.
public static HashMap<String,ContactsModal> contactItems=new HashMap<String, ContactsModal>();
Luego en tu fragmento haz como seguir
ActivityName.contactItems.put(Number,contactsModal);
Esta respuesta puede ser demasiado tarde. Pero será útil para futuros lectores.
Tengo algunos criterios. He codificado para elegir el archivo de la intención. y el archivo seleccionado se pasará a un fragmento particular para su posterior proceso. Tengo muchos fragmentos que tienen la funcionalidad de selección de archivos. En ese momento, cada vez que se comprueba la condición, se obtiene el fragmento y se pasa el valor es bastante desagradable. Por lo tanto, he decidido pasar el valor utilizando la interfaz.
Paso 1: Crea la interfaz en la Actividad Principal.
public interface SelectedBundle {
void onBundleSelect(Bundle bundle);
}
Paso 2: crear el método en la misma actividad
public void setOnBundleSelected(SelectedBundle selectedBundle) {
this.selectedBundle = selectedBundle;
}
Paso 3: crear la referencia SelectedBundle en la misma actividad
SelectedBundle selectedBundle;
Paso 4: Debe inicializar la referencia de SelectedBundle, que son todos los fragmentos que necesitan la función de selector de archivos. Coloque este código en su fragmento en el onCreateView(..)
((MainActivity)getActivity()).setOnBundleSelected(new MainActivity.SelectedBundle() {
@Override
public void onBundleSelect(Bundle bundle) {
updateList(bundle);
}
});
Paso 5: onActivityResult de MainActivity, pasa los valores a los fragmentos usando la interfaz.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
selectedBundle.onBundleSelect(bundle);
}
Eso es todo. Implementa cada fragmento que necesites en el FragmentClass. Eres genial. has hecho. GUAU...
He encontrado muchas respuestas aquí @ .com pero definitivamente esta es la respuesta correcta de:
"Enviando datos de actividad a fragmento en android".
Actividad:
Bundle bundle = new Bundle();
String myMessage = " is cool!";
bundle.putString("message", myMessage );
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();
Fragmento:
Leyendo el valor en el fragmento.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = this.getArguments();
String myValue = bundle.getString("message");
...
...
...
}
o solo
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
String myValue = this.getArguments().getString("message");
...
...
...
}
La forma más inteligente y probada de pasar datos entre fragmentos y actividad es crear una variable, por ejemplo:
class StorageUtil {
public static ArrayList<Employee> employees;
}
Luego, para pasar los datos del fragmento a la actividad, lo hacemos en el método onActivityCreated:
//a field created in the sending fragment
ArrayList<Employee> employees;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
employees=new ArrayList();
//java 7 and above syntax for arraylist else use employees=new ArrayList<Employee>() for java 6 and below
//Adding first employee
Employee employee=new Employee("1","Andrew","Sam","1984-04-10","Male","Ghanaian");
employees.add(employee);
//Adding second employee
Employee employee=new Employee("1","Akuah","Morrison","1984-02-04","Female","Ghanaian");
employees.add(employee);
StorageUtil.employees=employees;
}
Ahora puede obtener el valor de StorageUtil.employees de todas partes. ¡Buena suerte!
La idea básica de usar Fragments (F) es crear componentes de IU autosostenibles y reutilizables en aplicaciones de Android. Estos fragmentos están contenidos en las actividades y hay una forma común (la mejor) de crear vías de comunicación desde A -> F y FA. Es imprescindible comunicarse entre FF a través de una actividad porque solo los fragmentos se desacoplan y son autosuficientes.
Por lo tanto, pasar datos desde A -> F será igual a lo explicado por ρяσѕρєя K. Además de esa respuesta, Después de la creación de los Fragmentos dentro de una Actividad, también podemos pasar datos a los fragmentos que llaman a los métodos en Fragmentos.
Por ejemplo:
ArticleFragment articleFrag = (ArticleFragment)
getSupportFragmentManager().findFragmentById(R.id.article_fragment);
articleFrag.updateArticleView(position);
Marque esta respuesta, si desea pasar los datos al fragmento después de que se haya creado https://.com/a/46467866/1594998
Mi solución es escribir un método estático dentro del fragmento:
public TheFragment setData(TheData data) {
TheFragment tf = new TheFragment();
tf.data = data;
return tf;
}
De esta manera, estoy seguro de que todos los datos que necesito están dentro del Fragmento antes de cualquier otra operación posible que pueda necesitar para trabajar con él. También se ve más limpio en mi opinión.
Muy viejo post, todavía me atrevo a agregar una pequeña explicación que hubiera sido útil para mí.
Técnicamente, puede establecer directamente miembros de cualquier tipo en un fragmento de actividad.
Entonces, ¿por qué Bundle?
La razón es muy simple: Bundle proporciona una manera uniforme de manejar:
- crear / abrir fragmento
- reconfiguración (rotación de pantalla) - simplemente agregue un paquete inicial / actualizado a outState en onSaveInstanceState ()
- Restauración de la aplicación después de ser recolectada en segundo plano (como con la reconfiguración).
Puede (si le gustan los experimentos) crear una solución alternativa en situaciones simples, pero Bundle-aproximación simplemente no ve la diferencia entre un fragmento y mil en un backstack, sigue siendo simple y directo.
Por eso la respuesta de @Elenasys es la solución más elegante y universal.
Y es por eso que la respuesta dada por @Martin tiene escollos.
Puede crear un método estático público en el fragmento, donde obtendrá una referencia estática de ese fragmento y luego pasará los datos a esa función y establecerá los datos en el mismo método y obtendrá datos a través de getArgument en el método oncreate del fragmento, y establecerá esos datos en locales variables
Quisiera agregar a los principiantes que la diferencia entre las 2 respuestas con más votos aquí viene dada por el uso diferente de un fragmento.
Si usa el fragmento dentro de la clase java donde tiene los datos que desea pasar, puede aplicar la primera respuesta para pasar los datos:
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
Sin embargo, si utiliza, por ejemplo, el código predeterminado que proporciona Android Studio para los fragmentos con pestañas, este código no funcionará.
No funcionará incluso si reemplaza el PlaceholderFragment predeterminado con sus FragmentClasses, e incluso si corrige el FragmentPagerAdapter a la nueva situación agregando un modificador para getItem () y otro modificador para getPageTitle () (como se muestra here )
Advertencia: el clip mencionado anteriormente tiene errores de código, que explico más adelante aquí, pero es útil para ver cómo se pasa del código predeterminado al código editable para fragmentos con pestañas. El resto de mi respuesta tiene mucho más sentido si consideras las clases java y los archivos xml de ese clip (representativo de un primer uso de fragmentos con pestañas en un escenario de principiante).
La razón principal por la que la respuesta con más votos de esta página no funcionará es que en ese código predeterminado para los fragmentos con pestañas, los fragmentos se usan en otra clase java: FragmentPagerAdapter!
Entonces, para enviar los datos, tiene la tentación de crear un paquete en MotherActivity y pasarlo en FragmentPagerAdapter, utilizando la respuesta no.2.
Solo que eso está mal otra vez. ( Probablemente podrías hacerlo así, pero es solo una complicación que no es realmente necesaria ).
Creo que la forma correcta / más fácil de hacerlo es pasar los datos directamente al fragmento en cuestión, utilizando la respuesta no.2. Sí, habrá un acoplamiento estrecho entre la Actividad y el Fragmento, PERO, para los fragmentos con pestañas, eso es algo que se espera. Incluso te aconsejaría crear los fragmentos con pestañas dentro de la clase java MotherActivity (como subclases, ya que nunca se usarán fuera de MotherActivity). Es fácil, solo agrega dentro de la clase java MotherActivity tantos fragmentos como necesites de esta manera:
public static class Tab1 extends Fragment {
public Tab1() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
return rootView;
}
}.
Por lo tanto, para pasar los datos de MotherActivity a tal Fragmento, deberá crear Strings / Bundles privados por encima de la actividad onCreate of your Mother, que puede rellenar con los datos que desea transmitir a los fragmentos, y transmitirlos a través de un método creado después de onCreate (aquí denominado getMyData ()).
public class MotherActivity extends Activity {
private String out;
private Bundle results;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mother_activity);
// for example get a value from the previous activity
Intent intent = getIntent();
out = intent.getExtras().getString("Key");
}
public Bundle getMyData() {
Bundle hm = new Bundle();
hm.putString("val1",out);
return hm;
}
}
Y luego en la clase de fragmentos, usas getMyData:
public static class Tab1 extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public Tab1() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
TextView output = (TextView)rootView.findViewById(R.id.your_id_for_a_text_view_within_the_layout);
MotherActivity activity = (MotherActivity)getActivity();
Bundle results = activity.getMyData();
String value1 = results.getString("val1");
output.setText(value1);
return rootView;
}
}
Si tiene consultas en la base de datos, le aconsejo que las haga en MotherActivity (y pase sus resultados como Strings / Enteros adjuntos a claves dentro de un paquete como se muestra arriba), ya que dentro de los fragmentos con pestañas, su sintaxis se volverá más compleja (esto se convierte en getActivity () por ejemplo, y getIntent se convierte en getActivity (). getIntent), pero también tiene la opción de hacer lo que desee.
Mi consejo para los principiantes es que se centren en pequeños pasos. Primero, obtenga su intención de abrir una actividad tabulada muy simple, sin pasar NINGUNA información. ¿Funciona? ¿Abre las pestañas que esperas? Si no, ¿por qué?
Comience por eso y, al aplicar soluciones como las que se presentan en here , vea lo que falta. Para ese clip en particular, nunca se muestra mainactivity.xml. Eso seguramente te confundirá. Pero si presta atención, verá que, por ejemplo, el contexto (herramientas: contexto) es incorrecto en los archivos de fragmentos XML. Cada fragmento XML debe apuntar a la clase de fragmento correcta (o subclase usando el separador $).
También verá que en la clase de actividad principal java necesita agregar tabLayout.setupWithViewPager (mViewPager) - justo después de la línea TabLayout tabLayout = (TabLayout) findViewById (R.id.tabs); sin esta línea, su vista no está realmente vinculada a los archivos XML de los fragmentos, pero muestra SOLAMENTE el archivo xml de la actividad principal.
Además de la línea en la clase java de actividad principal, en el archivo XML de actividad principal debe cambiar las pestañas para que se ajusten a su situación (por ejemplo, agregar o eliminar TabItems). Si no tiene pestañas en el XML de actividad principal, es posible que no haya elegido el tipo de actividad correcta cuando lo creó en primer lugar (nueva actividad - actividad con pestañas).
Tenga en cuenta que en los últimos 3 párrafos hablo sobre el video! Entonces, cuando digo la actividad principal XML, es la actividad principal XML en el video, que en su situación es el archivo XML MotherActivity.
Si pasa una referencia al fragmento (subclase concreta de) en la tarea asíncrona, puede acceder al fragmento directamente.
Algunas formas de pasar la referencia del fragmento a la tarea asíncrona:
- Si su tarea asíncrona es una clase de pleno derecho (la
class FooTask extends AsyncTask
), entonces pase su fragmento al constructor. - Si su tarea asíncrona es una clase interna, simplemente declare una variable Fragmento final en el alcance que se define la tarea asíncrona, o como un campo de la clase externa. Podrás acceder a eso desde la clase interna.
Si una activity
necesita hacer que un fragment
realice una acción después de la inicialización, la forma más fácil es hacer que la activity
invoque un método en la instancia del fragment
. En el fragment
, agregue un método:
public class DemoFragment extends Fragment {
public void doSomething(String param) {
// do something in fragment
}
}
y luego en la activity
, obtenga acceso al fragment
usando el administrador de fragment
y llame al method
:
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DemoFragment fragmentDemo = (DemoFragment)
getSupportFragmentManager().findFragmentById(R.id.fragmentDemo);
fragmentDemo.doSomething("some param");
}
}
y luego la activity
puede comunicarse directamente con el fragment
invocando este method
.
También puedes acceder a los datos de actividad del fragmento:
Actividad:
public class MyActivity extends Activity {
private String myString = "hello";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
...
}
public String getMyData() {
return myString;
}
}
Fragmento:
public class MyFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
MyActivity activity = (MyActivity) getActivity();
String myDataFromActivity = activity.getMyData();
return view;
}
}
Utilice la siguiente interfaz para comunicarse entre la actividad y el fragmento.
public interface BundleListener {
void update(Bundle bundle);
Bundle getBundle();
}
O utilice este escucha genérico para la comunicación bidireccional mediante la interfaz
/**
* Created by Qamar4P on 10/11/2017.
*/
public interface GenericConnector<T,E> {
T getData();
void updateData(E data);
void connect(GenericConnector<T,E> connector);
}
método de mostrar fragmentos
public static void show(AppCompatActivity activity) {
CustomValueDialogFragment dialog = new CustomValueDialogFragment();
dialog.connector = (GenericConnector) activity;
dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
}
también puede convertir su contexto en GenericConnector
en onAttach(Context)
en tu actividad
CustomValueDialogFragment.show(this);
en tu fragmento
...
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
connector.connect(new GenericConnector() {
@Override
public Object getData() {
return null;
}
@Override
public void updateData(Object data) {
}
@Override
public void connect(GenericConnector connector) {
}
});
}
...
public static void show(AppCompatActivity activity, GenericConnector connector) {
CustomValueDialogFragment dialog = new CustomValueDialogFragment();
dialog.connector = connector;
dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
}
Nota: Nunca lo use como "".toString().toString().toString();
camino.
el mejor enfoque para enviar datos de la clase de actividad al fragmento es pasar a través de métodos de establecimiento. Me gusta
FragmentClass fragmentClass = new FragmentClass();
fragmentClass.setMyList(mylist);
fragmentClass.setMyString(myString);
fragmentClass.setMyMap(myMap);
y obtener estos datos de la clase fácilmente.