大厂Android面试秘籍:Activity 与 Fragment 交互(九)

Android 的 Activity 与 Fragment 交互模块深度剖析

本人掘金号,欢迎点击关注:掘金号地址

本人公众号,欢迎点击关注:公众号地址

一、引言

在 Android 开发中,Activity 和 Fragment 是两个至关重要的组件。Activity 作为 Android 应用的可视化界面容器,为用户提供了与应用交互的窗口;而 Fragment 则是 Activity 中的模块化组件,能够实现界面的灵活组合和复用。Activity 与 Fragment 之间的交互机制是 Android 开发中不可或缺的一部分,它使得开发者可以构建出更加复杂、灵活且富有交互性的应用界面。

本博客将从源码级别深入分析 Android 的 Activity 与 Fragment 交互模块,详细探讨它们之间各种交互方式的实现原理,帮助开发者更好地理解和运用这一重要机制。

二、Activity 与 Fragment 基础概念回顾

2.1 Activity 概述

Activity 是 Android 应用中最基本的组件之一,它代表了一个具有用户界面的单屏。每个 Activity 都有自己的生命周期,从创建、启动、暂停、恢复到销毁,开发者可以通过重写相应的生命周期方法来实现特定的逻辑。

以下是一个简单的 Activity 示例:

java

java 复制代码
import android.app.Activity;
import android.os.Bundle;

// 自定义 Activity 类,继承自 Activity
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 调用父类的 onCreate 方法
        super.onCreate(savedInstanceState);
        // 设置 Activity 的布局文件
        setContentView(R.layout.activity_main);
    }
}

在上述代码中,onCreate 方法是 Activity 生命周期中的一个重要方法,它在 Activity 首次创建时被调用。在该方法中,我们调用了 setContentView 方法来设置 Activity 的布局文件。

2.2 Fragment 概述

Fragment 是 Android 3.0(API 级别 11)引入的一个概念,它可以被看作是 Activity 中的一个子模块,有自己的生命周期和布局。Fragment 可以动态地添加、替换和移除,使得界面的管理更加灵活。

以下是一个简单的 Fragment 示例:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;

// 自定义 Fragment 类,继承自 Fragment
public class MyFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        return inflater.inflate(R.layout.fragment_my, container, false);
    }
}

在上述代码中,onCreateView 方法是 Fragment 生命周期中的一个重要方法,它在 Fragment 创建视图时被调用。在该方法中,我们使用 LayoutInflater 来加载 Fragment 的布局文件。

2.3 Activity 与 Fragment 的关系

Fragment 必须依赖于 Activity 而存在,它的生命周期受到 Activity 生命周期的影响。一个 Activity 可以包含多个 Fragment,通过 FragmentManager 来管理这些 Fragment。Fragment 可以与 Activity 进行交互,实现数据的传递和界面的更新。

三、Activity 向 Fragment 传递数据

3.1 使用 Bundle 传递数据

在 Activity 中创建 Fragment 时,可以通过 Bundle 对象来传递数据。Bundle 是一个键值对的集合,类似于 Map,可以存储各种基本数据类型和可序列化的对象。

以下是一个 Activity 向 Fragment 传递数据的示例:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;

// 自定义 Fragment 类,继承自 Fragment
public class DataReceiverFragment extends Fragment {
    private static final String ARG_DATA = "data";
    private String mData;

    // 静态工厂方法,用于创建 Fragment 实例并传递数据
    public static DataReceiverFragment newInstance(String data) {
        DataReceiverFragment fragment = new DataReceiverFragment();
        Bundle args = new Bundle();
        // 将数据存入 Bundle 中
        args.putString(ARG_DATA, data);
        // 将 Bundle 设置为 Fragment 的参数
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            // 从 Bundle 中获取数据
            mData = getArguments().getString(ARG_DATA);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        View view = inflater.inflate(R.layout.fragment_data_receiver, container, false);
        TextView textView = view.findViewById(R.id.textView);
        // 将获取到的数据显示在 TextView 上
        textView.setText(mData);
        return view;
    }
}

在 Activity 中使用该 Fragment 并传递数据:

java

java 复制代码
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;

