Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Жизненный цикл фрагментов

У фрагментов есть жизненный цикл, который во многом совпадает с жизненным циклом активности, внутри которой они находятся.

Жизненный цикл фрагментов

Список дополнительных методов жизненного цикла фрагментов, которых нет у активности:

onAttach(Activity)
Вызывается, когда фрагмент связывается с активностью. С этого момента мы можем получить ссылку на активность через метод getActivity()
onCreate()
В этом методе можно сделать работу, не связанную с интерфейсом. Например, подготовить адаптер.
onCreateView(LayoutInflater, ViewGroup, Bundle)
Вызывается для создания компонентов внутри фрагмента
onActivityCreated(Bundle)
Вызывается, когда отработает метод активности onCreate(), а значит фрагмент может обратиться к компонентам активности
onDestroyView()
Вызывается, когда набор компонентов удаляется из фрагмента
onDetach()
Вызывается, когда фрагмент отвязывается от активности

Одноимённые с методами активности методы фрагментов выполняют аналогичные функции. К примеру, метод onResume() вызывается, когда фрагмент вновь становится видимым.

Метод onStart() вызывается, когда фрагмент становится видимым после запуска такого же метода в родительской активности.

Фрагмент всегда связан с активностью. Отдельно фрагмент от активности существовать не может.

Если активность останавливается, то её фрагменты также останавливаются. Если активность уничтожается, то её фрагменты также уничтожаются.

Метод onCreateView() вызывается один раз, когда фрагмент должен загрузить на экран свой интерфейс. В этом методе вы можете "надуть" (inflate) разметку фрагмента через метод inflate() объекта Inflater, который задан в параметре метода. В фрагментах без интерфейса вы можете пропустить надувание.

Метод onActivityCreated() вызывается после метода onCreateView(), когда создаётся активность-хозяйка для фрагмента. Здесь можно объявить объекты, необходимые для Context.

Фрагменты не являются подклассами Context, вам следует использовать метод getActivity(), чтобы получить родительскую активность.

Создадим несколько фрагментов и с помощью всплывающих сообщений и логов посмотрим на срабатывание методов.

FirstFragment


package ru.alexanderklimov.fragmentdemo;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;


public class FirstFragment extends Fragment {

    public static FirstFragment newInstance(String param1, String param2) {
        FirstFragment fragment = new FirstFragment();
       // Bundle args = new Bundle();
        return fragment;
    }

    public FirstFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Toast.makeText(getActivity(), "FirstFragment.onCreate()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onCreate");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_first, container, false);

        Toast.makeText(getActivity(), "FirstFragment.onCreateView()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onCreateView");

        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        Toast.makeText(getActivity(), "FirstFragment.onAttach()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onAttach");
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Toast.makeText(getActivity(), "FirstFragment.onActivityCreated()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onActivityCreated");
    }

    @Override
    public void onStart() {
        super.onStart();
        Toast.makeText(getActivity(), "FirstFragment.onStart()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Toast.makeText(getActivity(), "FirstFragment.onResume()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        Toast.makeText(getActivity(), "FirstFragment.onPause()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Toast.makeText(getActivity(), "FirstFragment.onStop()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onStop");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Toast.makeText(getActivity(), "FirstFragment.onDestroyView()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onDestroyView");
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(getActivity(), "FirstFragment.onDestroy()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onDestroy");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        //mListener = null;
        Toast.makeText(getActivity(), "FirstFragment.onDetach()",
                Toast.LENGTH_LONG).show();
        Log.d("Fragment 1", "onDetach");
    }
}

Разметка для первого фрагмента


<?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" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Первый фрагмент" />
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/ic_launcher"/>
</LinearLayout>

По аналогии создайте второй фрагмент SecondFragment, заменив тексты и названия идентификаторов там, где это нужно.

Создадим разметку для главной активности с двумя кнопками для переключения между фрагментами.

activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="0px"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Выберите фрагмент:" />

        <Button
            android:id="@+id/buttonFragment1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Fragment 1" />

        <Button
            android:id="@+id/buttonFragment2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Fragment 2" />
    </LinearLayout>

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="0px"
        android:layout_weight="3"
        android:layout_height="match_parent" />

</LinearLayout>

MainActivity.java

В главной активности можно переключаться между фрагментами при нажатии на кнопку, а также через кнопку BACK, чтобы увидеть транзакции фрагментов.


package ru.alexanderklimov.fragmentdemo;

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;


public class MainActivity extends ActionBarActivity {

    Button fragment1Button, fragment2Button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragment1Button = (Button) findViewById(R.id.buttonFragment1);
        fragment2Button = (Button) findViewById(R.id.buttonFragment2);

        // get an instance of FragmentTransaction from your Activity
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        //add a fragment
        FirstFragment firstFragment = new FirstFragment();
        fragmentTransaction.add(R.id.container, firstFragment);
        fragmentTransaction.commit();

        fragment1Button.setOnClickListener(onButtonClickListener);
        fragment2Button.setOnClickListener(onButtonClickListener);
    }

    Button.OnClickListener onButtonClickListener = new Button.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Fragment newFragment = null;

            // Create new fragment
            if (v == fragment1Button) {
                newFragment = new FirstFragment();
            } else {
                newFragment = new SecondFragment();
            }

            // Create new transaction
            FragmentTransaction transaction = getFragmentManager().beginTransaction();

            // Replace whatever is in the fragment_container view with this fragment,
            // and add the transaction to the back stack
            transaction.replace(R.id.container, newFragment);
            transaction.addToBackStack(null);

            // Commit the transaction
            transaction.commit();
        }
    };
}

Cмотрим сообщения. При запуске приложения запускается первый фрагмент, который загружается в контейнер. Последовательность следующая.

onAttach
onCreate
onCreateView
onActivityCreated
onStart
onResume

Нажимаем на кнопку Home:

onPause
onStop

Запустим из списка недавно запущенных программ:

onStart
onResume

Выходим из программы через кнопку Back:

onPause
onStop
onDestroyView
onDestroy
onDetach

При замещении первого фрагмента вторым почти как при закрытии, только нет методов onDestroy и onDetach, а затем повторяются те же методы при старте фрагмента:

// Первый фрагмент onPause
onStop
onDestroyView
// Второй фрагмент onAttach
onCreate
onCreateView
onActivityCreated
onStart
onResume

Дополнительное чтение

xxv/android-lifecycle - схема жизненного цикла в SVG, PDF, PNG.

Реклама