Android中Service與多個Activity通訊

  因爲項目須要,咱們有時候須要在service中處理耗時操做,而後將結果發送給activity以更新狀態。一般狀況下,咱們只須要在一個service與一個activity之間通訊,一般這種狀況下,咱們使用最多的是經過回調接口。具體作法是在service中定義一個接口,在activity中實現該接口,並經過bindservice來傳入。實現方式很簡單,在此再也不贅述。java

  當須要將service中的結果一次發送給多個activity時,咱們又該如何實現呢?通過多個項目的積累,總結了三種實現的方式。分別是回調接口、廣播接收者和觀察者模式android

1.回調接口的方式,與單個service與單個activity通訊相似,只是將service中的接口變爲接口的集合,每一個須要通訊的activity都實現接口,而後在獲取結果後,循環調用集合中的實現類,來與多個activity進行通訊,代碼以下:app

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);
            }
        }
    };
}
View Code

第一個activity:async

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());
    }
}
View Code

第二個activity:ide

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());
    }
}
View Code

 

2.經過廣播接收者,在service中執行完耗時操做後,將結果以廣播的形式發送,在全部的activity中註冊廣播,接收到結果後更新UI,這種方式比較簡單,也是筆者比較推薦的方式。由於耗時的操做結果不須要以handler的方式發送到主線程,能夠直接在子線程中發送廣播,接收者始終運行在主線程中。代碼以下:佈局

Service類:this

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);
    }
}
View Code

第一個activity:spa

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());
        }
    }
}
View Code

另外一個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());
        }
    }
}
View Code

 

3.使用觀察者模式,service爲被觀察者,全部的activity爲觀察者,當service中的內容發生改變時,通知全部的activity來更新,代碼以下:

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);
        }
    }
}
View Code

第一個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());
    }

}
View Code

第二個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());
    }
}
View Code

 

附上其餘相關代碼,三種方式都同樣:

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 + "]";
    }

}
View Code

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>
View Code

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>
View Code

因爲筆者的水平有限,若有錯漏,請各位留言指正,感激涕零!

以上雖有借鑑別人的思想,可是源代碼均爲原創。請尊重筆者的勞動成果。若是轉載,請註明出處,謝謝!

全文完

相關文章
相關標籤/搜索