Fragments Basic Knowledge
Fragment Lifecycle :
The Correlation between Activity and Fragment Lifecycle considering Fragment is created on creation of Activity
OnCreate - A
onAttach - F
onCreate - F
onCreateView - F
onActivityCreated - F
onStart - F
onStart - A
onResume - A
onResume - F
onPause - F
onPause - A
onStop - F
onStop - A
onDestroyView - F
onDestroy - F
onDetach - F
onDestroy - A
The Correlation between Activity and Fragment Lifecycle considering Activity is created 1st and then the fragment is added
OnCreate - A
onStart - A
onResume - A
onAttach - F
onCreate - F
onCreateView - F
onActivityCreated - F
onStart - F
onResume - F
onPause - F
onPause - A
onStop - F
onStop - A
onDestroyView - F
onDestroy - F
onDetach - F
onDestroy - A
The Correlation between Activity and Fragment Lifecycle considering Activity is created 1st and then the fragment is added to back stack and back pressed
OnCreate - A
onStart - A
onResume - A
onAttach - F
onCreate - F
onCreateView - F
onActivityCreated - F
onStart - F
onResume - F
onPause - F
onStop - F
onDestroyView - F
onDestroy - F
onDetach - F
onPause - A
onStop - A
onDestroy - A
Steps for Adding a fragment :
- Create a layout for fragment
- Create a fragment class and extend with Fragment class
- Set the layout file to the defined fragment
- Add a layout that will host the fragment
- Write code to add Fragment to Activity in Activity
Fragments should not launch other fragments
public class MainActivity extends AppCompatActivity {
Button add;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
add = findViewById(R.id.btnAdd);
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addFragment();
}
});
}
private void addFragment() {
Fragment sampleFragment = new SampleFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmentContainer, sampleFragment, "demofragment");
// This statement will remove the fragment from the activity when we press back button
// Doesn't affect activity lifecycle
fragmentTransaction.addToBackStack("fragmentStack1");
fragmentTransaction.commit();
}
}Activity back stack is managed by ActivityManager managed by Android Platform itselfFragment back stack is managed by FragmentManager and needs to be managed by Developer
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/pale_blue_200"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragmentContainer"
android:layout_margin="5dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
SampleFragment.Java
public class SampleFragment extends Fragment {
@Nullable
@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,}
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_sample, container, false);
}fragment_sample.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:background="@color/pale_green_200">
</LinearLayout>
Playing with Back Stack :
Adding Fragment and Removing them from Back Stack
MainActivity.xml
public class MainActivity extends AppCompatActivity {
private final String TAG = this.getClass().getSimpleName();
Button add;
TextView txtFragCount;
FragmentTransaction fragmentTransaction;
FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
add = findViewById(R.id.btnAdd);
txtFragCount = (TextView)findViewById(R.id.txtFragCount);
fragmentManager = getSupportFragmentManager();
txtFragCount.setText("Frag Count in BackStack " + fragmentManager.getBackStackEntryCount());
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addFragment();
}
});
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
txtFragCount.setText("Frag Count in BackStack " + fragmentManager.getBackStackEntryCount());
}
});
Log.i(TAG, "Initial BackStackCount : "+fragmentManager.getBackStackEntryCount());
}
private void addFragment() {
Fragment fragment;
switch(fragmentManager.getBackStackEntryCount()) {
case 0 : fragment = new SampleFragment();
break;
case 1 : fragment = new FragmentTwo();
break;
case 2 : fragment = new FragmentThree();
break;
default : fragment = new SampleFragment();
break;
}
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragmentContainer, fragment, "demofragment");
// This statement will remove the fragment from the activity when we press back button
// Doesn't affect activity lifecycle
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}activity_main.xml<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/pale_blue_200"
tools:context=".MainActivity">
<Button
android:id="@+id/btnAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Fragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.023" />
<TextView
android:id="@+id/txtFragCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnAdd"
app:layout_constraintVertical_bias="0.041" />
<FrameLayout
app:layout_constraintTop_toBottomOf="@+id/txtFragCount"
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_marginTop="428dp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="16dp">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>fragment_sample/two/three.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"
android:background="@color/pale_green_200">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="100sp"
android:text="1" />
</LinearLayout>Playing with Fragments without Back Stack :Add, Remove and Replace Fragmentspublic class MainActivity extends AppCompatActivity {
private final String TAG = this.getClass().getSimpleName();
Button add;
TextView txtFragCount;
FragmentTransaction fragmentTransaction;
FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
add = findViewById(R.id.btnAdd);
txtFragCount = (TextView)findViewById(R.id.txtFragCount);
fragmentManager = getSupportFragmentManager();
txtFragCount.setText("Frag Count in BackStack " + fragmentManager.getBackStackEntryCount());
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addFragment();
}
});
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
txtFragCount.setText("Frag Count in BackStack " + fragmentManager.getBackStackEntryCount());
}
});
Log.i(TAG, "Initial BackStackCount : "+fragmentManager.getBackStackEntryCount());
}
private void addFragment() {
Fragment fragment = fragmentManager.findFragmentById(R.id.fragmentContainer);
if(fragment instanceof SampleFragment) {
fragment = new FragmentTwo();
} else if(fragment instanceof FragmentTwo) {
fragment = new FragmentThree();
} else if(fragment instanceof FragmentThree) {
fragment = new SampleFragment();
} else {
fragment = new SampleFragment();
}
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentContainer, fragment, "demofragment");
// This statement will remove the fragment from the activity when we press back button
// Doesn't affect activity lifecycle
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
@Override
public void onBackPressed() {
Fragment fragment = fragmentManager.findFragmentById(R.id.fragmentContainer);
if(fragment != null) {
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(fragment);
fragmentTransaction.commit();
} else {
super.onBackPressed();
}
}
}fragmentTransaction.replace(R.id.fragmentContainer, fragment, "demofragment");fragmentTransaction.add(R.id.fragmentContainer, fragment, "demofragment");Add : Will add the fragments one over other and will pop in LIFO when back pressed.Replace : Will replace the existing fragment with the new fragment.Only 1 fragment instance remains at any instance of timePop Back Stack are of three types :
Assuming we have 4 fragments added sequentially to backstack with positions mentioned as shown below eg :FragFour - 3 FragThree - 2 FragTwo - 1 FragOne - 0
- fm.popBackStack() - The default backstack which pops individual fragments from the backstack
- fm.popBackStack(int id, int flags) - The 1st int variable refers to the position/id of the fragments to be removed. Eg: Suppose we pass (1,0) then Frag at position 2 and 3 are popped out and position 1 i.e FragTwo will be at the top of backstack Suppose we pass (1,POP_BACK_STACK_INCLUSIVE) then Frag at position 1, 2 and 3 are popped out and position 1 i.e FragOne will be at the top of backstack
- fm.popBackStack(String name, int flags) - the String name refers to the string that we has used to add to the Back Stack ie fragmentTransaction.addToBackStack("Add "+fragment.toString()) Eg: Suppose we pass fm.popBackStack("Add FragTwo", 0) then Frag at position 2 and 3 are popped out and position 1 i.e FragTwo will be at the top of backstack Special Cases : Suppose we have the following situation FragTwo - 5 FragTwo - 4 FragFour - 3 FragThree - 2 FragTwo - 1 FragOne - 0 Suppose we pass fm.popBackStack("Add FragTwo", POP_BACK_STACK_INCLUSIVE), now 5 and 4 will be removed
& if we call fm.popBackStack("Add FragTwo", POP_BACK_STACK_INCLUSIVE) again then 3, 2, 1 will be removedMainActivity.xmlpublic class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String COMMON_TAG = "CombinedLifeCycle";
private static final String ACTIVITY_NAME = MainActivity.class.getSimpleName();
private static final String TAG = ACTIVITY_NAME;
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;
private Button buttonAddFragmentOne, buttonpopFragment, buttonRemoveFragment;
private TextView textViewFragmentCount;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonAddFragmentOne = (Button)findViewById(R.id.buttonAddFragmentOne);
buttonpopFragment = (Button)findViewById(R.id.buttonPopFragment);
buttonRemoveFragment = (Button)findViewById(R.id.buttonRemoveFragment);
textViewFragmentCount = (TextView)findViewById(R.id.textViewFragmentCount);
fragmentManager=getSupportFragmentManager();
textViewFragmentCount.setText("Fragment count in back stack: "+fragmentManager.getBackStackEntryCount());
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
textViewFragmentCount.setText("Fragment count in back stack: "+fragmentManager.getBackStackEntryCount());
StringBuilder stringBuilder=new StringBuilder("Current status of transaction back stack: "+fragmentManager.getBackStackEntryCount()+"\n");
for(int i=(fragmentManager.getBackStackEntryCount()-1); i>=0;i--){
FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(i);
stringBuilder.append(backStackEntry.getName()+"\n");
}
Log.i(TAG,stringBuilder.toString());
}
});
Log.i(COMMON_TAG,"Initial BackStackEntryCount: "+fragmentManager.getBackStackEntryCount());
buttonAddFragmentOne.setOnClickListener(this);
buttonpopFragment.setOnClickListener(this);
buttonRemoveFragment.setOnClickListener(this);
}
private void addFragment(){
Fragment fragment;
if(fragmentManager.getBackStackEntryCount()>0){
switch (fragmentManager.getBackStackEntryCount()){
case 0: loadFragmentOne(); break;
case 1: loadFragmentTwo();break;
case 2: loadFragmentThree(); break;
default: loadFragmentOne(); break;
}
}else {
fragment = fragmentManager.findFragmentById(R.id.fragmentContainer);
if(fragment instanceof SampleFragment){
loadFragmentTwo();
}else if(fragment instanceof FragmentTwo){
loadFragmentThree();
}else if(fragment instanceof FragmentThree){
loadFragmentOne();
}else{
loadFragmentOne();
}
}
}
private void loadFragmentOne(){
Fragment fragment;
fragmentTransaction = fragmentManager.beginTransaction();
fragment = fragmentManager.findFragmentByTag("demofragment");
/*if(fragment!=null){
fragmentTransaction.remove(fragment);
}*/
fragment = new SampleFragment();
fragmentTransaction.replace(R.id.fragmentContainer,fragment,"demofragment");
fragmentTransaction.addToBackStack("Add "+fragment.toString());
fragmentTransaction.commit();
}
private void loadFragmentTwo(){
Fragment fragment;
fragmentTransaction = fragmentManager.beginTransaction();
fragment = fragmentManager.findFragmentByTag("demofragment");
/*if(fragment!=null){
fragmentTransaction.remove(fragment);
}*/
fragment = new FragmentTwo();
fragmentTransaction.replace(R.id.fragmentContainer,fragment,"demofragment");
fragmentTransaction.addToBackStack("Add "+fragment.toString());
fragmentTransaction.commit();
}
private void loadFragmentThree(){
Fragment fragment;
fragmentTransaction = fragmentManager.beginTransaction();
fragment = fragmentManager.findFragmentByTag("demofragment");
/*if(fragment!=null){
fragmentTransaction.remove(fragment);
}*/
fragment = new FragmentThree();
fragmentTransaction.replace(R.id.fragmentContainer,fragment,"demofragment");
fragmentTransaction.addToBackStack("Add "+fragment.toString());
fragmentTransaction.commit();
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.buttonAddFragmentOne: addFragment(); break;
case R.id.buttonPopFragment: fragmentManager.popBackStack("Add SampleFragment",FragmentManager.POP_BACK_STACK_INCLUSIVE); break;
case R.id.buttonRemoveFragment:
fragmentTransaction = fragmentManager.beginTransaction();
Fragment fragment=fragmentManager.findFragmentById(R.id.fragmentContainer);
if(fragment!=null){
fragmentTransaction.remove(fragment);
fragmentTransaction.addToBackStack("Remove "+fragment.toString());
fragmentTransaction.commit();
}else{
Toast.makeText(this,"No Fragment to remove",Toast.LENGTH_SHORT).show();
}
break;
default: break;
}
}
}activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/pale_blue_200"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="3">
<Button
android:id="@+id/buttonAddFragmentOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Add" />
<Button
android:id="@+id/buttonPopFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Pop" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/buttonRemoveFragment"
android:text="Remove"
android:layout_weight="1"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textColor="@color/pale_green_200"
android:id="@+id/textViewFragmentCount"
android:gravity="center"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragmentContainer"
android:layout_margin="5dp" />
</LinearLayout>
Comments
Post a Comment