// 自定义 Activity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建要传递的数据
        String data = "Hello from Activity!";
        // 创建 Fragment 实例并传递数据
        DataReceiverFragment fragment = DataReceiverFragment.newInstance(data);
        // 获取 FragmentManager
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        // 将 Fragment 添加到布局中
        transaction.add(R.id.fragment_container, fragment);
        // 提交事务
        transaction.commit();
    }
}
3.1.1 源码分析

DataReceiverFragment 中,newInstance 方法是一个静态工厂方法,用于创建 DataReceiverFragment 的实例并传递数据。在该方法中,我们创建了一个 Bundle 对象,并将数据存入其中,然后调用 setArguments 方法将 Bundle 设置为 Fragment 的参数。

onCreate 方法中,我们通过 getArguments 方法获取之前设置的 Bundle,并从中取出数据。

MainActivity 中,我们创建了要传递的数据,并调用 DataReceiverFragmentnewInstance 方法创建 Fragment 实例。然后,我们获取 FragmentManager 并开始一个事务,将 Fragment 添加到布局中,最后提交事务。

3.2 通过接口回调传递数据

Activity 可以通过接口回调的方式向 Fragment 传递数据。具体步骤如下:

  1. 在 Fragment 中定义一个接口。

  2. 在 Activity 中实现该接口。

  3. 在 Fragment 中设置接口的实现对象。

  4. 在 Activity 中调用接口的方法传递数据。

以下是一个示例:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;

// 自定义 Fragment 类,继承自 Fragment
public class CallbackReceiverFragment extends Fragment {
    private OnDataReceivedListener mListener;
    private TextView mTextView;

    // 定义接口
    public interface OnDataReceivedListener {
        void onDataReceived(String data);
    }

    // 设置接口的实现对象
    public void setOnDataReceivedListener(OnDataReceivedListener listener) {
        mListener = listener;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        View view = inflater.inflate(R.layout.fragment_callback_receiver, container, false);
        mTextView = view.findViewById(R.id.textView);
        return view;
    }

    // 处理接收到的数据
    public void handleData(String data) {
        if (mTextView != null) {
            mTextView.setText(data);
        }
    }
}

在 Activity 中实现该接口并传递数据:

java

java 复制代码
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

// 自定义 Activity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity implements CallbackReceiverFragment.OnDataReceivedListener {
    private CallbackReceiverFragment mFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建 Fragment 实例
        mFragment = new CallbackReceiverFragment();
        // 设置接口的实现对象
        mFragment.setOnDataReceivedListener(this);
        // 获取 FragmentManager
        getSupportFragmentManager().beginTransaction()
               .add(R.id.fragment_container, mFragment)
               .commit();

        // 传递数据
        sendDataToFragment();
    }

    private void sendDataToFragment() {
        String data = "Hello from Activity via callback!";
        // 调用接口的方法传递数据
        onDataReceived(data);
    }

    @Override
    public void onDataReceived(String data) {
        // 调用 Fragment 的方法处理数据
        mFragment.handleData(data);
    }
}
3.2.1 源码分析

CallbackReceiverFragment 中,我们定义了一个 OnDataReceivedListener 接口,该接口包含一个 onDataReceived 方法,用于接收数据。

setOnDataReceivedListener 方法用于设置接口的实现对象。

handleData 方法用于处理接收到的数据,将数据显示在 TextView 上。

MainActivity 中,我们实现了 OnDataReceivedListener 接口,并在 onCreate 方法中创建了 CallbackReceiverFragment 实例,设置了接口的实现对象。

sendDataToFragment 方法用于创建要传递的数据,并调用 onDataReceived 方法传递数据。

onDataReceived 方法中,我们调用 CallbackReceiverFragmenthandleData 方法处理数据。

四、Fragment 向 Activity 传递数据

4.1 使用接口回调传递数据

Fragment 向 Activity 传递数据最常用的方式也是接口回调。具体步骤如下:

  1. 在 Fragment 中定义一个接口。

  2. 在 Activity 中实现该接口。

  3. 在 Fragment 中设置接口的实现对象。

  4. 在 Fragment 中调用接口的方法传递数据。

