Android通信相关总结

关于android中的数据通信,你会想到有那些地方,一起来回顾下吧:

  • 组件间的通信:Activity,fragment,Service, Provider,Receiver
  • 进程间的通信:AIDL
  • 线程间的通信:Handler,AnsycTask,IntentService
  • 多个App间的通信
  • 使用大型开源框架完成组件通信:如EventBus、otto

组件间通信

Activity 和 Activity

方式1:基于内存

Intent Bundle方式
  • 有以下两种重载方法

    1
    2
    startActivity(new Intent(),new Bundle());
    startActivityForResult(new Intent(),FLAG,new Bundle());
  • 注意事项

    • Intent Bundle 无法传递“不可序列化”的数据
    • Intent Bundle 能传递的数据大小在40K以内
公有静态变量

例如:

1
public static String flag=“我是参数”;

使用:在其他Activity当中,修改静态变量的值

1
MainActivity.flag=“我是在其他地方修改后的参数”;
全局变量 Application

将数据存入自定义Application对象中
例如:

1
2
3
public class MyApplication extends Application {	
public String flag=“我是参数”;
}

在其他组件中获取

1
2
MyApplication mMyApplication = (MyApplication)Context.getApplication();
String flag = mMyApplication.flag=“我是在其他地方修改后的参数”;

方式2,基于磁盘

  • 存文件 File
  • 存数据库SQLite
  • 存Sharepreference文件
  • 网络存储、等等方式….

Activity与Fragment

Activity传递给Fragment

  • 通过构造函数传递

    1
    2
    3
    4
    5
    6
    7
    public static CustomFragment newInstance(String name) {
    CustomFragment mFragment = new CustomFragment();
    Bundle mBundle = new Bundle();
    mBundle.putString("name", name);
    mFragment.setArguments(mBundle);
    return mFragment;
    }
  • 获取Fragment的实例对象

    1
    CustomFragment mCustomFragment = CustomFragment.newInstance("我是从Activity传递给Fragment的参数");

Fragment回传参数给Activity

方式1:

  • Activity 实现自定义接口
  • Fragment中通过 onAttach(Activity activity)方法拿到该自定义接口
  • Fragment中通过该自定义接口传递参数给Activity

方式2:

  • 也可通过getActivity()强制转换指定Activity,就可以任意操纵该Activity,但对于多个Activity对接该Fragment情况下,不建议这种方式使用

代码暂略

Activity与Service

Activity传参给Service

比如:CustomService 是自定义Service,完成一些后台操作

从FirstActivity传递参数给CustomService可通过Intent传输

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Intent mIntent = new Intent(FirstActivity.this,CustomService.class);
mIntent.putExtra(key,new Bundle());
startService(mIntent);
bindService(mIntent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//当前启动的service 一些数据就会回调回这里,我们在Activity中操作这些数据即可
// 系统调用这个来传送在service的onBind()中返回的IBinder.
}

@Override
public void onServiceDisconnected(ComponentName name) {
//Android系统在同service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了.当客户端解除绑定时,这个方法不会被调用.
}
},flags);

Service传参给Activity

Service提供Binder对象给Activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class thisCustomService extends Service {

public class LocalBinder extends Binder {
thisCustomService getService() {
// 当客户端回调的时候,返回LoacalService实例
return this,CustomService.this;
}
}

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}

//其他代码略
}

Activity与BroadcastReceiver

Activity传递参数给广播,通信基本也是通过Intent

1
2
3
Intent mIntent = new Intent(ACTION_INTENT_TEST);  
//mIntent可携带各种序列化参数
sendBroadcast(mIntent);

以下是在Activity中启动广播的形式

1
2
3
4
5
6
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {

}
},new IntentFilter());
1
2
3
4
5
6
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {

}
},new IntentFilter(),"",new Handler());//Handler参数为:定义了一个用于接收Intent的子线程,如果不填或者默认为null,那么就会在主线程中完成接收Intent的操作

AIDL 进程通信

AIDL的最终效果就是让 IPC的通讯就像调用函数那样简单。自动的帮你完成了参数序列化发送以及解析返回数据的那一系列麻烦。而你所需要做的就是写上一个接口文件,然后利用aidl工具转化一下得到另一个java文件,这个文件在服务和客户端程序各放一份。服务程序继承IxxxxService.Stub 然后将函数接口里面的逻辑代码实现一下。

相关参考:

线程间通信

  • Handler

Handler 是 一种机制【Handler+Message+Looper】,所有的数据通过Message携带,,所有的执行顺序按照队列的形式执行,Looper用来轮询判断消息队列,Handler用来接收和发送Message

  • AsyncTask

AsyncTask 是一个单独的类,设计之初的目的只是为了 异步方式完成耗时操作的,顺便可以通知主线程刷新Ui,AsyncTask的内部机制则是维护了一个线程池,提升性能。

  • IntentService 用于异步完成一个任务,结束后自动停止
    • 创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent。
    • 创建工作队列,用于将一个 Intent 逐一传递给 onHandleIntent() 实现,这样我们就永远不必担心多线程问题。
    • 在处理完所有启动请求后停止服务,因此我们不必调用 stopSelf()。
    • 提供 onBind() 的默认实现(返回 null)。
    • 提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent() 实现。

多个App间的通信

比如,从某某App打开地图查看某某地理位置时,这个时候就需要传递经纬度等信息给其他地图软件。需要给出指定action,打开对应action的应用

可通过隐式意图传递参数:

  • 如拨打电话.

    1
    2
    Uri number = Uri.parse("tel:4001111");
    Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
  • 查看地图

    1
    2
    3
    4
    5
    // 基于地址的地图位置
    Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
    // 基于经纬度的地图位置
    // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
    Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
  • 查看网页

    1
    2
    Uri webpage = Uri.parse("http://www.goluck.top");
    Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

可通过Intent.startActivityForResult()来完成其他应用返回的参数。
如:启动带返回模式打开其他应用

1
2
3
4
5
private void pickContact() {
Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
pickContactIntent.setType(Phone.CONTENT_TYPE);
startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}
  • 获取其他软件返回的参数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // 检查requestCode是否正确
    if (requestCode == PICK_CONTACT_REQUEST) {
    // 确保请求时成功的
    if (resultCode == RESULT_OK) {
    // 完成我们的业务逻辑
    }
    }
    }

使用其他大型数据通信框架

以下给出了一些比较出名的开源框架,使用可参考相关文档