android之fragment与fragment、activity与activity、fragment与activity之间的通信

Broadcast广播接受者可以实现所有通信;

-----------activity与activity之间的通信---------

  **********传给上一个activity*********
 //右侧+按钮的点击事件  
    public  void addClick(View v){

        Intent intent=new Intent(this,NextActivity.class);
//       startActivity(intent);  
        //如果下一个activity关闭时,要在当前activity获取下一个的数据,就要使用给下面的方法  
        startActivityForResult(intent,1);//1是requestCode,<span style="color:#ff0000;">用于标识请求的来源,在下面的onActivityResult中的requestCode可以区分业务</span>  
    }

    //当开启的activity关闭时调用,也就是下一个activity关闭时,在当前的activity调用  
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //requestCode 是从下一个activity关闭的时候传过来的  
        if(resultCode==10) {
//data就是下一个页面的意图  
            String name = data.getStringExtra("name");
            tx.setText(name);
        }else if(resultCode==20){

        }
    }

}  

//吧数据返回给调用者  
Intent intent=new Intent();  
            intent.putExtra("name","lambo");
                    setResult(10,intent);//<span style="color:#ff0000;">10是resultCode,用于标识返回结果的来源,在上一个activity中的onActivityResult中区分业务;当前activity关闭时,会传给上一个activity</span>  
                    //关闭当前activity,才会执行上一个activity中的方法onActivityResult(int requestCode, int resultCode, Intent data)  
                    finish(); 
 

*********传给下一个activity******

方法一:通过Intent传值给ACOne

Intent inten = new Intent(getContext(), ACOne.class);
inten.putExtra("f", "diyige");
startActivity(inten);/*跳转到下一个页面*/
方法二:用Bundle携带参数:
    public void OpenNew(View v){
        //新建一个显式意图,第一个参数为当前Activity类对象,第二个参数为你要打开的Activity类
        Intent intent =new Intent(MainActivity.this,MainActivity2.class);

        //用Bundle携带数据
        Bundle bundle=new Bundle();
        //传递name参数为tinyphp
        bundle.putString("name", "tinyphp");
        intent.putExtras(bundle);

        startActivity(intent);
    }

  
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.newtest);

        //新页面接收数据
        Bundle bundle = this.getIntent().getExtras();
        //接收name值
        String name = bundle.getString("name");
        Log.i("获取到的name值为",name);
        } 

------------fragment与fragment之间的通信---------

public class Fragment1 extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v=inflater.inflate(R.layout.fragment1,null);
        // 给fragment上的按钮添加点击事件  
        v.findViewById(R.id.btn_change).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//拿到frgment---fragment之间的通信  
                Fragment2 f2= (Fragment2) getActivity().getFragmentManager().findFragmentByTag("two");//two是fragment2的tag, 切换fragmentbeginTracsaction.replace(R.id.lltwo,new Fragment2(),"two");中two是tag 
 
                f2.changeStr("我要改变世界");

            }
        });

        return v;
    }
}

_________________fragment与activity之间的通信__-----------

------activity传值给fragment-------

方法一:在activity中建一个bundle,把要传的值存入bundle,然后通过fragment的setArguments(bundle)传到fragment,在fragment中,用getArguments接收,
        
        activity中:

        FragmentTransaction ft=fm.beginTransaction();
        OneFragment oneFragment=new OneFragment();
        ft.replace(R.id.frame,oneFragment,"f1");
        Bundle bundle=new Bundle();
        bundle.putString("one","要传的值");
        oneFragment.setArguments(bundle);
        ft.commit();

        OneFragment中:
        Bundle bundle=getArguments();
        String s=bundle.getString("one");

方法二:

可以看到Fragment比Activity多了几个额外的生命周期回调方法:
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用

注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,



在fragmentOne中:

public class FragmentOne extends Fragment {

    private Button btn;
    private TextView text;
    private String str;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v=inflater.inflate(R.layout.fragmentone,null);
        // 给fragment上的按钮添加点击事件
        text = v.findViewById(R.id.tv_fragmentone);
        btn = v.findViewById(R.id.getImgae);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        text.setText(str);
//        return inflater.inflate(R.layout.fragmentone,container,false);
        return v;
    }


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        str = ((MainActivity)context).toFragmentone();
        Log.e("ss",str);

    }
}

在MainActivity中:

//给FragmentOne传值
    public  String toFragmentone(){

        return  "fragmentone";
    }

-----fragment传值给activity----

******通过在fragment中实现接口的方式,Fragment向Activity传值的步骤 接口回调传递(5部曲)

1.fragment中准备回调接口 接口中声明传值的回调方法

  • 2.在fragment中定义属性private MyListener myListener

  • 3.重写fragment中的onAttach()方法:listener = (MyLisener)getActivity();

  • 4.fragment触发事件时回传值

  • 5.Activity中实现回调接口 重写回调方法获取回传的值并显示

在fragment中:
import android.content.Context;
public class FragmentOne extends Fragment {

    private Button btn;
    private TextView text;
    private String str;
//    private MainActivity ac;
    private MyListener ac;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v=inflater.inflate(R.layout.fragmentone,null);
        // 给fragment上的按钮添加点击事件
        text = v.findViewById(R.id.tv_fragmentone);
        btn = v.findViewById(R.id.getImgae);
btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //通过调用在activity中实现的接口方法,吧数据传给Mainactivity
       ac.sendContent("dddd");

    }
});
//        return inflater.inflate(R.layout.fragmentone,container,false);
        return v;
    }

