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

 

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

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

当下一个activity关闭时传值给上一个activity,主要用得到startActivityForResult和onActivityResult方法。
 

oneActivity //按钮的点击事件
public void addClick(View v){

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

//当开启的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){

}
}

}  

nextActivity

//吧数据返回给调用者  
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);
        }

 

 

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值