Android 四大组件之间的通信

    Android四大组件:Activity,Service,Broadcast,ContentProvider。下面主要介绍Activity之间的通信,Activity和Fragment之间的通信,Activity和Service之间的通信,以及ContentProvider使用。组件之间利用广播,EventBus等第三方框架进行通信这里不做介绍。

一、Activity之间的通信

1、通过startActivity或者startActivityForResult通信方式

    传递数据的通信方式就是Intent,Intent可以携带的数据类型包括基本数据类型(boolean, byte, char, double, float, int, long, short)以及基本类型数组,CharSequence以及CharSequence数组,String以及String数组,Parcelable以及Parcelable数组,Serializable和Bundle。

    在Bundle中可以put的数据类型和Intent保持一致,另外还可以传递Arraylist和SpareArray集合,其中的对象可以是实现序列化的Object,String和Integer对象。

    startActivity没什么说的,下面说下startActivityForResult / onActivityResult / setResult 组合。现有两个Activity :A和B,A启动B后,在B中做些操作然后返回,并携带一些数据(Intent携带数据)。

    A中:

Intent intent = new Intent(AActivity.this, BActivity.class);
startActivityForResult(intent, 1);
@Override
protected void onActivityResult(int requestCode, int resultCode,Intent intent) {
      //获取从B Activity回调的intent数据。
 }

   B中:

setResult(RESULT_OK, intent);        
finish();

2、使用Application,SharePreference,文件存储,数据库,ContentProvider等等 

    就是使用Application在一个较长的生命周期中暂存一些数据,供不同的activity等去读写调用,但其实并不安全,Application有可能被回收,SharePreference和文件存储和数据库基本都是将数据保存在相应的文件中了,不展开讨论了 。

3、使用接口

    就是定义一个接口,需要关注该事件的地方来实现这个接口。然后事件触发的地方来注册/取消注册这些对该事件感兴趣的控件.就是观察者模式,这样做的问题也是显而易见的,就是不同组件之间往往耦合的比较厉害,越来越多的接口也维护很麻烦,篇幅原因,不具体展开。关于观察者模式介绍可以参考这篇文章。

二、Activity和Fragment之间的通信

1、通过fragment.setArguments(bundle)方式传递数据,bundle传递数据

MyFragment myFragment = new MyFragment();
Bundle bundle = new Bundle();
bundle.putString("DATA",values);//这里的values就是我们要传的值
myFragment.setArguments(bundle);

    然后在Fragment中的onCreatView方法中,通过getArgments()方法,获取到bundle对象,然后通过getString的key值拿到我们传递过来的值。

    另一种一般在Fragment中定义静态方法getInstance来获取Frament实例,如:

public static MyFragment newInstance(String s){
        MyFragment myFragment = new MyFragment();
        Bundle bundle = new Bundle();
        bundle.putString("DATA",s);
        myFragment.setArguments(bundle);
        return myFragment;
    }

2、在Fragment和Actiivty关联后,调用Activity中的public修饰的方法

    Fragment中的onAttach方法,表明Fragment和Activity进行了关联,用该种方式容易出现Fragment getActivity为null的情况,得注意Fragment生命周期,避免出现crash。

3、广播方式,定义接口,文件方式等不在累述。


三、Activity和Service之间的通信

广播以及文件,第三方方式略过。

1、通过bundle传递数据,startService(intent)和bindService()方法启动服务

    分别调用startService(intent)和stopService(intent)来启动和停止服务。在Service中,我们通过onStartCommand(finalIntent intent, int flags, intstartId)这个函数来接收从Activity传过来的值


    多次startService() 同一个Service,onCreate()只会执行一次,onStartCommand()会执行多次。通过stopService结束服务。

    通过bindService()启动服务,在没有进行unbindService()情况下执行stopService()是没办法结束Service的。多次进行bindService()方法,但onCreate()和onBind()都只执行一次。

2、通过Binder(activity和service属于同一个application应用进程)

    bindService(intent, connection, Context.BIND_AUTO_CREATE);在connection中获取到Binder对象,通过Binder获取到Service即可调用service中对应的方法。