//activity和fragment联系时候调用,fragment必须依赖activty
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
//获取实现接口的activity
     ac = (MyListener) getActivity();//或者ac=(MainActivity) context;

    }


    //①定义回调接口
    public interface MyListener{
        public void sendContent(String info);
    }

}
在MainActivity中:
import com.example.wofu.aichi010.Fragment.FragmentOne.MyListener;//fragmentOne中的接口

public class MainActivity extends BaseActivity implements RadioGroup.OnCheckedChangeListener,MyListener{
//fragmentOne中的接口,在这实现,以实现fragmentOne传值Mainactivity
    public void sendContent(String info) {
        if (info!=null && !"".equals(info)) {
            Log.e("sss",info);
        }else {

        }
    }


}

**********EventBus实现fragment向Activity传值**********

参考:https://www.jianshu.com/p/acfe78296bb5

https://blog.csdn.net/bskfnvjtlyzmv867/article/details/71480647

EventBus是一款Android下的发布/订阅事件总线机制。可以代替Intent、Handler、Broadcast等在Fragment、Activity之间传递消息。
优点:开销小,代码优雅。将发送者和接受者解耦。

*****添加依赖 implimentation 'org.greenrobot:eventbus:3.0.0'
 ******EventBus的三要素
        Event:事件,可以是任意类型的对象。
        Subscriber:事件订阅者,在EventBus3.0之前消息处理的方法只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,他们分别代表四种线程模型。而在EventBus3.0之后,事件处理的方法可以随便取名,但是需要添加一个注解@Subscribe,并且要指定线程模型(默认为POSTING)。
        Publisher:事件发布者,可以在任意线程任意位置发送事件,直接调用EventBus的post(Object)方法。可以自己实例化EventBus对象,但一般使用EventBus.getDefault()就好了,根据post函数参数的类型,会自动调用订阅相应类型事件的函数。
       ******** EventBus的四种线程模型(ThreadMode)
        POSTING(默认):如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起应用程序无响应(ANR)。
        MAIN:事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
        BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
        ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。
普通的方法是 先注册(register),再post,才能接受到事件;如果你使用postSticky发送事件,那么可以不需要先注册,也能接受到事件,也就是一个延迟注册的过程。粘性事件就是为了解决这个问题,通过 postSticky 发送粘性事件,这个事件不会只被消费一次就消失,而是一直存在系统中,直到被 removeStickyEvent 删除掉。那么只要订阅了该粘性事件的所有方法,只要被register 的时候,就会被检测到,并且执行。订阅的方法需要添加 sticky = true 属性。该广播发送后,会保存在内存中,如果后来有注册的Receiver与之匹配,那么该Receiver便会接收到该广播。那么粘性事件同理,在注册之前便把事件发生出去,等到注册之后便会收到最近发送的粘性事件(必须匹配)。注意:只会接收到最近发送的一次粘性事件,之前的会接受不到;

****举例*****

普通事件:

//注册成为订阅者
        EventBus.getDefault().register(this);
//订阅方法,当接收到事件的时候,会调用该方法
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent messageEvent){
    textView.setText(messageEvent.getMessage());
}


@Override
protected void onDestroy() {
    super.onDestroy();
    //解除注册
    EventBus.getDefault().unregister(this);
}

在另一个activity或者fragment中post事件:

与观察者模式对应的,当有事件发生,需要通知观察者的时候,被观察者会调用notifyObservers()方法来通知所有已经注册的观察者,在EventBus中,对观察者模式底层进行了封装,我们只需要调用以下代码就能把事件发送出去:

EventBus.getDefault().post(new MessageEvent("发送的消息"));

@Subscribe注解,该注解标识了当前方法为订阅方法;该注解内部有三个成员,分别是threadMode、sticky、priority。threadMode代表订阅方法所运行的线程,sticky代表是否是粘性事件,priority代表优先级。给这个三个成员赋不同的值,能使得订阅方法有着不同的效果。

*******ThreadMode是一个枚举类型,有着以下几个类型:
POSTING:表示订阅方法运行在发送事件的线程。
 MAIN:表示订阅方法运行在UI线程,由于UI线程不能阻塞,因此当使用MAIN的时候,订阅方法不应该耗时过长。
 BACKGROUND:表示订阅方法运行在后台线程,如果发送的事件线程不是UI线程,那么就使用该线程;如果发送事件的线程是UI线程,那么新建一个后台线程来调用订阅方法。
 ASYNC:订阅方法与发送事件始终不在同一个线程,即订阅方法始终会使用新的线程来运行。
  ThreadMode默认是使用POSTING的,如果需要更改设置,可以在添加注解的时候同时为threadMode赋值。

        *****.priority 优先级

        设置该优先级的目的是,当一个事件有多个订阅者的时候,优先级高的会优先接收到事件。

粘性事件:

注册粘性事件
EventBus.getDefault().register(this);

发送粘性事件:
 EventBus.getDefault().postSticky(new MessageEvent("发送粘性事件"));

接受粘性事件:
@Subscribe(sticky = true)
public void onEvent(MessageEvent messageEvent){
        Log.d("cylog","接受到了来自EventBus的事件:"+messageEvent.getMessage());
        }
取消注册
@Override
protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
        }



猜你喜欢

转载自blog.csdn.net/u011146511/article/details/80485362