以下是一个示例:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.fragment.app.Fragment;

// 自定义 Fragment 类,继承自 Fragment
public class DataSenderFragment extends Fragment {
    private OnDataSendListener mListener;
    private Button mSendButton;

    // 定义接口
    public interface OnDataSendListener {
        void onDataSent(String data);
    }

    // 设置接口的实现对象
    public void setOnDataSendListener(OnDataSendListener listener) {
        mListener = listener;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        View view = inflater.inflate(R.layout.fragment_data_sender, container, false);
        mSendButton = view.findViewById(R.id.sendButton);
        // 为按钮设置点击事件监听器
        mSendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 传递数据
                sendDataToActivity();
            }
        });
        return view;
    }

    private void sendDataToActivity() {
        String data = "Hello from Fragment!";
        if (mListener != null) {
            // 调用接口的方法传递数据
            mListener.onDataSent(data);
        }
    }
}

在 Activity 中实现该接口并处理数据:

java

java 复制代码
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

// 自定义 Activity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity implements DataSenderFragment.OnDataSendListener {
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = findViewById(R.id.textView);
        // 创建 Fragment 实例
        DataSenderFragment fragment = new DataSenderFragment();
        // 设置接口的实现对象
        fragment.setOnDataSendListener(this);
        // 获取 FragmentManager
        getSupportFragmentManager().beginTransaction()
               .add(R.id.fragment_container, fragment)
               .commit();
    }

    @Override
    public void onDataSent(String data) {
        // 处理接收到的数据
        mTextView.setText(data);
    }
}
4.1.1 源码分析

DataSenderFragment 中,我们定义了一个 OnDataSendListener 接口,该接口包含一个 onDataSent 方法,用于传递数据。

setOnDataSendListener 方法用于设置接口的实现对象。

sendDataToActivity 方法用于创建要传递的数据,并调用接口的 onDataSent 方法传递数据。

MainActivity 中,我们实现了 OnDataSendListener 接口,并在 onCreate 方法中创建了 DataSenderFragment 实例,设置了接口的实现对象。

onDataSent 方法用于处理接收到的数据,将数据显示在 TextView 上。

4.2 通过 Activity 的公共方法传递数据

Fragment 还可以通过调用 Activity 的公共方法来传递数据。具体步骤如下:

  1. 在 Activity 中定义公共方法。

  2. 在 Fragment 中获取 Activity 的实例。

  3. 调用 Activity 的公共方法传递数据。

以下是一个示例:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.fragment.app.Fragment;

// 自定义 Fragment 类,继承自 Fragment
public class MethodCallSenderFragment extends Fragment {
    private Button mSendButton;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        View view = inflater.inflate(R.layout.fragment_method_call_sender, container, false);
        mSendButton = view.findViewById(R.id.sendButton);
        // 为按钮设置点击事件监听器
        mSendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 传递数据
                sendDataToActivity();
            }
        });
        return view;
    }

    private void sendDataToActivity() {
        String data = "Hello from Fragment via method call!";
        // 获取 Activity 的实例
        MainActivity activity = (MainActivity) getActivity();
        if (activity != null) {
            // 调用 Activity 的公共方法传递数据
            activity.receiveData(data);
        }
    }
}

在 Activity 中定义公共方法并处理数据:

java

java 复制代码
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

// 自定义 Activity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity {
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = findViewById(R.id.textView);
        // 创建 Fragment 实例
        MethodCallSenderFragment fragment = new MethodCallSenderFragment();
        // 获取 FragmentManager
        getSupportFragmentManager().beginTransaction()
               .add(R.id.fragment_container, fragment)
               .commit();
    }

    // 公共方法,用于接收数据
    public void receiveData(String data) {
        // 处理接收到的数据
        mTextView.setText(data);
    }
}
4.2.1 源码分析

MethodCallSenderFragment 中,sendDataToActivity 方法用于创建要传递的数据,并通过 getActivity 方法获取 Activity 的实例。

然后,我们将获取到的 Activity 实例强制转换为 MainActivity 类型,并调用其 receiveData 方法传递数据。

MainActivity 中,我们定义了一个公共方法 receiveData,用于接收数据并将其显示在 TextView 上。

五、Activity 与 Fragment 之间的事件交互

5.1 Activity 监听 Fragment 的事件

Activity 可以监听 Fragment 中的事件,例如按钮点击事件。通过接口回调的方式,Fragment 可以将事件传递给 Activity。

以下是一个示例:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.fragment.app.Fragment;

// 自定义 Fragment 类,继承自 Fragment
public class EventSenderFragment extends Fragment {
    private OnButtonClickListener mListener;
    private Button mButton;

    // 定义接口
    public interface OnButtonClickListener {
        void onButtonClicked();
    }

    // 设置接口的实现对象
    public void setOnButtonClickListener(OnButtonClickListener listener) {
        mListener = listener;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        View view = inflater.inflate(R.layout.fragment_event_sender, container, false);
        mButton = view.findViewById(R.id.button);
        // 为按钮设置点击事件监听器
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 触发事件
                if (mListener != null) {
                    mListener.onButtonClicked();
                }
            }
        });
        return view;
    }
}

在 Activity 中实现该接口并处理事件:

java

java 复制代码
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

// 自定义 Activity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity implements EventSenderFragment.OnButtonClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建 Fragment 实例
        EventSenderFragment fragment = new EventSenderFragment();
        // 设置接口的实现对象
        fragment.setOnButtonClickListener(this);
        // 获取 FragmentManager
        getSupportFragmentManager().beginTransaction()
               .add(R.id.fragment_container, fragment)
               .commit();
    }

    @Override
    public void onButtonClicked() {
        // 处理事件
        Toast.makeText(this, "Button in Fragment is clicked!", Toast.LENGTH_SHORT).show();
    }
}
5.1.1 源码分析

EventSenderFragment 中,我们定义了一个 OnButtonClickListener 接口,该接口包含一个 onButtonClicked 方法,用于处理按钮点击事件。

setOnButtonClickListener 方法用于设置接口的实现对象。

在按钮的点击事件监听器中,我们调用接口的 onButtonClicked 方法触发事件。

MainActivity 中,我们实现了 OnButtonClickListener 接口,并在 onCreate 方法中创建了 EventSenderFragment 实例,设置了接口的实现对象。

onButtonClicked 方法用于处理按钮点击事件,显示一个 Toast 消息。

5.2 Fragment 监听 Activity 的事件

Fragment 也可以监听 Activity 中的事件,例如 Activity 的菜单点击事件。通过在 Fragment 中重写 onActivityCreated 方法,获取 Activity 的菜单,并为菜单项设置点击事件监听器。

以下是一个示例:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.fragment.app.Fragment;

// 自定义 Fragment 类,继承自 Fragment
public class EventReceiverFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        return inflater.inflate(R.layout.fragment_event_receiver, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // 获取 Activity 的菜单
        Menu menu = getActivity().getMenuInflater().inflate(R.menu.main_menu, null);
        // 为菜单项设置点击事件监听器
        MenuItem item = menu.findItem(R.id.menu_item);
        item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                // 处理事件
                Toast.makeText(getActivity(), "Menu item in Activity is clicked!", Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }
}

在 Activity 中加载菜单:

java

java 复制代码
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;

// 自定义 Activity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建 Fragment 实例
        EventReceiverFragment fragment = new EventReceiverFragment();
        // 获取 FragmentManager
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        // 将 Fragment 添加到布局中
        transaction.add(R.id.fragment_container, fragment);
        // 提交事务
        transaction.commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // 加载菜单资源
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }
}
5.2.1 源码分析

EventReceiverFragment 中,onActivityCreated 方法在 Activity 创建完成后被调用。在该方法中,我们获取 Activity 的菜单,并为菜单项设置点击事件监听器。

在点击事件监听器中,我们处理菜单项的点击事件,显示一个 Toast 消息。

MainActivity 中,onCreateOptionsMenu 方法用于加载菜单资源。

六、使用 ViewModel 进行 Activity 与 Fragment 之间的数据共享

6.1 ViewModel 概述

ViewModel 是 Android Architecture Components 中的一个组件,它用于存储和管理与 UI 相关的数据,并且在配置更改(如屏幕旋转)时保持数据的一致性。ViewModel 可以在 Activity 和 Fragment 之间共享数据,避免了数据在 Activity 和 Fragment 之间的重复传递。

6.2 使用 ViewModel 共享数据的示例

以下是一个使用 ViewModel 进行 Activity 与 Fragment 之间数据共享的示例:

java

java 复制代码
import androidx.lifecycle.ViewModel;

// 自定义 ViewModel 类,继承自 ViewModel
public class SharedViewModel extends ViewModel {
    private String mData;

    // 获取数据
    public String getData() {
        return mData;
    }

    // 设置数据
    public void setData(String data) {
        mData = data;
    }
}

在 Activity 中使用 ViewModel 并设置数据:

java

java 复制代码
import android.os.Bundle;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;

// 自定义 Activity 类,继承自 AppCompatActivity
public class MainActivity extends AppCompatActivity {
    private SharedViewModel mViewModel;
    private Button mSetDataButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 获取 ViewModel 实例
        mViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
        mSetDataButton = findViewById(R.id.setDataButton);
        // 为按钮设置点击事件监听器
        mSetDataButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 设置数据
                mViewModel.setData("Hello from Activity via ViewModel!");
            }
        });
    }
}

在 Fragment 中使用 ViewModel 并获取数据:

java

java 复制代码
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;

// 自定义 Fragment 类,继承自 Fragment
public class DataReceiverViewModelFragment extends Fragment {
    private SharedViewModel mViewModel;
    private TextView mTextView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 加载 Fragment 的布局文件
        View view = inflater.inflate(R.layout.fragment_data_receiver_viewmodel, container, false);
        mTextView = view.findViewById(R.id.textView);
        // 获取 ViewModel 实例
        mViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
        // 观察数据的变化
        mViewModel.getData().observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String data) {
                // 处理数据的变化
                mTextView.setText(data);
            }
        });
        return view;
    }
}
6.2.1 源码分析

SharedViewModel 中,我们定义了一个 mData 变量,并提供了 getDatasetData 方法来获取和设置数据。

MainActivity 中,我们通过 ViewModelProvider 获取 SharedViewModel 的实例,并在按钮的点击事件监听器中调用 setData 方法设置数据。

DataReceiverViewModelFragment 中,我们同样通过 ViewModelProvider 获取 SharedViewModel 的实例,并使用 observe 方法观察数据的变化。当数据发生变化时,onChanged 方法会被调用,我们在该方法中更新 TextView 的文本。

七、Activity 与 Fragment 交互的生命周期影响

7.1 Activity 生命周期对 Fragment 的影响

Activity 的生命周期会直接影响 Fragment 的生命周期。当 Activity 进入不同的生命周期状态时,Fragment 也会相应地进入不同的生命周期状态。

例如,当 Activity 的 onCreate 方法被调用时,Fragment 的 onAttachonCreateonCreateView 方法会依次被调用。

以下是 Activity 和 Fragment 生命周期方法的调用顺序示例:

java

java 复制代码
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

// 自定义 Activity 类,继承自 FragmentActivity
public class LifecycleActivity extends FragmentActivity {
    private static final String TAG = "LifecycleActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lifecycle);
        Log.d(TAG, "Activity onCreate");

        // 创建 Fragment 实例
        LifecycleFragment fragment = new LifecycleFragment();
        // 获取 FragmentManager
        FragmentManager manager = getSupportFragmentManager();
        // 开始事务
        FragmentTransaction transaction = manager.beginTransaction();
        // 添加 Fragment
        transaction.add(R.id.fragment_container, fragment);
        // 提交事务
        transaction.commit();
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "Activity onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "Activity onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "Activity onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "Activity onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Activity onDestroy");
    }
}

// 自定义 Fragment 类,继承自 Fragment
public class LifecycleFragment extends Fragment {
    private static final String TAG = "LifecycleFragment";

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.d(TAG, "Fragment onAttach");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "Fragment onCreate");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d(TAG, "Fragment onCreateView");
        return inflater.inflate(R.layout.fragment_lifecycle, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "Fragment onActivityCreated");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "Fragment onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "Fragment onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, "Fragment onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "Fragment onStop");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d(TAG, "Fragment onDestroyView");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "Fragment onDestroy");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d(TAG, "Fragment onDetach");
    }
}
7.1.1 源码分析

LifecycleActivity 中,我们重写了 Activity 的生命周期方法,并在每个方法中打印日志。

onCreate 方法中,我们创建了 LifecycleFragment 实例,并将其添加到布局中。

LifecycleFragment 中,我们重写了 Fragment 的生命周期方法,并在每个方法中打印日志。

通过运行该示例,我们可以观察到 Activity 和 Fragment 生命周期方法的调用顺序。

7.2 Fragment 生命周期对 Activity 交互的影响

Fragment 的生命周期也会影响 Activity 与 Fragment 之间的交互。例如,在 Fragment 的 onDestroyView 方法中,视图已经被销毁,如果此时 Activity 尝试访问 Fragment 的视图,会导致空指针异常。

因此,在进行 Activity 与 Fragment 交互时,需要注意 Fragment 的生命周期状态,确保在合适的时机进行交互。

八、总结与展望

8.1 总结

通过对 Android 的 Activity 与 Fragment 交互模块的深入分析,我们了解了多种 Activity 与 Fragment 之间的交互方式,包括使用 Bundle 传递数据、接口回调、公共方法调用、ViewModel 数据共享等。

每种交互方式都有其适用场景和优缺点。使用 Bundle 传递数据简单直接,适用于在创建 Fragment 时传递静态数据;接口回调方式灵活,适用于传递事件和动态数据;公共方法调用方式直观,适用于 Fragment 直接调用 Activity 的方法;ViewModel 数据共享方式适用于在 Activity 和 Fragment 之间共享动态数据,并且可以在配置更改时保持数据的一致性。

同时,我们还分析了 Activity 和 Fragment 的生命周期对交互的影响,了解到在进行交互时需要注意生命周期状态,避免出现空指针异常等问题。

8.2 展望

随着 Android 开发技术的不断发展,Activity 与 Fragment 交互模块可能会有更多的优化和改进。例如,可能会出现更简洁、更高效的交互方式,或者对现有交互方式进行进一步的封装和简化。

在性能方面,可能会对交互过程中的数据传递和事件处理进行优化,减少不必要的内存开销和性能损耗。

在兼容性方面,会更好地支持不同版本的 Android 系统,确保开发者在不同的设备上都能稳定地使用 Activity 与 Fragment 交互功能。

此外,随着 Android 应用的复杂度不断增加,Activity 与 Fragment 交互模块可能会与其他组件和技术进行更深入的融合,为开发者提供更强大的开发工具和功能。

总之,Activity 与 Fragment 交互模块是 Android 开发中非常重要的一部分,深入理解和掌握其原理和使用方法,对于开发高质量的 Android 应用具有重要意义。开发者需要不断关注技术的发展,灵活运用各种交互方式,以满足不同的开发需求。

相关推荐
QING6181 小时前
详解:Kotlin 类的继承与方法重载
android·kotlin·app
QING6181 小时前
Kotlin 伴生对象(Companion Object)详解 —— 使用指南
android·kotlin·app
一一Null1 小时前
Android studio 动态布局
android·java·android studio
软件测试曦曦8 小时前
16:00开始面试,16:08就出来了,问的问题有点变态。。。
自动化测试·软件测试·功能测试·程序人生·面试·职场和发展
拉不动的猪8 小时前
设计模式之------策略模式
前端·javascript·面试
独行soc9 小时前
2025年常见渗透测试面试题-红队面试宝典下(题目+回答)
linux·运维·服务器·前端·面试·职场和发展·csrf
AD钙奶-lalala9 小时前
某车企面试备忘
android
uhakadotcom9 小时前
Google Earth Engine 机器学习入门:基础知识与实用示例详解
前端·javascript·面试
我爱拉臭臭10 小时前
kotlin音乐app之自定义点击缩放组件Shrink Layout
android·java·kotlin
uhakadotcom10 小时前
Amazon GameLift 入门指南:六大核心组件详解与实用示例
后端·面试·github