public class LocalService extends Service {  
    // 实例化自定义的Binder类  
    private final IBinder mBinder = new LocalBinder();  
    // 随机数的生成器  
    private final Random mGenerator = new Random();  
  
    /** 
     * 自定义的Binder类,这个是一个内部类,所以可以知道其外围类的对象,通过这个类,让Activity知道其Service的对象 
     */  
    public class LocalBinder extends Binder {  //Binder 实现了IBinder接口
        LocalService getService() {  
            // 返回Activity所关联的Service对象,这样在Activity里,就可调用Service里的一些公用方法和公用属性  
            return LocalService.this;  
        }  
    }  
  
    @Override  
    public IBinder onBind(Intent intent) {  
        return mBinder;  
    }  
  
    /** public方法,Activity可以进行调用 */  
    public int getRandomNumber() {  
      return mGenerator.nextInt(100);  
    }  
}  

    在Activity中创建connection对象

 /** 定交ServiceConnection,用于绑定Service的*/  
    private ServiceConnection mConnection = new ServiceConnection() {  
  
        @Override  
        public void onServiceConnected(ComponentName className,  
                IBinder service) {  
            // 已经绑定了LocalService,强转IBinder对象,调用方法得到LocalService对象  
            LocalBinder binder = (LocalBinder) service;  
            mService = binder.getService();  
            
        }  
  
        @Override  
        public void onServiceDisconnected(ComponentName arg0) {  
            
        }  
    };  
}  

3、通过Messenger实现和service双向通信(可跨进程)

    Activity通过bindService方法来开启Service,先查看下Messenger的两个构造方法:

Messenger(Handler target)
Create a new Messenger pointing to the given Handler.

Messenger(IBinder target)
Create a Messenger from a raw IBinder, which had previously been retrieved with getBinder().

    相关api方法:

void send(Message message)
Send a Message to this Messenger's Handler.

Ibinder getBinder()
Retrieve the IBinder that this Messenger is using to communicate with its associated Handler.

    1)、单向通信(Activity--->Service)

    使用Messenger和Service通信的步骤:

Service中的工作:

  • 在Service中,创建Handler对象用来处理消息,并用该Handler创建Messenger对象;
  • 在Service中,用创建好的Messenger对象获取一个IBinder对象,通过Service的onBind方法中返回给Activity。

Activity中的工作:

  • 用在ServiceConnection中获取的IBinder对象创建一个Messenger对象,该Messenger对象持有Service中的Handler对象;
  • 用Message msg = Message.obtain()方法创建消息,message可以通过setData(Bundle data)携带数据;
  • 用Messenger.send(Message msg)发送消息给Service中的Handler。

    通过上述几个步骤,即可实现单向通信(Activity--->Service),如果要实现双线通信,很容易想到只要在Service中获取到包含Activity中Handler对象的Messenger发送消息即可。

2)双向通信

    现在要实现双向通信的关键步骤是得获取到Activity中的Messenger对象。如何获取?在Message中有个属性:

public Messenger	replyTo  //用来对该消息的回复

    关键步骤在Activity通过Messenger.send(Message msg)给Service发送消息之前,指定Message的replyTo=clientMessaenger,然后Service通过message.replayTo获取到Activity的Messaenger,这样Service就可以向Activity发送消息了,实现双向通信。

 四、ContentProvider的简单实用介绍

    ContentProvider它主要的作用是:实现各个应用程序之间的(跨应用)数据共享,比如联系人应用中就使用了ContentProvider,你在自己的应用中可以读取和修改联系人的数据,不过需要获得相应的权限。所以组件之间也可以通过ContentProvider来进行数据通信,本质是通过数据库文件实现通信。

    ContentProvider提供数据供访问,需要使用ContentResolver来访问数据。最主要的工作就是操作数据库。两大步:

  • 自定义ContentProvider,主要对数据库进行存取等操作。
  • 获取ContentReolver对象,解析对应数据库的URI来访问和读取数据库等操作。如下查询操作(注意权限):
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://com.example.MyApplication.StudentsProvider/students");
Cursor cursor = contentResolver.query(uri, null, null, null, null);


猜你喜欢

转载自blog.csdn.net/white_wt/article/details/80461121