(一)
-
Faragment有自己的生命周期
-
Fragment依賴於Activity
-
Fragmen通過getActivity()可以獲取所在Activity;Activity通過FragmentManager的findFragmentById()或findFragmentbyTag()獲取Fragment
-
Fragment和Activity是多對多的關系
MainActivity
1 package com.example.fragmentdemo.UI; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 5 import android.content.Intent; 6 import android.os.Bundle; 7 import android.view.View; 8 import android.widget.Button; 9 10 import com.example.fragmentdemo.R; 11 12 public class MainActivity extends AppCompatActivity { 13 14 private Button mBtnFragment; 15 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 setContentView(R.layout.activity_main); 20 mBtnFragment = (Button)findViewById(R.id.btn_fragment); 21 setListeners(); 22 } 23 24 private void setListeners(){ 25 OnClick onclick = new OnClick(); 26 mBtnFragment.setOnClickListener(onclick); 27 } 28 29 private class OnClick implements View.OnClickListener { 30 31 @Override 32 public void onClick(View v) { 33 Intent intent = null; 34 switch (v.getId()){ 35 case R.id.btn_fragment: 36 intent = new Intent(MainActivity.this,ContainerActivity.class); 37 startActivity(intent); 38 break; 39 default: 40 } 41 } 42 } 43 }
ContainerActivity
1 package com.example.fragmentdemo.UI; 2 3 import android.os.Bundle; 4 import android.view.View; 5 import android.widget.Button; 6 7 import androidx.appcompat.app.AppCompatActivity; 8 import androidx.fragment.app.Fragment; 9 10 import com.example.fragmentdemo.AFragment; 11 import com.example.fragmentdemo.BFragment; 12 import com.example.fragmentdemo.R; 13 14 public class ContainerActivity extends AppCompatActivity { 15 16 private AFragment aFragment; 17 private BFragment bFragment; 18 private Button mBtnChange; 19 20 @Override 21 protected void onCreate(Bundle savedInstanceState) { 22 super.onCreate(savedInstanceState); 23 setContentView(R.layout.activity_container); 24 mBtnChange = (Button)findViewById(R.id.btn_change); 25 mBtnChange.setOnClickListener(new View.OnClickListener(){ 26 27 @Override 28 public void onClick(View v) { 29 if (bFragment == null){ 30 bFragment = new BFragment(); 31 } 32 getSupportFragmentManager().beginTransaction().replace(R.id.fl_container,bFragment).commitNowAllowingStateLoss(); 33 } 34 }); 35 // 實例化AFragment 36 aFragment = new AFragment(); 37 // 把aFragment添加到Activity中 記得調用commitAllowingStateLoss 38 // getSupportFragmentManager().beginTransaction().add(R.id.fl_container,aFragment).commit(); 39 // 當Fragment出現錯誤時,使用commit()方法會返回一些錯誤,而commitAllowingStateLoss()就不會 40 getSupportFragmentManager().beginTransaction().add(R.id.fl_container,aFragment).commitAllowingStateLoss(); 41 // getSupportFragmentManager().beginTransaction().replace()替換 42 // getSupportFragmentManager().beginTransaction().remove()移除 43 } 44 45 }
AFragment
1 package com.example.fragmentdemo; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.os.Bundle; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.TextView; 10 11 import androidx.annotation.NonNull; 12 import androidx.annotation.Nullable; 13 import androidx.fragment.app.Fragment; 14 15 public class AFragment extends Fragment { 16 17 private TextView mTvTitle; 18 private Activity mActivity; 19 20 /** 21 * 返回一個視圖文件,相當於activity中的setContentView() 22 */ 23 @Nullable 24 @Override 25 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 26 View view = inflater.inflate(R.layout.fragment_a,container,false); 27 return view; 28 } 29 30 /** 31 * 當View創建完成之后回調該方法 32 */ 33 @Override 34 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 35 super.onViewCreated(view, savedInstanceState); 36 37 mTvTitle = view.findViewById(R.id.tv_title); 38 } 39 40 }
BFragment
1 package com.example.fragmentdemo; 2 3 import android.os.Bundle; 4 import android.view.LayoutInflater; 5 import android.view.View; 6 import android.view.ViewGroup; 7 import android.widget.TextView; 8 9 import androidx.annotation.NonNull; 10 import androidx.annotation.Nullable; 11 import androidx.fragment.app.Fragment; 12 13 public class BFragment extends Fragment { 14 15 private TextView mTvTitle; 16 17 /** 18 * 返回一個視圖文件,相當於activity中的setContentView() 19 */ 20 @Nullable 21 @Override 22 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 23 View view = inflater.inflate(R.layout.fragment_b,container,false); 24 return view; 25 } 26 27 /** 28 * 當View創建完成之后回調該方法 29 */ 30 @Override 31 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 32 super.onViewCreated(view, savedInstanceState); 33 34 mTvTitle = view.findViewById(R.id.tv_title); 35 } 36 }
(二)
-
Fragment中getActivity()為null的問題:當手機應用長期位於后台被回收后,當里面一些異步任務完成后回來getActivity時就為null
-
1 package com.example.fragmentdemo; 2 3 import android.app.Activity; 4 import android.content.Context; 5 import android.os.Bundle; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 import android.widget.TextView; 10 11 import androidx.annotation.NonNull; 12 import androidx.annotation.Nullable; 13 import androidx.fragment.app.Fragment; 14 15 public class AFragment extends Fragment { 16 17 private TextView mTvTitle; 18 private Activity mActivity; 19 20 /** 21 * 返回一個視圖文件,相當於activity中的setContentView() 22 */ 23 @Nullable 24 @Override 25 public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 26 View view = inflater.inflate(R.layout.fragment_a,container,false); 27 return view; 28 } 29 30 /** 31 * 當View創建完成之后回調該方法 32 */ 33 @Override 34 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 35 super.onViewCreated(view, savedInstanceState); 36 37 mTvTitle = view.findViewById(R.id.tv_title); 38 if(getActivity() != null){ //判斷當前activity是否為null 39 40 }else{ 41 42 } 43 } 44 45 /** 46 * 當Fragment重建或者Fragment與Activity重新建立關系時運行這個方法 47 * @param context 48 */ 49 @Override 50 public void onAttach(Context context) { 51 super.onAttach(context); 52 mActivity = (Activity)context; 53 } 54 55 56 /** 57 * 當activity為null時必然運行了這個方法,就是Fragment與Activity脫離關系 58 */ 59 @Override 60 public void onDetach() { 61 super.onDetach(); 62 } 63 64 /** 65 * Fragment回收 66 */ 67 @Override 68 public void onDestroy() { 69 super.onDestroy(); 70 // 取消異步任務 71 } 72 }
-
-
向Fragment傳遞參數
1 //ContainerActivity: 2 3 aFragment = AFragment.newInstance("我是參數");//傳遞參數給Fragment
1 //AFragment: 2 3 4 /** 5 *傳參 6 */ 7 public static AFragment newInstance(String title){ 8 AFragment fragment = new AFragment(); 9 Bundle bundle = new Bundle(); 10 bundle.putString("title",title); 11 fragment.setArguments(bundle); //將bundle傳入fragment;即便fragment重構,setArguments()方法也會運用反射機制將title重新放入fragment 12 return fragment; 13 } 14 15 16 17 /** 18 * 當View創建完成之后回調該方法 19 */ 20 @Override 21 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 22 super.onViewCreated(view, savedInstanceState); 23 // if(getActivity() != null){ //判斷當前activity是否為null 24 // }else{} 25 mTvTitle = view.findViewById(R.id.tv_title); 26 if(getArguments() != null){ 27 mTvTitle.setText(getArguments().getString("title")); 28 } 29 }
(三)
-
Fragment回退棧
1 AFragment: 2 3 mBtnChange = view.findViewById(R.id.btn_change); 4 mBtnReset = view.findViewById(R.id.btn_reset); 5 mBtnChange.setOnClickListener(new View.OnClickListener() { 6 @Override 7 public void onClick(View v) { 8 if (bFragment == null) { 9 bFragment = new BFragment(); 10 } 11 Fragment fragment = getFragmentManager().findFragmentByTag("a"); 12 if (fragment != null) { 13 // 隱藏aFragment,再添加bFragment 14 getFragmentManager().beginTransaction().hide(fragment).add(R.id.fl_container, bFragment).addToBackStack(null).commit(); 15 } else { 16 // 在commitNowAllowingStateLoss()方法之前加addToBackStack(null)將AFragment添加到回退棧里面,這樣跳到BFragment再按返回鍵時,返回到AFragment,而不是MainActivity 17 // replace可以理解為先remove再add,導致前一個fragment的視圖沒有被保存下來,雖然重新創建fragment視圖了,但其視圖內容也被重新創建了 18 getFragmentManager().beginTransaction().replace(R.id.fl_container, bFragment).addToBackStack(null).commit(); 19 } 20 } 21 });
(四)
-
Fragment和Activity的通信
- 方法一:
1 AFragment 2 3 mBtnMessage.setOnClickListener(new View.OnClickListener() { 4 @Override 5 public void onClick(View v) { 6 // 通過getActivity()獲得Activity,然后將其轉換成ContainerActivity,調用它的setData()方法 7 // 該方法能夠向Activity傳參,但不推薦 8 ((ContainerActivity)getActivity()).setData("你好"); //方法一 9 } 10 });
1 ContainerActivity 2 3 public void setData(String text){ 4 mTvTitle.setText(text); 5 }
這個方法可行但不推薦使用
-
方法二:在activity中實現fagment中聲明的接口,通過回調接口來實現數據的傳遞
1 AFragment 2 3 4 /** 5 * 接口 6 */ 7 public interface IOnMessageClick{ 8 void onClick(String text); 9 } 10 11 /** 12 * 當Fragment重建或者Fragment與Activity重新建立關系時運行這個方法 13 * 14 * @param context 15 */ 16 @Override 17 public void onAttach(Context context) { 18 super.onAttach(context); 19 // mActivity = (Activity)context; 20 try{ 21 listener = (IOnMessageClick) context; 22 } catch (ClassCastException e) { 23 throw new ClassCastException("Activity 必須實現IOnMessageClick接口"); 24 } 25 26 } 27 28 mBtnMessage.setOnClickListener(new View.OnClickListener() { 29 @Override 30 public void onClick(View v) { 31 // 通過getActivity()獲得Activity,然后將其轉換成ContainerActivity,調用它的setData()方法 32 // 該方法能夠向Activity傳參,但不推薦 33 // ((ContainerActivity)getActivity()).setData("你好"); //方法一 34 listener.onClick("你好"); 35 } 36 });
1 ContainerActivity 2 3 4 @Override 5 public void onClick(String text) { 6 mTvTitle.setText(text); 7 }