美文网首页Android代码封装Android知识面试
Android中Service与多个Activity通信的三种方

Android中Service与多个Activity通信的三种方

作者: 爱因私谈 | 来源:发表于2017-05-16 16:18 被阅读141次

    由于项目需要,我们有时候需要在service中处理耗时操作,然后将结果发送给activity以更新状态。通常情况下,我们只需要在一个service与一个activity之间通信,通常这种情况下,我们使用最多的是通过回调接口。具体做法是在service中定义一个接口,在activity中实现该接口,并通过bindservice来传入。实现方式很简单,在此不再赘述。
    当需要将service中的结果一次发送给多个activity时,我们又该如何实现呢?经过多个项目的积累,总结了三种实现的方式。分别是回调接口、广播接收者和观察者模式。

    1. 回调接口的方式

    与单个service与单个activity通信类似,只是将service中的接口变为接口的集合,每个需要通信的activity都实现接口,然后在获取结果后,循环调用集合中的实现类,来与多个activity进行通信,代码如下:

    1.1 Service类:

    package com.example.servicecallback;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.util.Log;
    
    public class ContentService extends Service {
    
        //回调接口的集合
        private List<Callback> list;
    
        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            return new LocalBinder();
        }
    
        @Override
        public void onCreate() {
            // TODO Auto-generated method stub
            super.onCreate();
            list = new ArrayList<Callback>();
        }
    
        public final class LocalBinder extends Binder {
            public ContentService getService() {
                return ContentService.this;
            }
        }
    
        /**
         * 回调接口
         * @author Ivan Xu
         *
         */
        public interface Callback {
            public void getPerson(Person person);
        }
    
        /**
         * 往回调接口集合中添加一个实现类
         * @param callback
         */
        public void addCallback(Callback callback) {
            list.add(callback);
        }
    
        public void asyncSendPerson(final String name) {
            // 休息5秒,模拟异步任务
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    handler.sendMessage(handler.obtainMessage(0, name));
                }
            }).start();
        }
    
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                String name = (String) msg.obj;
                Log.i("ContentService", "---name-->" + name);
                Person person = new Person();
                person.setName(name);
                Log.i("ContentService", "---list.size()-->" + list.size());
                Log.i("ContentService", "---person-->" + person.toString());
                //遍历集合,通知所有的实现类,即activity
                for (int i = 0; i < list.size(); i++) {
                    list.get(i).getPerson(person);
                }
            }
        };
    }
    

    1.2 第一个activity:

    package com.example.servicecallback;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.TextView;
    import com.example.servicecallback.ContentService.Callback;
    import com.example.servicecallback.ContentService.LocalBinder;
    
    public class MainActivity extends Activity implements Callback {
    
        private MyServiceConn conn;
        private ContentService service;
        private TextView mContent;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            conn=new MyServiceConn();
            bindService(new Intent(this, ContentService.class), conn,
                    BIND_AUTO_CREATE);
    
            mContent = (TextView) findViewById(R.id.content);
    
            this.findViewById(R.id.button1).setOnClickListener(
                    new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // TODO Auto-generated method stub
                            startActivity(new Intent(MainActivity.this,
                                    OtherActivity.class));
                        }
                    });
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        public class MyServiceConn implements ServiceConnection {
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                service = ((LocalBinder) binder).getService();
                //将当前activity添加到接口集合中
                service.addCallback(MainActivity.this);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                // TODO Auto-generated method stub
                service = null;
            }
        }
    
        @Override
        protected void onDestroy() {
            // TODO Auto-generated method stub
            super.onDestroy();
            unbindService(conn);
        }
    
        /**
         * 获取回调的内容,更新UI
         */
        @Override
        public void getPerson(Person person) {
            // TODO Auto-generated method stub
            mContent.setText(person.toString());
        }
    }
    

    1.3 第二个activity:

    package com.example.servicecallback;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    import com.example.servicecallback.ContentService.Callback;
    import com.example.servicecallback.ContentService.LocalBinder;
    import com.example.servicecallback.MainActivity.MyServiceConn;
    
    public class OtherActivity extends Activity implements Callback {
    
        private ContentService service;
        private TextView mContent;
        private Button mSubmit;
        private EditText mEditText;
        private ServiceConnection conn;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.other);
    
            mEditText = (EditText) findViewById(R.id.edittext);
            mSubmit = (Button) findViewById(R.id.button1);
            mContent = (TextView) findViewById(R.id.content);
    
            mSubmit.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    String name = mEditText.getText().toString();
                    service.asyncSendPerson(name);
                }
            });
    
            
            conn=new MyServiceConn();
            bindService(new Intent(OtherActivity.this, ContentService.class), conn,
                    BIND_AUTO_CREATE);
    
        }
    
        public final class MyServiceConn implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                // TODO Auto-generated method stub
                service = ((LocalBinder) binder).getService();
                //将当前activity添加到接口集合中
                service.addCallback(OtherActivity.this);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                // TODO Auto-generated method stub
                service = null;
            }
        }
    
        @Override
        protected void onDestroy() {
            // TODO Auto-generated method stub
            super.onDestroy();
            unbindService(conn);
        }
    
        /**
         * 获取回调的内容,更新UI
         */
        @Override
        public void getPerson(Person person) {
            // TODO Auto-generated method stub
            mContent.setText(person.toString());
        }
    }
    

    2 通过广播(==推荐==)

    在service中执行完耗时操作后,将结果以广播的形式发送,在所有的activity中注册广播,接收到结果后更新UI,这种方式比较简单,也是笔者比较推荐的方式。因为耗时的操作结果不需要以handler的方式发送到主线程,可以直接在子线程中发送广播,接收者始终运行在主线程中。代码如下:

    2.1 Service类:

    package com.example.servicecallback;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    
    public class ContentService extends Service {
    
    
        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            return new LocalBinder();
        }
    
        @Override
        public void onCreate() {
            // TODO Auto-generated method stub
            super.onCreate();
        }
    
        public final class LocalBinder extends Binder {
            public ContentService getService() {
                return ContentService.this;
            }
        }
    
        public void asyncSendPerson(final String name) {
            // 休息5秒,模拟异步任务
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //可以在子线程中直接发送广播
                    sendContentBroadcast(name);
                }
            }).start();
        }
    
        /**
         * 发送广播
         * @param name
         */
        protected void sendContentBroadcast(String name) {
            // TODO Auto-generated method stub
            Intent intent=new Intent();
            intent.setAction("com.example.servicecallback.content");
            intent.putExtra("name", name);
            sendBroadcast(intent);
        }
    }
    

    2.2 第一个activity:

    package com.example.servicecallback;
    
    import android.app.Activity;
    import android.content.BroadcastReceiver;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
        private MyServiceConn conn;
        private TextView mContent;
        private ContentReceiver mReceiver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            conn = new MyServiceConn();
            bindService(new Intent(this, ContentService.class), conn,
                    BIND_AUTO_CREATE);
    
            mContent = (TextView) findViewById(R.id.content);
    
            this.findViewById(R.id.button1).setOnClickListener(
                    new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // TODO Auto-generated method stub
                            startActivity(new Intent(MainActivity.this,
                                    OtherActivity.class));
                        }
                    });
    
            
            doRegisterReceiver();
        }
    
        /**
         * 注册广播接收者
         */
        private void doRegisterReceiver() {
            mReceiver=new ContentReceiver();
            IntentFilter filter = new IntentFilter(
                    "com.example.servicecallback.content");
            registerReceiver(mReceiver, filter);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        public class MyServiceConn implements ServiceConnection {
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                // service = ((LocalBinder) binder).getService();
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                // TODO Auto-generated method stub
                // service = null;
            }
        }
    
        @Override
        protected void onDestroy() {
            // TODO Auto-generated method stub
            super.onDestroy();
            unbindService(conn);
            if (mReceiver!=null) {
                unregisterReceiver(mReceiver);
            }
        }
    
        public class ContentReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                String name = intent.getStringExtra("name");
                Person person = new Person();
                person.setName(name);
                mContent.setText(person.toString());
            }
        }
    }
    

    2.3 第二个activity:

    package com.example.servicecallback;
    
    import android.app.Activity;
    import android.content.BroadcastReceiver;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    import com.example.servicecallback.ContentService.LocalBinder;
    
    public class OtherActivity extends Activity {
    
        private ContentService service;
        private TextView mContent;
        private Button mSubmit;
        private EditText mEditText;
        private ServiceConnection conn;
        private ContentReceiver mReceiver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.other);
    
            mEditText = (EditText) findViewById(R.id.edittext);
            mSubmit = (Button) findViewById(R.id.button1);
            mContent = (TextView) findViewById(R.id.content);
    
            mSubmit.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    String name = mEditText.getText().toString();
                    service.asyncSendPerson(name);
                }
            });
    
            
            conn=new MyServiceConn();
            bindService(new Intent(OtherActivity.this, ContentService.class), conn,
                    BIND_AUTO_CREATE);
    
            doRegisterReceiver();
        }
    
        private void doRegisterReceiver() {
            mReceiver=new ContentReceiver();
            IntentFilter filter = new IntentFilter(
                    "com.example.servicecallback.content");
            registerReceiver(mReceiver, filter);
        }
        
        public final class MyServiceConn implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                service = ((LocalBinder) binder).getService();
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                service = null;
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(conn);
            if (mReceiver!=null) {
                unregisterReceiver(mReceiver);
            }
        }
    
        public class ContentReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                String name = intent.getStringExtra("name");
                Person person = new Person();
                person.setName(name);
                mContent.setText(person.toString());
            }
        }
    }
    

    3 使用观察者模式

    service为被观察者,所有的activity为观察者,当service中的内容发生改变时,通知所有的activity来更新,代码如下:

    3.1 Service类:

    package com.example.servicecallback;
    
    import java.util.Observable;
    import java.util.Observer;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    
    public class ContentService extends Service {
    
        //被观察者
        private MyObservable mObservable;
    
        @Override
        public IBinder onBind(Intent arg0) {
            return new LocalBinder();
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            mObservable = new MyObservable();
        }
    
        public final class LocalBinder extends Binder {
            public ContentService getService() {
                return ContentService.this;
            }
        }
    
        public void asyncSendPerson(final String name) {
            // 休息5秒,模拟异步任务
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    handler.sendMessage(handler.obtainMessage(0, name));
                }
            }).start();
        }
    
        /**
         * 添加观察者
         * @param observer
         */
        public void addObserver(Observer observer) {
            mObservable.addObserver(observer);
        }
    
        private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                String name = (String) msg.obj;
                Person person = new Person();
                person.setName(name);
                //通知更新
                mObservable.notifyChanged(person);
            }
        };
    
        public class MyObservable extends Observable {
            
            public void notifyChanged(Object object) {
                this.setChanged();
                this.notifyObservers(object);
            }
        }
    }
    

    3.2 第一个activity:

    package com.example.servicecallback;
    
    import java.util.Observable;
    import java.util.Observer;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.TextView;
    
    import com.example.servicecallback.ContentService.LocalBinder;
    
    public class MainActivity extends Activity implements Observer {
    
        private MyServiceConn conn;
        private TextView mContent;
        private ContentService mService;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            conn = new MyServiceConn();
            bindService(new Intent(this, ContentService.class), conn,
                    BIND_AUTO_CREATE);
    
            mContent = (TextView) findViewById(R.id.content);
    
            this.findViewById(R.id.button1).setOnClickListener(
                    new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            startActivity(new Intent(MainActivity.this,
                                    OtherActivity.class));
                        }
                    });
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        public class MyServiceConn implements ServiceConnection {
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                mService = ((LocalBinder) binder).getService();
                //将当前activity添加为观察者
                mService.addObserver(MainActivity.this);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mService = null;
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(conn);
        }
    
        //更新UI
        @Override
        public void update(Observable observable, Object data) {
            Person person = (Person) data;
            mContent.setText(person.toString());
        }
    
    }
    

    3.2 第二个activity:

    package com.example.servicecallback;
    
    import java.util.Observable;
    import java.util.Observer;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    import com.example.servicecallback.ContentService.LocalBinder;
    
    public class OtherActivity extends Activity implements Observer {
    
        private ContentService service;
        private TextView mContent;
        private Button mSubmit;
        private EditText mEditText;
        private ServiceConnection conn;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.other);
    
            mEditText = (EditText) findViewById(R.id.edittext);
            mSubmit = (Button) findViewById(R.id.button1);
            mContent = (TextView) findViewById(R.id.content);
    
            mSubmit.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    String name = mEditText.getText().toString();
                    service.asyncSendPerson(name);
                }
            });
    
            conn = new MyServiceConn();
            bindService(new Intent(OtherActivity.this, ContentService.class), conn,
                    BIND_AUTO_CREATE);
    
        }
    
        public final class MyServiceConn implements ServiceConnection {
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                service = ((LocalBinder) binder).getService();
                //将当前activity添加为观察者
                service.addObserver(OtherActivity.this);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                service = null;
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(conn);
        }
    
        //更新UI
        @Override
        public void update(Observable observable, Object data) {
            // TODO Auto-generated method stub
            Person person=(Person) data;
            
            mContent.setText(person.toString());
        }
    }
    

    附上其他相关代码,三种方式都一样:

    Person类:

    package com.example.servicecallback;
    
    public class Person {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + "]";
        }
    
    }
    

    MainActiivty的布局文件:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="next" />
    
        <TextView
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />
    
    </LinearLayout>
    

    OtherActivity的布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <EditText
            android:id="@+id/edittext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="submit" />
    
        <TextView
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="content" />
    
    </LinearLayout>
    

    相关文章

      网友评论

      本文标题:Android中Service与多个Activity通信的三种方

      本文链接:https://www.haomeiwen.com/subject/sevlxxtx.html