您的位置:首页 > 其它

学习笔记(八)进程与服务

2016-09-02 23:39 337 查看

进程

上次说到了线程和多线程之间的通信方式,这次我们学习多进程。

Android每个程序的运行都会自动创建一个进程,进程名会以包名命名。进程是系统进行资源分配和调度的基本单位,形象的来说就是,一个车间就是一个进程,一个进程中可以有多个线程,一个车间可以有多个生产线。

进程的创建

<service android:name=".Messenger_Service"
android:process="com.example.lenovo_pc.class_eight_messnger">
</service>


只需加android:process=”value”就可以创建一个新的进程,所在进程的名字就是value值,如果android:process的value不是”:”开头,则系统里有同样名字的进程的话,会放到已存在的同名进程里运行,这样能减小消耗。如果android:process的value是以”:”开头,则启动一个名字为value的进程。

同样,activity,Broadcast等开启新的进程也是使用相同的方法。

进程的生命周期

共分五个等级

- 前台进程 (重要性最高)

- 可见进程

- 服务进程

- 后台进程

- 空进程 (重要性最低)

其中,拥有最低重要性的进程会首先被干掉,然后就是那些次低重要性的进程,依次类推。

多进程

我们都知道,android平台对应用都有内存限制,使用多进程就可以使得我们一个apk所使用的内存限制加大几倍,从而使我们的程序处理起来更加流畅。而且由于进程之间内存不共享,更加稳定安全,不易崩溃。

多进程之间的通信

由于进程之间数据不共享,所以就要使用多进程之间的通信。

- Messenger+Handler 适用于:多进程,单线程

- Aidl 适用于多进程,多线程

Messenger

Google定义:This allows for the implementation of message-based communication across processes

允许实现基于消息的进程间通信的方式。

至于什么是基于消息的进程间通信方式,大家可以参考:

http://blog.csdn.net/lmj623565791/article/details/47017485

一般的使用方法:

一般使用方法如下:

1。远程通过

mMessenger = new Messenger(mHandler)

创建一个信使对象

2。客户端使用bindlerService请求连接远程

3。远程onBind方法返回一个bindler

return mMessenger.getBinder();

4.客户端使用远程返回的bindler得到一个信使(即得到远程信使)

public void onServiceConnected(ComponentName name, IBinder service) {

rMessenger = new Messenger(service);     

……

}

这里虽然是new了一个Messenger,但我们查看它的实现

public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }

发现它的mTarget是通过Aidl得到的,实际上就是远程创建的那个。

5。客户端可以使用这个远程信使对象向远程发送消息:rMessenger.send(msg);

这样远程服务端的Handler对象就能收到消息了,然后可以在其handlerMessage(Message msg)方法中进行处理。(该Handler对象就是第一步服务端创建Messenger时使用的参数mHandler).

经过这5个步骤貌似只有客户端向服务端发送消息,这样的消息传递是单向的,那么如何实现双向传递呢?

首先需要在第5步稍加修改,在send(msg)前通过msm.replyTo = mMessenger将自己的信使设置到消息中,这样服务端接收到消息时同时也得到了客户端的信使对象了,然后服务端可以通过/得到客户端的信使对象,并向它发送消息 cMessenger = msg.replyTo; cMessenger.send(message);

即完成了从服务端向客户端发送消息的功能,这样客服端可以在自己的Handler对象的handlerMessage方法中接收服务端发送来的message进行处理。

上面的一般方法大家可以自行百度,网上有很多资源。

**注意:**Message的obj不能设置为设置为non-Parcelable的对象,在跨进程的情形下,Message的obj设置为了一个String对象,那么在Messenger执行send(Message)方法时就会报如下错误: Java.lang.RuntimeException: Can’t marshal non-Parcelable objects across processes.

解决该问题最简单的办法是,在跨进程的时候不使用Message的obj,用Bundle传递数据,setData设置Bundle数据,getData获取Bundle数据。

AIDL

aidl是 Android Interface definition language的缩写,可以定义为进程间的通信接口。

AIDL的使用过程:

首先,创建一个aidl文件(不清楚的自行百度哈)



其次,创建一个Service类

public class Aidl_Service extends Service {
IMyAidlInterface.Stub stub=new IMyAidlInterface.Stub(){

@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

}
Override
public String getName(String nickName) throws RemoteException {
return nickName+"aidi_hahah";
}

@Override
public int result(int a, int b) throws RemoteException {
return a+b;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}


同样我们还可以自定义一些方法,然后编译一下,新加入的方法就可以被使用。

第三,在另一个activity中实现通信

private Button btn;
ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};
private IMyAidlInterface iMyAidlInterface;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aidl_layout);
btn = (Button) findViewById(R.id.aidl_btn);

bindService(new Intent(Aidl.this,Aidl_Service.class),connection, Context.BIND_AUTO_CREATE);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(iMyAidlInterface!=null){
try {
String name=iMyAidlInterface.getName("nick_know_maco");
int result=iMyAidlInterface.result(1,3);
Toast.makeText(Aidl.this,name+""+result,Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});


最后,在AndroidManifest.xml中给service开辟一个新的进程,然后我们点击运行就可以实现了跨进程之间的通信。



Notification

 Notification,俗称通知,是一种具有全局效果的通知,它展示在屏幕的顶端,首先会表现为一个图标的形式,当用户向下滑动的时候,展示出通知具体的内容。

通知一般通过NotificationManager服务来发送一个Notification对象来完成,NotificationManager是一个重要的系统级服务,该对象位于应用程序的框架层中,应用程序可以通过它像系统发送全局的通知。

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
MainActivity.this).setSmallIcon(R.drawable.one)
.setContentTitle("new message")
.setContentText("twain@android.com");
mBuilder.setTicker("New message");//第一次提示消息的时候显示在通知栏上
mBuilder.setNumber(12);
mBuilder.setLargeIcon(btm);
mBuilder.setAutoCancel(true);//自己维护通知的消失

//构建一个Intent
Intent resultIntent = new Intent(MainActivity.this,
ResultActivity.class);
//封装一个Intent
PendingIntent resultPendingIntent = PendingIntent.getActivity(
MainActivity.this, 0, resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 设置通知主题的意图
mBuilder.setContentIntent(resultPendingIntent);
//获取通知管理器对象
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}


这样我们就做好了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