Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Observable in Android

I want to implement a Navigation View with many fragments that depend totally on a value defined in the MainActivity. I know that variables in MainActivity can be accessed using method defined in MainActivity from other Fragments to get the value, but the catch here is that the value of the variable in MainActivity may change (which runs on an AsyncThread). Now, I either change the code such that my Fragments update their value based on some event in the fragment itself or use SharedPreference. But I don't want to use SharedPreferences, neither have to check for change in the value unnecessarily many times.

I know in RxJS, we use Observable that runs Asynchronously and works in a fashion similar to a conveyor belt. A bit of googling through the official docs : Observable confirmed my suspicion of something similar being available in Android, but couldn't find any proper Tutorial or explanation on how to implement it. So, am looking for a simple code snippet that might give clarity to how Observable works in Android and if it is Async and if its based similar to RxJS implementation of it. (No, I don't want RxJS implementation)

Test Case:

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

MainActivity contains integers whose value when changed should reflect in corresponding integers across the Fragments and calls separate function for each Fragment on the change being noticed.

like image 529
Kaushik NP Avatar asked Mar 23 '17 17:03

Kaushik NP


People also ask

What is observable field in Android?

An observable class that holds a parcelable object. An object wrapper to make it observable. Observable field classes may be used instead of creating an Observable object.

How LiveData is different from ObservableField?

ObservableField is not Lifecycle aware but LiveData is lifecycle aware and hence will notify only the observables which are “active”. We have to do manual handling of Lifecycle awareness in ObservableField.

What is Rx in Android?

ReactiveX, also known as Reactive Extensions or RX, is a library for composing asynchronous and event-based programs by using observable sequences. This is perfect for Android, which is an event-driven and user-focused platform.


1 Answers

Here is a simple example with an Activity and a single Fragment but it will be the same with other fragments.

First you need to create a class standing for the value you want to observe, in your case it's a simple int so create a class containing this int and that extends Observable (it implements Serializable to simplify exchange between activity and fragment):

... 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);     } } 

Then use this observable int in an activity (activity layout contains a Button and a FrameLayout used to display a 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);             }         });     } } 

Finally, create a Fragment that listen a value change:

... 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);     } } 

I try to name my variables the same as yours, I hope it will help you.

like image 193
Gaëtan Maisse Avatar answered Oct 04 '22 02:10

Gaëtan Maisse