Cũng giống như activity, vòng đời của một fragment xảy ra khi trạng thái của nó thay đổi. Một sự kiện trong vòng đời của Fragment xảy ra khi chúng ta có thể nhìn thấy fragment đang hoạt động, hoặc là khi fragment không sử dụng được hoặc bị destroy. Và cũng giống với Activity, bạn có thể override các hàm trong vòng đời fragment như: onCreate(), onAttach(), onCreateView()… để thực hiện những tác vụ mong muốn
Dưới đây là sơ đồ minh họa về vòng đời của Fragment
Giải thích sơ đồ:
Khi fragment được tạo và chạy, sẽ thực hiện theo thứ tự như sau:
onAttach(): Fragment được gắn vào activity. Mỗi Fragment muốn chạy được thì nó phải thuộc vào một activity nào đó.
onCreate(): Khi một fragment mới được khởi tạo (hàm này luôn được gọi sau khi fragment được attach vào Activity)
onCreateView(): Hàm này dùng để tạo giao diện cho fragment. onActivityCreated(): Khi activity của fragment đã khởi tạo xong.
onStart(): Khi fragment hiển thị. Một fragment chỉ start sau khi Activity start và thường là nó start ngay lập tức khi Activity start xong.
ThS. Bùi Trung Úy 94
Các sự kiện khi bạn hoặc hệ thống destroy một fragment:
onPause(): Khi fragment không còn tương tác (có thể vẫn hiển thị). Điều này xảy ra ngay cả khi fragment bị gỡ bỏ hoặc bị thay thế, hoặc là khi activity của fragment bị tạm dừng.
onStop(): Khi fragment không còn hiển thị. Điều này xảy ra ngay sau khi fragment bị gỡ bỏ hoặc thay thế, hoặc là khi activity của fragment bị tạm dừng.
onDestroyView(): Khi các view hay resource được tạo trong onCreateView bị remove khỏi activity và destroy.
onDestroy(): Khi fragment kết thúc việc dọn dẹp. onDetach(): Khi fragment bị tách khỏi Activity của nó.
Bạn có thể thấy vòng đời của fragment được đan xen với vòng đời của activity. Tuy nhiên, vòng đời của Fragment có nhiều sự kiện trong vòng đời hơn so với Activity. Để hiểu rõ hơn vòng đời của một Frament, chúng ta có thể ghi đè các hàm sự kiện tương ứng và ghi ra log:
package com.example.helloandroid; import android.content.Context;
import android.support.v4.app.Fragment; import android.os.Bundle;
import android.util.Log;
public class DetailsFragment extends Fragment { @Override
public void onAttach(Context context) { super.onAttach(context);
Log.d("Fragment", "onAttach"); }
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
Log.d("Fragment", "onCreate"); }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
log.d("Fragment", "onCreateView"); return null;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState);
Log.d("Fragment", "onActivityCreated"); }
@Override
public void onStart() { super.onStart();
ThS. Bùi Trung Úy 95 Log.d("Fragment", "onStart");
}
@Override
public void onResume() { super.onResume();
Log.d("Fragment", "onResume"); }
@Override
public void onPause() { super.onPause();
Log.d("Fragment", "onPause"); }
@Override
public void onStop() { super.onStop();
Log.d("Fragment", "onStop"); }
@Override
public void onDestroyView() { super.onDestroyView();
Log.d("Fragment", "onDestroyView"); }
@Override
public void onDestroy() { super.onDestroy();
Log.d("Fragment", "onDestroy"); }
@Override
public void onDetach() { super.onDetach();
Log.d("Fragment", "onDetach"); }
}
Chạy ứng dụng trên thiết bị Android, thực hiện các thao tác bấm phím Home, Back, mở ứng dụng khác… bạn sẽ thấy hiển thị log về các sự kiện xảy ra trong vòng đời của các Fragment:
11-03 23:24:29.398: D/Fragment (11354): onAttach 11-03 23:24:29.398: D/Fragment (11354): onCreate 11-03 23:24:29.398: D/Fragment (11354): onCreateView 11-03 23:24:29.398: D/Fragment (11354): onActivityCreated 11-03 23:24:29.398: D/Fragment (11354): onStart 11-03 23:24:29.398: D/Fragment (11354): onResume 11-03 23:24:33.835: D/Fragment (11354): onPause 11-03 23:24:33.835: D/Fragment (11354): onStop 11-03 23:24:33.835: D/Fragment (11354): onDestroyView 11-03 23:24:33.835: D/Fragment (11354): onDestroy 11-03 23:24:33.835: D/Fragment (11354): onDetach
ThS. Bùi Trung Úy 96
Thực hành với Fragment:
Tạo dự án với bố cục giao diện như sau (với các hình ảnh như ví dụtrước).
Các bước thực hiện:
ThS. Bùi Trung Úy 97
B2. Tiếp theo chúng ta tạo file top_fragment.xml:
Trên Android Studio chọn: „File/New/Layout resource file‟
Nhập thông tin như sau:
Thiết kế giao diện trên top_fragment.xml, có được xml như sau: <?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:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:textColor="#FF0000" android:layout_marginTop="10dp" android:layout_gravity="center"
android:text="Image of 4 cities in Vietnam" />
ThS. Bùi Trung Úy 98 <RadioGroup android:id="@+id/rdGpCities" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal" > <RadioButton android:id="@+id/rdDalat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Dalat" /> <RadioButton android:id="@+id/rdDanang" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Danang" /> <RadioButton android:id="@+id/rdHanoi" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hanoi" /> <RadioButton android:id="@+id/rdbSaigon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Saigon" /> </RadioGroup> <Button android:id="@+id/btApply" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Apply" /> </LinearLayout>
Tương tự tạo file bottom_fragment.xml, có XML như sau: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:textSize="25dp" android:textColor="#0000FF" android:layout_marginTop="20dp" android:text=""/> <ImageView
ThS. Bùi Trung Úy 99 android:id="@+id/cityView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitCenter" /> </LinearLayout>
Mỗi Fragment sẽ tương ứng với một lớp trong Java. Lớp này mở rộng từ lớp Fragment. Tạo 2 lớp TopFragment.java và BottomFragment.java và sửa code của nó như sau. TopFragment.java package com.example.helloandroid; import android.support.v4.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;
public class TopFragment extends Fragment { @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Đọc file xml tạo ra đối tượng View.
View view = inflater.inflate(R.layout.top_fragment, container, false); return view; } } BottomFragment.java package com.example.helloandroid; import android.support.v4.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;
ThS. Bùi Trung Úy 100 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Đọc file xml tạo ra đối tượng View.
View view= inflater.inflate(R.layout.bottom_fragment, container, false); return view;
} }
Và bây giờ, bạn cần bố trí các fragment trên giao diện chính của FragmentActivity. Mở file activity_fragment.xml, kéo thẻ <fragment> vào giao diện và chọn TopFragment.java
Tương tự với BottomFragment.java, ta có nội dung file activity_fragment.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <fragment android:id="@+id/fragTop" android:name="com.example.helloandroid.TopFragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> <fragment android:id="@+id/fragBottom"
ThS. Bùi Trung Úy 101 android:name="com.example.helloandroid.BottomFragment"
android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Sửa file AndroidManifest.xml cho FragmentActivity là activity chính như sau:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.helloandroid"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".FragmentActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MainActivity" /> </application> </manifest> Chạy thửứng dụng, ta có kết quả:
Tiếp theo, bạn cần phải viết code cho 3 lớp FragmentActivity.java,
TopFragment.java, BottomFragment.java để xử lý các sự kiện.
TopFragment.java package com.example.helloandroid; import android.app.Activity; import android.content.Context; import android.support.v4.app.Fragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View;
ThS. Bùi Trung Úy 102 import android.view.ViewGroup;
import android.widget.Button; import android.widget.RadioGroup; import android.widget.Toast;
public class TopFragment extends Fragment { private int imageCityId;
private String cityName = ""; private FragmentActivity mActivity; @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Đọc file xml tạo ra đối tượng View.
View view = inflater.inflate(R.layout.top_fragment, container, false); // Đăng ký sự kiện khi RadioGroup Cities có thay đổi.
RadioGroup rdGpCities = (RadioGroup) view.findViewById(R.id.rdGpCities);
rdGpCities.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override
public void onCheckedChanged(RadioGroup group, int checkedId) { doOnCitiesChanged(group, checkedId);
} });
Button applyButton = (Button) view.findViewById(R.id.btApply); applyButton.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) { applyChange(); } }); return view; }
// Phương thức này được gọi sau khi Fragment được gắn vào Activity. @Override
public void onAttach(Context context) { super.onAttach(context);
Log.d("Fragment", "onAttach");
if (context instanceof FragmentActivity) { this.mActivity = (FragmentActivity) context; }
}
// Khi radio group "Cities" có thay đổi.
private void doOnCitiesChanged(RadioGroup group, int checkedId) { int checkedRadioId = group.getCheckedRadioButtonId();
if(checkedRadioId== R.id.rdDalat) { imageCityId = R.drawable.dalat; cityName = "City: Dalat";
} else if(checkedRadioId== R.id.rdDanang ) { imageCityId = R.drawable.danang;
ThS. Bùi Trung Úy 103 cityName = "City: Danang";
} else if(checkedRadioId== R.id.rdHanoi) { imageCityId = R.drawable.hanoi; cityName = "City: Ha Noi";
} else if(checkedRadioId== R.id.rdbSaigon) { imageCityId = R.drawable.saigon; cityName = "City: Saigon"; }
Toast.makeText(mActivity, "You choose:" + cityName, Toast.LENGTH_SHORT).show(); }
private void applyChange() {
mActivity.showCityImage(cityName, imageCityId); } } BottomFragment.java package com.example.helloandroid; import android.support.v4.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView;
public class BottomFragment extends Fragment { private TextView textView;
private ImageView cityView; @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Đọc file xml tạo ra đối tượng View.
View view = inflater.inflate(R.layout.bottom_fragment, container, false); textView = (TextView) view.findViewById(R.id.textView);
cityView = (ImageView) view.findViewById(R.id.cityView); return view;
}
public void showCity(String cityName, int imageId) { textView.setText(cityName); cityView.setImageResource(imageId); } } FragmentActivity.java package com.example.helloandroid;
ThS. Bùi Trung Úy 104 import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity; import android.os.Bundle;
public class FragmentActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment); }
public void showCityImage(String cityName, int imageId) {
FragmentManager fragManager = this.getSupportFragmentManager(); BottomFragment bottomFragment
= (BottomFragment)fragManager.findFragmentById(R.id.fragBottom); bottomFragment.showCity(cityName, imageId);
} }
ThS. Bùi Trung Úy 105