Android之Fragment


(一)

  • 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. 方法一:
     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     }

    這個方法可行但不推薦使用

  2. 方法二:在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     }

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM