美文网首页
Activity&Fragment数据交换

Activity&Fragment数据交换

作者: whd_Alive | 来源:发表于2018-03-23 14:26 被阅读0次

    谨以文章记录学习历程,如有错误还请指明。

    前言

    此文将解决两个实际问题:

    • Activity如何传递数据到Fragment
    • Fragment如何传递数据到Activity

    ActivityActivity传递数据可通过将数据保存在Intent对象中,发送方调用Intent.putExtra(),接收方调用getIntent().getXxx(getInt,getString,getBoolean等)来获得数据。

    至于FragmentFragment传递数据,其实也就是Fragment1获取宿主Activity引用,继而传递数据给Fragment2。在解决上述两个问题之后,相信你们就知道如何处理了。


    Activity向Fragment传递数据

    1. 在Activity中,通过FragmentManager.findFragmentById(R.id.fragment_id)方法获取相应fragment的实例,继而调用fragment的相关方法传递数据。

    该方式有个显著的问题,这会将这个fragment和其宿主activity紧紧绑定在一起,我们知道,Fragment的引入就是为了更加灵活的使用UI,显然这丧失了灵活性,因此我们通常采取以下的第2种方式。

    1. Bundle作为媒介传递数据:
      宿主Activity创建Fragment时调用Fragment.setArguments(bundle)方法。
      Fragment中通过调用Fragment.getArguments()方法获取包含数据的bundle。
      好处在于:实现了FragmentActivity解耦

    话不多说,直接上Demo:

    • MainActivity.java
    public class MainActivity extends AppCompatActivity {
    
        //静态变量存储key,防止多处使用时输错
        public static final String KEY = "key";
    
        private Button mButton;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //发送按钮初始化并设置点击事件
                    mButton = findViewById(R.id.button);
                    mButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            //获取FragmentManager
                            FragmentManager fragmentManager = getSupportFragmentManager();
    
                            //获取FragmentTransaction
                            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
                            //实例化要添加的fragment
                            MyFragment fragment = new MyFragment();
    
                            //创建Bundle对象
                            Bundle args = new Bundle();
    
                            //添加数据
                    args.putString(KEY,"This is a message from Activity");
    
                    //将Bundle对象设置到fragment中
                    fragment.setArguments(args);
    
                    //动态添加fragment
                    fragmentTransaction.add(R.id.fragment_container,fragment).commit();
    
                }
            });
        }
    }
    
    • MyFragment.java
    public class MyFragment extends Fragment {
    
        private TextView mTextView;
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            //填充布局
            View view = inflater.inflate(R.layout.fragment,container,false);
            mTextView = view.findViewById(R.id.fragment_text);
    
            //获取Activity传递过来的bundle对象
            Bundle bundle = getArguments();
    
            //获取某一值
            String message = bundle.getString(MainActivity.KEY);
    
            //显示传递值
            mTextView.setText(message);
            return view;
        }
    }
    
    • activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center|top"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="This is an Activity"
            />
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="20dp"
            android:text="Send Message"/>
        <FrameLayout
            android:layout_gravity="center"
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    
    </LinearLayout>
    
    
    • fragment.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:background="#a90765">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="I'm a fragment. And I receive a message that is: "/>
        <TextView
            android:id="@+id/fragment_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="40dp"
            android:gravity="center"/>
    
    </LinearLayout>
    

    结果展示:

    点击button传递数据前
    点击button传递数据后

    至此,讲解完如何由Activity向Fragment传递数据


    Fragment向Activity传递数据

    有以下几种方式:

    • 直接在Fragment调用getActivity(),获取到关联的活动实例,继而通过该实例调用Activity中的方法,以此传递数据。

    显然这和前面提到的Activity向Fragment传递数据的第1种方法有同样的问题,都会是二者绑定到一起,失去灵活性。因此该方法基本弃用。

    • 通过接口回调的方式
      把实现了某一接口的类所创建的对象的引用 赋给 声明的接口变量(实际上为转型),通过该接口变量 调用 该实现类对象的实现的接口方法。
    // 声明的回调接口变量
    Callback callback;
    
    //实现了Callback接口的类(MyActivity)所创建的对象的引用 赋给 声明的回调接口变量(callback)
    callback = new MyActivity();
    
    // 通过该接口变量(callback)调用 该实现类对象(MyActivity)实现的接口方法(initialize())
    callback.initialize();
    

    不再多说,上Demo:

    • 回调接口ICallBack
    public interface ICallback {
        //该接口只有一个方法,用来传递一段字符串
        void getMessage(String message);
        
    }
    
    • MainActivity.java
    public class MainActivity extends AppCompatActivity implements ICallback {
    
        private TextView mTextView;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mTextView = findViewById(R.id.activity_text);
            
            //获取FragmentManager
            FragmentManager fragmentManager = getSupportFragmentManager();
    
            //获取FragmentTransaction
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
            //实例化要添加的fragment
            MyFragment fragment = new MyFragment();
    
    
            //动态添加fragment
            fragmentTransaction.add(R.id.fragment_container,fragment).commit();
    
        }
        
        //实现接口方法,收到fragment传递过来的字符串后,更新TextView
        @Override
        public void getMessage(String message) {
            mTextView.setText(message);
        }
    }
    
    • MyFragment.java
    public class MyFragment extends Fragment {
    
        //声明一个接口变量
        private ICallback mCallback;
    
        private Button mButton;
    
        //将关联的Activity的引用 赋给 声明的接口变量(也即转型)
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            mCallback = (ICallback) context;
        }
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment,container,false);
            //button的初始化和点击事件
            mButton = view.findViewById(R.id.button);
            mButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //通过接口变量调用实现类中实现的接口方法,传递一串字符串
                    mCallback.getMessage("Message: This is a message from fragment");
                }
            });
            return view;
        }
    }
    
    • activity_main.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center|top"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="This is an Activity"
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/activity_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="20dp"
            android:text="Ready to receive message"/>
        <FrameLayout
            android:layout_gravity="center"
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    
    </LinearLayout>
    
    
    • fragment.xml
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:background="#a90765">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="I'm a fragment."/>
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="20dp"
            android:text="Send Message"/>
    
    </LinearLayout>
    

    结果展示

    点击button传递数据前
    点击button传递数据后

    至此,讲解完如何由Fragment向Activity传递数据

    Demo地址

    Github-whdalive:DemoActivity&Fragment


    总结

    • 本文尽可能详细的对Activity&Fragment通信做出介绍.
    • 笔者水平有限,如有错漏,欢迎指正。
    • 接下来我也会将所学的知识分享出来,有兴趣可以继续关注whd_Alive的Android开发笔记

    欢迎关注whd_Alive的简书

    • 不定期分享Android开发相关的技术干货,期待与你的交流,共勉。

    相关文章

      网友评论

          本文标题:Activity&Fragment数据交换

          本文链接:https://www.haomeiwen.com/subject/unatcftx.html