How to pass data between fragments of an Activity in Android app

This blog demonstrates how to pass values of a variable between two fragments of a single activity. The blog will mainly include the demonstration of passing values between fragments while using BottomSheet Navigation as done in PSLab Android application.

This blog contains the work done by me in the Lux Meter instrument of the PSLab Android app of passing data from LuxMeterConfiguration fragment to LuxMeterData fragment as shown in the featured image to set the high limit for the pointer and to set the update period of the Lux Sensor. The blog will solve the difficult task of communication between two fragments of a single activity. For passing data between multiple fragments of different activities, refer to [1].

How to pass data between fragments?

In this blog, I will pass data from Fragment 2 to Fragment 1 only. But vice versa or passing data from both the fragments can also be made using the same given approach.

  • First, make a static method in Fragment 1 which can set the parameters i.e. the value of the variables as soon as the fragment is inflated as follow
public static void setParameters(int one, int two, int three) {
        Fragment1.firstValue = one;
        Fragment1.secondValue = two;
        Fragment1.thirdValue = three;
    }
  • Now, there is one point to mark that Fragment 1 will be inflated only when Fragment 2 gets destroyed. Else, other than default inflation of Fragment 1, there is no way Fragment 1 can be inflated after navigating to Fragment 2.
  • So, override the OnDestroy() method of Fragment 2 and use the setParameters() method to set the value of variables from Fragment 2 to be used in Fragment 1.
@Override
    public void onDestroyView() {
        super.onDestroyView();
        highValue = getValueFromText(highLimit, 0, highLimitMax);
        updatePeriodValue = getValueFromText(updatePeriod, updatePeriodMin, updatePeriodMax + 100);
        Fragment1.setParameters(selectedSensor, highValue, updatePeriodValue);
    }

Here, the highValue, updatePeriodValue and selectedSensor are the variables being used in the Lux Meter fragment in PSLab Android app. But they can be replaced by the necessary variables as per the app.

So, in this way, we can pass data between the fragments of the same Activity in an Android application. Above demonstration can be extended in passing values between multiple fragments of the same Activity by creating different methods in different fragments.

Resources

  1. Blog on how to pass data between fragments of different/same activities: https://www.journaldev.com/14207/android-passing-data-between-fragments

Continue ReadingHow to pass data between fragments of an Activity in Android app

How Switch Case improve performance in PSLab Saved Experiments

PSLab android application contains nearly 70 experiments one can experiment on using the PSLab device and the other necessary circuit components and devices. These experiments span over areas such as Electronics, Electrical, Physical and High school level. All these experiments are accessible via an android adapter in the repository named “PerformExperimentAdapter”. This adapter houses a tab view with two different tabs; one for the experiment details and the other for actual experiment and resultant graphs.

The adapter extends an inbuilt class FragmentPagerAdapter;

public class PerformExperimentAdapter extends FragmentPagerAdapter

This class displays every page attached to its viewpager as a fragment. The good thing about using fragments is that they have a recyclable life cycle. Rather than creating new views for every instance of an experiment, the similar views can be recycled to use once again saving resources and improving performance. FragmentPagerAdapter needs to override a method to display the correct view on the tab select by user.

@Override
public Fragment getItem(int position) {

}

Depending on the value of position, relevant experiment documentation and the experiment implementation fragments are displayed determined using the experiment title. Performance can be critical in this place as if it takes too long to process and render a fragment, user will feel a lag.

The previous implementation was using consecutive if statements.

@Override
public Fragment getItem(int position) {
   switch (position) {
       case 0:
           if (experimentTitle.equals(context.getString(R.string.diode_iv)))
               return ExperimentDocFragment.newInstance("D_diodeIV.html");
           if (experimentTitle.equals(context.getString(R.string.zener_iv)))
               return ExperimentDocFragment.newInstance("D_ZenerIV.html");
           ...
       case 1:
           if (experimentTitle.equals(context.getString(R.string.diode_iv)))
               return ZenerSetupFragment.newInstance();
           if (experimentTitle.equals(context.getString(R.string.zener_iv)))
               return DiodeExperiment.newInstance(context.getString(R.string.half_wave_rectifier));
           ...
       default:
           return ExperimentDocFragment.newInstance("astable-multivibrator.html");
   }
}

This setup was suitable for applications where there is less than around 5 choices to chose between. As the list grows, the elements in the end of the if layers will take more time to load as each of the previous if statements need to be evaluated false in order to reach the bottom statements.

This is when this implementation was replaced using switch case statements instead of consecutive if statements. The theory behind the performance improvement involves algorithm structures; Hash Tables

Hash Tables

Hash tables use a hash function to calculate the index of the destination cell. This operation on average has a complexity of O(1) which means it will take the same time to access any two elements which are randomly positioned.

This is possible because java uses the hash code of the string to determine the index where the target is situated at. This way it is much faster than consecutive if statement calls where in the worst case it will take O(n) time to reach the statement causing a lag in the application.

Current application uses switch cases in the PerformExperimentAdapter;

@Override
public Fragment getItem(int position) {
   switch (position) {
       case 0:
           switch (experimentTitle) {
               case "Diode IV Characteristics":
                   return ExperimentDocFragment.newInstance("D_diodeIV.html");
               case "Zener IV Characteristics":
                   return ExperimentDocFragment.newInstance("D_ZenerIV.html");
               case "Half Wave Rectifier":
                   return ExperimentDocFragment.newInstance("L_halfWave.html");
           }
       case 1:
           switch (experimentTitle) {
               case "Diode IV Characteristics":
                   return ZenerSetupFragment.newInstance();
               case "Zener IV Characteristics":
                   return ZenerSetupFragment.newInstance();
               case "Half Wave Rectifier":
                   return DiodeExperiment.newInstance(context.getString(R.string.half_wave_rectifier));
           }
       default:
           return ExperimentDocFragment.newInstance("astable-multivibrator.html");
   }
}

There is one downfall in using switch case in the context. That is the inability to use string resources directly as Java requires a constant literals in the evaluation statement of a case.

Resources:

Continue ReadingHow Switch Case improve performance in PSLab Saved Experiments