Activity 与 Activity 、Fragment、Service间的通信
1. Activity->Activity
-
Intent/Bundle
这种方式多用于Activity之间传递数据。示例代码如下://首先创建一个Bundle对象 Bundle bundle = new Bundle(); bundle.putString("data_string","数据"); bundle.putInt("data_int",10); bundle.putChar("da_char",'a'); //然后创建一个Intent对象 Intent intent = new Intent(FirstActivity.this,SecondActivity.class); intent.putExtras(bundle); startActivity(intent);
-
类静态变量
在Activity内部定义静态的变量,这种方式见于少量的数据通信,如果数据过多,还是使用第一种方式。示例代码如下:public class FirstActivity extends AppCompatActivity { //声明为静态 static boolean isFlag = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); //首先创建一个Bundle对象 Bundle bundle = new Bundle(); bundle.putString("data_string","数据"); bundle.putInt("data_int",10); bundle.putChar("da_char",'a'); //然后创建一个Intent对象 Intent intent = new Intent(FirstActivity.this,SecondActivity.class); intent.putExtras(bundle); startActivity(intent); } }
-
全局变量
定义一批静态变量,Activity之间通信都可以访问这个类里面的静态变量,这就是全局变量。
2. Activity->Service
-
绑定服务的方式,利用 ServiceConnection 这个接口。首先我们需要在要绑定的服务中声明一个Binder类
public class MyService1 extends Service { public String data = ""; public MyService1() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return new Binder(); } public class Binder extends android.os.Binder{ public void sendData(String data){ MyService1.this.data = data; } } }
然后让Activity实现 ServiceConnection 这个接口,并且在 onServiceConnected 方法中获取到 Service 提供给 Activity 的 Binder 实例对象,通过这个对象我们就可以与Service进行通信可以通过上述代码的Binder类中的sendData()方法进行通信。
public class ServiceBindActivity extends AppCompatActivity implements ServiceConnection,View.OnClickListener { private Button bt0,bt1,bt2; public MyService1.Binder binder = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_service_bind); bt0 = findViewById(R.id.bt0); bt1 = findViewById(R.id.bt1); bt2 = findViewById(R.id.bt2); bt0.setOnClickListener(this); bt1.setOnClickListener(this); bt2.setOnClickListener(this); } @Override protected void onDestroy() { super.onDestroy(); unbindService(this); } //这个是服务绑定的时候调用 @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = (MyService1.Binder) iBinder; } //这个是服务解绑的时候调用 @Override public void onServiceDisconnected(ComponentName componentName) { } @Override public void onClick(View view) { switch (view.getId()){ case R.id.bt0: //绑定服务 Intent intent = new Intent(ServiceBindActivity.this,MyService1.class); bindService(intent,this, Context.BIND_AUTO_CREATE); break; case R.id.bt1: //通过binder对象来和Service进行通信 if(binder != null) binder.sendData("bt1"); break; case R.id.bt2: //通过binder对象来和Service进行通信 if(binder != null) binder.sendData("bt2"); break; } } }
-
Intent
这种方式很简单,我们在启动和停止Service时所调用的方法都需要传入一个Intent实例对象,通过这个传入的Intent对象,我们就可以与Service进行通信。
Activity代码是这样的:public class ServiceStartActivity extends AppCompatActivity implements View.OnClickListener { private Button bt0,bt1; private Intent intent ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_service_start); intent = new Intent(this, MyService2.class); bt0 = findViewById(R.id.bt0); bt1 = findViewById(R.id.bt1); bt0.setOnClickListener(this); bt1.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.bt0: //开启服务并且传递数据 intent.putExtra("data_stirng","string数据"); startActivity(intent); break; case R.id.bt1: //结束服务 stopService(intent); break; } } } //Service中的代码: public class MyService2 extends Service { public String data = ""; public MyService2() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { //得到Activity传递过来的数据 data = intent.getStringExtra("data_string"); return super.onStartCommand(intent, flags, startId); } }
这种通信方式的缺点:只能传递少量的数据。
-
CallBack + Handler,监听服务的进程变化
//Service中: public class MyService3 extends Service { //在Service中如果要进行耗时任务,可以通过CallBack接口提供的方法与Activity进行通信 public Callback callback; public MyService3() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return new Binder(); } public void setCallBack(CallBack callBack){ this.callback = callback; } public Callback getCallback() { return callback; } public interface CallBack{ void onDataChange(String data); } public class Binder extends android.os.Binder{ public MyService3 getMyService3(){ return MyService3.this; } } } //Activity中: public class ServiceBind2Activity extends AppCompatActivity implements ServiceConnection{ public MyService3.Binder binder = null; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); Bundle bundle = msg.getData(); String data_string = bundle.getString("data_string"); //接下来就是更新ui } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_service_bind2); } @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = (MyService3.Binder) iBinder; binder.getMyService3().setCallBack(new MyService3.CallBack() { //此方法提供给MyService3在子线程中调用 @Override public void onDataChange(String data) { Message message = new Message(); Bundle bundle = new Bundle(); bundle.putString("data_string","String数据"); message.setData(bundle); //通过Handler进行异步通信,不过耗时操作放在MyService3中 handler.sendMessage(message); } }); } @Override public void onServiceDisconnected(ComponentName componentName) { } }
当ServiceBind2Activity去绑定服务MyService3的时候,那么在Activity中的onServiceConnected()方法被调用,此时位于MySerivce3的CallBack接口引用被实例化,并且onDataChange()方法被实现,可以看到里面是一段Handler通信的代码,;
这个方法是为MyService3做耗时操作调用的,没有在MyService3 中写耗时操作的代码,
这种通信方式的好处:监听服务的进程变化。
3. Activity->Fragment
-
Bundle
在创建Fragment实例的时候,调用方法 setArguments 将一个 Bundle 对象传递给 Fragment ,然后在 Fragment 中先去判断是否和当前 Activity 绑定上了,如果绑定上了,就可以拿出这个 Bundle 中的数据啦。//在Activity中:首先创建一个Bundle对象 Bundle bundle = new Bundle(); bundle.putString("data_string","数据"); bundle.putInt("data_int",10); bundle.putChar("da_char",'a'); Fragment fragment = new MyFragment1(); fragment.setArguments(bundle); //在MyFragment1中代码是这样的: if(isAdded()){ //这里判断是否Fragment和Activity进行了绑定 Bundle bundle = getArguments(); String data_string = bundle.getString("data_string"); String data_int = bundle.getInt("data_int"); String data_char = bundle.getChar("data_char"); }
对于这个 isAdded() ;因为如果这个Fragment没有和Activity绑定的话,那么 Bundle 对象是无法从 Activity 传递给 Fragment 的,因此这种写法是必须的。
-
直接进行方法调用
在Activity里通过Fragment的引用,可以直接调用Framgent中的定义的任何方法。MyFragment1 myFragment1 = new MyFragment1(); myFragment.toString("传送的string数据");