`
qilixiang012
  • 浏览: 202697 次
文章分类
社区版块
存档分类
最新评论

android中Activity,Service和线程之间的通信

 
阅读更多
Activity、Service和线程应该是Android编程中最常见的几种类了,几乎大多数应用程序都会涉及到这几个类的编程,自然而然的,也就会涉及到三者之间的相互通信,本文就试图简单地介绍一下这三者通信的方式。
想写这篇文章的起因是,笔者跟几个同学在做一个Android上的应用,起初代码写得很凌乱,因为我在Activity中直接创建了线程,去执行某些任务。但是我们知道线程可能需要运行的时间比较长,而Android在内存不足的时候,会将一些Activity销毁,这样线程就会失去了管理的对象,从而使程序发生意想不到的结果。此外,在Activity中创建线程,线程跟Activity的通信也比较麻烦,一般借助Handler类来进行通信(http://blog.sina.com.cn/s/blog_3fe961ae0100mvc5.html)。
与Activity相比,Service一般“默默”地运行在后台,生命周期比较长,所以它更合适去为主程序提供某些服务,创建线程并管理线程。因此,笔者将原程序改成三层架构,从高到低分别为:Activity层--Service层--Thread层。Activity将需要的服务“告诉”Service层,Service层创建Thread去完成服务。Thread将任务的进度、状态、错误信息反馈给Service,Service将这些消息反馈给相关的Activity,并且还可以利用Notification更新通知栏消息。大体的结构就是这样。

1 Activity和Service之间的通信

1.2 Activity调用startService (Intentservice)方法,将消息添加到Intent对象中,这样Service对象可以在调用onStartCommand (Intentintent, int flags, intstartId)的时候可以得到这些消息。这种方法很简单,但如果有大量的信息要传递的话,就很麻烦了。因为Service端还要判断一下消息是什么,才能作进一步的动作。

1.3 Activity调用bindService (Intentservice, ServiceConnection conn, intflags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法。具体代码:

1.4Service向Activity发送消息,除了可以利用Handler外,还可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好。具体方法可以看一下这篇文章:

2 Service跟Thread之间的通信
2.1Service创建Thread后,如果要对线程进行控制(启动,暂停,停止等),那么Service中应该保留线程的引用,这不用多说。那么有了这个引用,Service就可以直接调用Thread的其它方法了。运行的线程要向Service发送消息的话,通常使用Handler就可以了:


3 Activity和Thread之间的通信
不用多想了,直接使用Handler吧。不推荐Activity直接去创建线程,因为不好管理线程。

****************************************************************************************************************************************************************************************

Activity与Service通信的方式有三种:

继承Binder类

这个方式只有当你的Acitivity和Service处于同一个Application和进程时,才可以用,比如你后台有一个播放背景音乐的Service,这时就可以用这种方式来进行通信。

用例子来说明其使用方法:

1. 来看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 {  
        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);  
    }  
}  

在Service里定义一个内部类,Binder的子类,通过这个类,把Service的对象传给Activity,这样Activity就可以调用Service里的公用方法和公用属性了,但这种方式,一定要在同一个进程和同一个Application里。

2. 再看相应Activity的代码:

public class BindingActivity extends Activity {  
    LocalService mService;  
    boolean mBound = false;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
    }  
  
    @Override  
    protected void onStart() {  
        super.onStart();  
        // 绑定Service,绑定后就会调用mConnetion里的onServiceConnected方法  
        Intent intent = new Intent(this, LocalService.class);  
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);  
    }  
  
    @Override  
    protected void onStop() {  
        super.onStop();  
        // 解绑Service,这样可以节约内存  
        if (mBound) {  
            unbindService(mConnection);  
            mBound = false;  
        }  
    }  
  
    /** 用户点击button,就读取Service里的随机数 */  
    public void onButtonClick(View v) {  
        if (mBound) {  
            // 用Service的对象,去读取随机数  
            int num = mService.getRandomNumber();  
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();  
        }  
    }  
  
    /** 定交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();  
            mBound = true;  
        }  
  
        @Override  
        public void onServiceDisconnected(ComponentName arg0) {  
            mBound = false;  
        }  
    };  
}  

这里就是通过IBinder来得到LocalService对象,再去调用其Public方法。

使用Messenger

上面的方法只能在同一个进程里才能用,如果要与另外一个进程的Service进行通信,则可以用Messenger。

其实实现IPC的方式,还有AIDL,但推荐使用Messenger,有两点好处:

1. 使用Messenger方式比使用AIDL的方式,实现起来要简单很多

2. 使用Messenger时,所有从Activity传过来的消息都会排在一个队列里,不会同时请求Service,所以是线程安全的。如果你的程序就是要多线程去访问Service,就可以用AIDL,不然最好使用Messenger的方式。

不过,其实Messenger底层用的就是AIDL实现的,看一下实现方式,先看Service的代码:

public class MessengerService extends Service {  
    /** 用于Handler里的消息类型 */  
    static final int MSG_SAY_HELLO = 1;  
  
    /** 
     * 在Service处理Activity传过来消息的Handler 
     */  
    class IncomingHandler extends Handler {  
        @Override  
        public void handleMessage(Message msg) {  
            switch (msg.what) {  
                case MSG_SAY_HELLO:  
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();  
                    break;  
                default:  
                    super.handleMessage(msg);  
            }  
        }  
    }  
  
    /** 
     * 这个Messenger可以关联到Service里的Handler,Activity用这个对象发送Message给Service,Service通过Handler进行处理。 
     */  
    final Messenger mMessenger = new Messenger(new IncomingHandler());  
  
    /** 
     * 当Activity绑定Service的时候,通过这个方法返回一个IBinder,Activity用这个IBinder创建出的Messenger,就可以与Service的Handler进行通信了 
     */  
    @Override  
    public IBinder onBind(Intent intent) {  
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();  
        return mMessenger.getBinder();  
    }  
}  

再看一下Activity的代码:

public class ActivityMessenger extends Activity {  
    /** 向Service发送Message的Messenger对象 */  
    Messenger mService = null;  
  
    /** 判断有没有绑定Service */  
    boolean mBound;  
  
    private ServiceConnection mConnection = new ServiceConnection() {  
        public void onServiceConnected(ComponentName className, IBinder service) {  
            // Activity已经绑定了Service  
            // 通过参数service来创建Messenger对象,这个对象可以向Service发送Message,与Service进行通信  
            mService = new Messenger(service);  
            mBound = true;  
        }  
  
        public void onServiceDisconnected(ComponentName className) {  
            mService = null;  
            mBound = false;  
        }  
    };  
  
    public void sayHello(View v) {  
        if (!mBound) return;  
        // 向Service发送一个Message  
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);  
        try {  
            mService.send(msg);  
        } catch (RemoteException e) {  
            e.printStackTrace();  
        }  
    }  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
    }  
  
    @Override  
    protected void onStart() {  
        super.onStart();  
        // 绑定Service  
        bindService(new Intent(this, MessengerService.class), mConnection,  
            Context.BIND_AUTO_CREATE);  
    }  
  
    @Override  
    protected void onStop() {  
        super.onStop();  
        // 解绑  
        if (mBound) {  
            unbindService(mConnection);  
            mBound = false;  
        }  
    }  
}  

注意:以上写的代码只能实现从Activity向Service发送消息,如果想从Service向Activity发送消息,只要把代码反过来写就可以了。

使用AIDL

这个方法略,如果知道上面两种方法,这个方法基本很少会用到。

转载地址:http://blog.csdn.net/qjbagu/article/details/7481796
分享到:
评论

相关推荐

    详解Android Service与Activity之间通信的几种方式

    在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activity中启动后台Service,通过Intent来启动,...

    Android中Service与Activity之间通信的几种方式

    在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activity中启动后台Service,通过Intent来启动,...

    Android Activity与Service通信(不同进程之间)详解

    在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activity中启动后台Service,通过Intent来启动,...

    Android服务Service详解

    本章内容服务(Service)是Android系统中4个应用程序组件之一(其他的组件详见3.2节的内容)。服务主要用于两个目的:后台运行和跨进程访问。通过启动一个服务,可以在不显示界面的前提下在后台运行指定的任务,这样...

    Android在后台最小化的多线程下载程序实例.rar

    service 与activity 之间的消息通信 既是activity向service发消息 需要实现ServiceConnection接口 绑定服务, 第一次启动BackStage的Activity时启动接收广播,需要知道当前SD卡的目录,Environment....

    Android中使用开源框架eventbus3.0实现fragment之间的通信交互

    1.概述 ...作用是可以代替传统的Intent,Handler,Broadcast或接口函数在Fragment、Activity、Service、线程之间传递数据进行通信,执行方法。做为消息总线,有三个主要元素: (1)Event:事件 (2)Subs

    快速入门android AIDL(开启多进程并进行通信)

    如果仅仅在子线程中运行,一旦开启该线程的Activity被杀死后,线程也被杀死,无法实现后台运行效果,更加不合理。而如果在另外一个进程中使用service后台运行,就显得十分恰当了。 二、由于android对单个应用所使用...

    安卓多线程断点续传下载服务器和客户端源码

    1、android中主线程与非主线程通信机制。 2、多线程的编程和管理。 3、android网络编程 4、自己设计实现设计模式-监听器模式 5、Activity、Service、数据库编程 6、android文件系统 7、缓存 博文地址:...

    Android开发案例驱动教程 配套代码

    8.4.1 Android线程应用中的问题与分析 164 8.4.2 Message和MessageQueue 169 8.4.3 Handler 169 8.4.4 Looper和HandlerThread 172 本章小结 178 第9章 Activity和Intent 179 9.1 Activity 179 9.1.1 创建...

    android开发demo集合

    39、Activity与Service运行中通信 40、Service 相当于没有界面的activity 41、AIDL Service android中的跨进程调用 客户端,服务端见AidlService 42、BroadcastReceiver 接收广播消息 43、非UI线程中不能操作UI...

    《Android开发案例驱动教程》

    第9章 Activity和Intent 219 第10章 Android数据存储 248 第11章 Content Provider 302 第12章 多媒体开发 341 第13章 Service 385 第14章 Broadcast Receiver和Notification 422 第15章 云端应用 449 第16章 Google...

    《Android系统源代码情景分析》

    1.3 下载、编译和运行Android源代码 1.3.1 下载Android源代码 1.3.2 编译Android源代码 1.3.3 运行Android模拟器 1.4 下载、编译和运行Android内核源代码 1.4.1 下载Android内核源代码 1.4.2 编译...

    《Android开发案例驱动教程》源码

    第9章 Activity和Intent 219 第10章 Android数据存储 248 第11章 Content Provider 302 第12章 多媒体开发 341 第13章 Service 385 第14章 Broadcast Receiver和Notification 422 第15章 云端应用 449 第16章 Google...

    android 面试2

    service不包含可见的用户界面,而是在后台无限地运行可以连接到一个正在运行的服务中,连接后,可以通过服务中暴露出来的借口与其进行通信 broadcast receiver是一个接收广播消息并作出回应的component,broadcast ...

    Android自学视频教程 part1

    主要包括Android高级组件的使用、Android中的事件处理、数据存储技术、Content Provider实现数据共享、图形图像处理技术、利用OpenGL实现3D图形、多媒体应用开发、线程与消息处理、网络编程技术和Service服务的使用...

    Android开发入门与实战+和第二版部分章节+第二版源代码

    本书主要内容为:Android开发环境搭建、Android SDK介绍、Android应用程序结构剖析,并对Android 中最重要的组件Activity、Intents&Intent Filters&Broadcast receivers、Intent、Service、Content Providers进行了...

    Android开发与应用——张荣,原书配套课件

    7.4 Android多线程通信机制 7.5 小结 练习 第8章 网络通信 8.1 通过HTTP访问网络 8.1.1 测试用Web服务器 8.1.2 WebView组件 8.1.3 HttpURLConnection 8.2 Socket编程 8.3 数据的解析 8.3.1 JSON...

    android初学者入门项目

    39、Activity与Service运行中通信 40、Service 相当于没有界面的activity 41、AIDL Service android中的跨进程调用 客户端,服务端见AidlService 42、BroadcastReceiver 接收广播消息 43、非UI线程中不能操作UI...

    Android的设计与实现(卷1)

    消息通信篇(第7章)重点分析了android的消息驱动和异步处理机制,能让读者深入理解线程间的通信模型;package manager篇(第8~9章)主要讲解了package manager的机制与实现,以及apk的安装方法与过程;activity ...

Global site tag (gtag.js) - Google Analytics