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     }

     

posted @ 2019-11-06 19:20  似鱼  阅读(683)  评论(0编辑  收藏  举报