tutorial rxkotlin rxjava2 rxjava que observables español java android observable

java - rxkotlin - Usando Observable en Android



rxjava2 android español (3)

Aquí hay un ejemplo simple con una Activity y un solo Fragment pero será igual con otros fragmentos.

Primero debe crear una clase que represente el valor que desea observar, en su caso, es un int simple, así que cree una clase que contenga este int y que se extienda a Observable (implementa Serializable para simplificar el intercambio entre actividad y fragmento):

... import java.util.Observable; public class ObservableInteger extends Observable implements Serializable { private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; this.setChanged(); this.notifyObservers(value); } }

Luego use este int observable en una actividad (el diseño de la actividad contiene un Button y un FrameLayout usado para mostrar un Fragment ):

public class MainActivity extends Activity { private ObservableInteger a; private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create observable int a = new ObservableInteger(); // Set a default value to it a.setValue(0); // Create frag1 Frag1 frag1 = new Frag1(); Bundle args = new Bundle(); // Put observable int (That why ObservableInteger implements Serializable) args.putSerializable(Frag1.PARAM, a); frag1.setArguments(args); // Add frag1 on screen getFragmentManager().beginTransaction().add(R.id.container, frag1).commit(); // Add a button to change value of a dynamically button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Set a new value in a a.setValue(a.getValue() + 1); } }); } }

Finalmente, crea un Fragment que escuche un cambio de valor:

... import java.util.Observer; public class Frag1 extends Fragment { public static final String PARAM = "param"; private ObservableInteger a1; private Observer a1Changed = new Observer() { @Override public void update(Observable o, Object newValue) { // a1 changed! (aka a changed) // newValue is the observable int value (it''s the same as a1.getValue()) Log.d(Frag1.class.getSimpleName(), "a1 has changed, new value:"+ (int) newValue); } }; public Frag1() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { // Get ObservableInteger created in activity a1 = (ObservableInteger) getArguments().getSerializable(PARAM); // Add listener for value change a1.addObserver(a1Changed); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_blank, container, false); } }

Intento nombrar mis variables igual que las tuyas, espero que te ayuden.

Quiero implementar una Navigation View con muchos fragmentos que dependen totalmente de un valor definido en MainActivity . Sé que se puede acceder a las variables en MainActivity utilizando el método definido en MainActivity desde otros Fragmentos para obtener el valor , pero el problema aquí es que el valor de la variable en MainActivity puede cambiar (que se ejecuta en un AsyncThread ). Ahora, o cambio el código para que mis Fragmentos actualicen su valor en función de algún evento en el propio fragmento o utilicen SharedPreference . Pero no quiero usar SharedPreferences, ni tengo que verificar el cambio en el valor innecesariamente muchas veces.

Sé que en RxJS, utilizamos Observable que funciona de forma asíncrona y funciona de una manera similar a una cinta transportadora. Un poco de googlear en los documentos oficiales: Observable confirmó mi sospecha de que algo similar estaba disponible en Android, pero no pudo encontrar ningún tutorial o explicación adecuada sobre cómo implementarlo. Por lo tanto, estoy buscando un fragmento de código simple que pueda aclarar cómo funciona Observable en Android y si es Async y si está basado en la implementación de RxJS. (No, no quiero la implementación de RxJS)

Caso de prueba:

MainActivity : int a, b (need observable for both variables) Frag1 : int a1 , b1, a1changed(),b1changed() Frag2 : int a2 , b2, a2Changed(), b2changed()

MainActivity contiene enteros cuyo valor cuando se modifica debe reflejarse en los enteros correspondientes en los Fragmentos y llama a una función separada para cada Fragmento en el cambio que se está notando.


Reactivo no es parte de Android pero probablemente esté buscando esta biblioteca: https://github.com/JakeWharton/RxBinding

A la página de destino le falta un ejemplo introductorio, así que tienes que mirar el javadoc. Esta publicación debería darle un buen comienzo: ¿Cómo crear un Observable desde OnClick Event Android? Aquí está el ejemplo de código de Matt para comenzar

RxView.clicks(myButton) .subscribe(new Action1<Void>() { @Override public void call(Void aVoid) { /* do something */ } });


Hay un buen ejemplo sobre el uso de Observable de Android (java.util.Observable) aquí: https://andhradroid.wordpress.com/2012/04/05/object-observer-pattern-in-android/

Y otro ejemplo sobre el uso del patrón Observer en Java: http://www.journaldev.com/1739/observer-design-pattern-in-java .

En general, hay dos formas:

  • Utilice java.util.Observable .
  • Diseña tu propio Observable (más flexible, ayúdanos a comprender más profundamente).

Me gusta la segunda forma más, por ejemplo: ( Lo siento, quiero asegurarme de que funcione, así que hago un ejemplo completo )

El observable :

public interface MyObservable { void addObserver(MyObserver myObserver); void removeObserver(MyObserver myObserver); void notifyObserversAboutA(); void notifyObserversAboutB(); }

El observador:

public interface MyObserver { void onAChange(int newValue); void onBChange(int newValue); }

La actividad principal:

public class MainActivity extends AppCompatActivity implements MyObservable { private List<MyObserver> myObservers; private int a, b; private EditText etA; private EditText etB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myObservers = new ArrayList<>(); ViewPager vpContent = (ViewPager) findViewById(R.id.activity_main_vp_content); etA = (EditText) findViewById(R.id.et_a); etB = (EditText) findViewById(R.id.et_b); Button btnOk = (Button) findViewById(R.id.btn_ok); //add fragments to viewpager List<Fragment> fragments = new ArrayList<>(); Fragment1 fragment1 = new Fragment1(); addObserver(fragment1); Fragment2 fragment2 = new Fragment2(); addObserver(fragment2); fragments.add(fragment1); fragments.add(fragment2); MyFragmentPagerAdapter fragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments); vpContent.setAdapter(fragmentPagerAdapter); btnOk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String a = etA.getText().toString().trim(); String b = etB.getText().toString().trim(); if (!a.equals("") && !b.equals("")) { setA(Integer.parseInt(a)); setB(Integer.parseInt(b)); } } }); } private void setA(int value) { a = value; notifyObserversAboutA(); } private void setB(int value) { b = value; notifyObserversAboutB(); } @Override public void addObserver(MyObserver myObserver) { myObservers.add(myObserver); } @Override public void removeObserver(MyObserver myObserver) { myObservers.remove(myObserver); } @Override public void notifyObserversAboutA() { for (MyObserver observer : myObservers) { observer.onAChange(this.a); } } @Override public void notifyObserversAboutB() { for (MyObserver observer : myObservers) { observer.onBChange(this.b); } } }

El Fragmento 1:

public class Fragment1 extends Fragment implements MyObserver { private TextView tvA; private TextView tvB; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View contentView = inflater.inflate(R.layout.fragment_basic, container, false); tvA = (TextView) contentView.findViewById(R.id.tv_a); tvB = (TextView) contentView.findViewById(R.id.tv_b); return contentView; } @Override public void onAChange(int newValue) { tvA.setText(String.valueOf("New value of a: " + newValue)); } @Override public void onBChange(int newValue) { tvB.setText(String.valueOf("New value of b: " + newValue)); } }

El Fragmento 2:

public class Fragment2 extends Fragment implements MyObserver { private TextView tvA; private TextView tvB; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View contentView = inflater.inflate(R.layout.fragment_basic, container, false); tvA = (TextView) contentView.findViewById(R.id.tv_a); tvB = (TextView) contentView.findViewById(R.id.tv_b); return contentView; } @Override public void onAChange(int newValue) { tvA.setText(String.valueOf("New value of a: " + newValue)); } @Override public void onBChange(int newValue) { tvB.setText(String.valueOf("New value of b: " + newValue)); } }

El adaptador:

public class MyFragmentPagerAdapter extends FragmentPagerAdapter { private List<Fragment> fragments; public MyFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) { super(fm); this.fragments = fragments; } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getCount() { return fragments.size(); } }

El diseño principal activity_main.xml:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="codeonce.thinktwice.testobserverpattern.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:id="@+id/linearLayout"> <EditText android:id="@+id/et_a" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" android:inputType="number" android:hint="Type value for a"/> <EditText android:id="@+id/et_b" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" android:inputType="number" android:hint="Type value for b"/> <Button android:id="@+id/btn_ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:layout_gravity="center_horizontal" android:text="OK"/> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/activity_main_vp_content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/linearLayout" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"> </android.support.v4.view.ViewPager> </RelativeLayout>

El diseño del fragmento fragment_basic.xml:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal"> <TextView android:layout_marginTop="20dp" android:id="@+id/tv_a" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Value of a will appear here" android:textSize="20sp"/> <TextView android:id="@+id/tv_b" android:layout_marginTop="20dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Value of b will appear here" android:textSize="20sp"/> </LinearLayout>