学习笔记(八)进程与服务
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()); }
这样我们就做好了。
相关文章推荐
- 【学习笔记】启动Nginx、查看nginx进程、查看nginx服务主进程的方式、Nginx服务可接受的信号、nginx帮助命令、Nginx平滑重启、Nginx服务器的升级
- 【Linux学习笔记二十三】进程和服务的管理
- 【学习笔记】启动Nginx、查看nginx进程、查看nginx服务主进程的方式、Nginx服务可接受的信号、nginx帮助命令、Nginx平滑重启、Nginx服务器的升级
- RHCE7学习笔记28――控制服务和进程
- Spring in Action 学习笔记—第七章访问企业服务
- 学习Axis2笔记之四--创建pojo服务和客户端
- rh9 linux服务配置学习笔记--------dns
- 扬扬的J2EE学习笔记(四)Platform Services平台服务
- 孙鑫VC学习笔记:第十七讲 用邮槽实现进程间的通信
- Linux学习笔记 文件服务Vsftp详细介绍
- C++学习笔记-后台服务程序开发模式
- 《Web Service 编程 --用C#.NET 开发网络服务》北京希望出版社 我的学习笔记(第二章)(也就是书上抄了一写东西而已)
- SNDCP学习笔记二(服务源语和功能)
- Linux学习笔记----Mail服务
- Web服务高级编程学习笔记(一)
- C++学习笔记-后台服务程序开发模式
- AD学习笔记8——活动目录服务的基本安装和配置
- 孙鑫VC学习笔记:第十七讲 用匿名管道实现进程间的通信
- 《Web Service 编程 --用C#.NET 开发网络服务》北京希望出版社 我的学习笔记(第一章)(也就是书上抄了一写东西而已)
- 孙鑫VC学习笔记:第十七讲 用剪贴板实现进程间的通信