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

进程

上次说到了线程和多线程之间的通信方式,这次我们学习多进程。
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());
}

这样我们就做好了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值