android中activity与fragment之间通信原理以及例题演示

android中activity与fragment之间通信原理以及例题演示

效果图
gif

首先,如果你想在android3.0及以下版本使用fragment,你必须引用android-support-v4.jar这个包

然后你写的activity不能再继承自Activity类了,而是要继承android.support.v4.app.FragmentActivity,一些其他的父类
也有相应的变化.

由于在android的实现机制中fragment和activity会被分别实例化为两个不相干的对象,他们之间的联系由activity的
一个成员对象SupportFragmentManager来维护.fragment实例化后会到activity中的SupportFragmentManager
去注册一下,这个动作封装在fragment对象的onAttach中,所以你可以在fragment中声明一些回调接口,当fragment
调用onAttach时,将这些回调接口实例化,这样fragment就能调用各个activity的成员函数了,当然activity必须implements
这些接口,否则会报ClassCastError异常!

fragment和activity的回调机制又是OOP的一次完美演绎!

下面通过一个例子来说明:

我把Activity的UI分为两个部分,左边和右边,左边用来放置点击的按钮(LeftFragment)
右边用来放置对应点击后显示的信息(RightFragment).

Activity的布局layout文件:main.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="horizontal"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/left_layout"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:orientation="vertical"
        />

    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="8"
        android:orientation="vertical"/>

</LinearLayout>
LeftFragment的布局layout:fragment_left.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="horizontal"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/left_layout"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="2"
        android:orientation="vertical"
        />

    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="8"
        android:orientation="vertical"/>

</LinearLayout>
RightFragment的布局layout:fragment_right.xml
  • 这里需要说明一下 用约束布局ConstraintLayout是为了屏幕适配 如果用其他的布局 会影响TextView的文字显示
  • 简单点说就是每行文字的宽度对不齐!
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/right_show_message"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/holo_blue_dark"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

以上是两个fragment和一个Activity的布局文件,下面来看他们的java文件

MainActivity:
public class MainActivity extends AppCompatActivity implements LeftFragment.MyListener {

    /**
     * 得到RightFragment中显示信息的控件
     */
    private TextView showMessageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("TAG", "Activity--->onCreate");

        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction ft = manager.beginTransaction();
        // 动态增加Fragment
        RightFragment rightFragment = new RightFragment();
        LeftFragment leftFragment = new LeftFragment();
        ft.add(R.id.left_layout, leftFragment, "leftFragment");
        ft.add(R.id.right_layout, rightFragment, "rightFragment");
        ft.commit();
    }

    /**
     * 实现MyListener,当LeftFragment中点击第一页的时候,让RightFragment显示第一页信息
     * 同理当点击第二页的时候,RightFragment显示第二页信息
     *
     * @param index 显示的页数
     */
    public void showMessage(int index) {
        if (index == 1) {
            showMessageView.setText(R.string.first_page);
        }
        if (index == 2) {
            showMessageView.setText(R.string.second_page);
        }
        if (index == 3) {
            showMessageView.setText(R.string.third_page);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e("TAG", "Activity--->onResume");
        showMessageView = findViewById(R.id.right_show_message);
    }
}
LeftFragment:
public class LeftFragment extends Fragment {

    private MyListener myListener;
    private Button firstButton;
    private Button secondButton;
    private Button thirdButton;

    /**
     * Fragment第一次属于Activity时调用,在onCreate之前调用
     *
     * @param context
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.e("TAG", "LeftFragment--->onAttach");

        myListener = (MyListener) context;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        Log.e("TAG", "LeftFragment--->onCreate");
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, 
    @Nullable Bundle savedInstanceState) {
        Log.e("TAG", "LeftFragment--->onCreateView");
        return inflater.inflate(R.layout.fragment_left, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e("TAG", "LeftFragment--->onActivityCreated");

    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e("TAG", "LeftFragment--->onResume");


        firstButton = getActivity().findViewById(R.id.first_button);
        secondButton = getActivity().findViewById(R.id.second_button);
        thirdButton = getActivity().findViewById(R.id.third_button);

        MyButtonClickListener clickListener = new MyButtonClickListener();
        firstButton.setOnClickListener(clickListener);
        secondButton.setOnClickListener(clickListener);
        thirdButton.setOnClickListener(clickListener);
    }

    /**
     * Activity要实现这个接口,这样Fragment和Activity就可以共享事件触发的资源了
     */
    public interface MyListener {
        void showMessage(int index);
    }

    /**
     * 按钮键的监听
     */
    class MyButtonClickListener implements View.OnClickListener {

        @Override
        public void onClick(View view) {
            Button button = (Button) view;
            if (button == firstButton) {
                myListener.showMessage(1);
            }
            if (button == secondButton) {
                myListener.showMessage(2);
            }
            if (button == thirdButton) {
                myListener.showMessage(3);
            }
        }
    }
}
RightFragment:
public class RightFragment extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        Log.e("TAG", "RightFragment--->onCreate");
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
     @Nullable Bundle savedInstanceState) {
        Log.e("TAG", "RightFragment--->onCreateView");
        return inflater.inflate(R.layout.fragment_right, container, false);
    }
}
注意:

Fragment的生命周期和Activity生命周期之间的关系。在Activity里动态生成Fragment,首先是Activity调用onCreate()
方法但是这时候还没有加载到Fragment里的组件,当Fragment调用其onCreateView()方法后,Activity才能得到
Fragment中的组件
生命周期

这里最关键的就是Fragment要有一个接口和这个接口的引用,而这个接口需要Activity去实现它。当Fragment调用onAttach(Context context)方法的时候,将这个activity传递给这个接口引用,这样,就可以和Activity进行交互了.

猜你喜欢

转载自blog.csdn.net/Life_s/article/details/80943320