Service和IntentService与Acticity之间的通信

一、Service与Activity之间通过IBinder对象进行通信

(1):在Service中必须要实现一个onBind(Intent intent)方法;
(2):在Service中需要自定义一个继承Bindler的类;在这个这个类中的一切 将会被传递到Activity中
        也就是说 其实 Activity与Service之间 通信靠的是onBind(0方法返回的那个IBinder对象,也就是上面那个对象
(3)在Activity中需要实现一个ServiceConnection对象,该对象必须实现两个方法:onServiceConnected,onServiceDisconnected.
(4)在onServiceConnected()方法中获取在Service中创建的Binder对象,因为在Service中的OnBind()方法返回的是
IBinder对象,所有也就要得到该对象,并通过该对象,来对Service中的Binder对象中的数据进行操作,从而达到了通信的目的。
(5)注意使用将Service和Activityvban绑定的方法来进行通信那么需要再Acticity中使用
bindService()启动的时候里面的参数就是:
第一个是一个从Activity跳转到Serviced的Intent (Intent intent=new Intent(this,myService.class)),
第二个是:一个serviceConnection对象,这个对象必须实现两个方法
第三个参数一般设置为:Service.BIND_AUTO_CREATE就可以了

在Service中的代码:

public class  BindService extends Service
{
    private int count;
    private boolean quit;
    // 定义onBinder方法所返回的对象
    private  MyBinder binder = new MyBinder();
    // 通过继承Binder来实现IBinder类
     public class MyBinder extends Binder  // ①
    {
        public int getCount()
        {
            // 获取Service的运行状态:count
            return count;
        }
    }
     // 必须实现的方法,绑定该Service时回调该方法
    @Override
     public IBinder onBind(Intent intent)
    {
        System.out.println("Service is Binded");
        // 返回IBinder对象
        return binder;
    }
    // Service被创建时回调该方法
    @Override
    public void onCreate()
    {
        super.onCreate();
        System.out.println("Service is Created");
        // 启动一条线程,动态地修改count状态值
        new Thread()
        {
            @Override
            public void run()
            {
                while (!quit)
                {
                    try
                    {
                        Thread.sleep(1000);
                    }
                    catch (InterruptedException e)
                    {
                    }
                    count++;
                }
            }
        }.start();
    }
    // Service被断开连接时回调该方法
    @Override
    public boolean onUnbind(Intent intent)
    {
        System.out.println("Service is Unbinded");
        return true;
    }
    // Service被关闭之前回调该方法
    @Override
    public void onDestroy()
    {
        super.onDestroy();
        this.quit = true;
        System.out.println("Service is Destroyed");
    }
}


在Activity中的代码:


public class MainActivity extends Activity
{
    Button bind, unbind, getServiceStatus;
    // 保持所启动的Service的IBinder对象
     BindService.MyBinder binder;
    // 定义一个ServiceConnection对象
     private ServiceConnection conn = new ServiceConnection()
    {
        // 当该Activity与Service连接成功时回调该方法
        @Override
        public void onServiceConnected(ComponentName name
                , IBinder service)
        {
            System.out.println("--Service Connected--");
            // 获取Service的onBind方法所返回的MyBinder对象
            binder = (BindService.MyBinder) service;  // ①
        }
        // 当该Activity与Service断开连接时回调该方法
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            System.out.println("--Service Disconnected--");
        }
    };
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取程序界面中的start、stop、getServiceStatus按钮
        bind = (Button) findViewById(R.id.bind);
        unbind = (Button) findViewById(R.id.unbind);
        getServiceStatus = (Button) findViewById(R.id.getServiceStatus);
        // 创建启动Service的Intent
        final  Intent intent = new Intent(this, BindService.class);
        bind.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View source)
            {
                // 绑定指定Service
                 bindService(intent, conn, Service.BIND_AUTO_CREATE);
            }
        });
        unbind.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View source)
            {
                // 解除绑定Service
                unbindService(conn);
            }
        });
        getServiceStatus.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View source)
            {
                 // 获取、并显示Service的count值
                Toast.makeText(MainActivity.this,
                        "Service的count值为:" +  binder.getCount(),
                        Toast.LENGTH_SHORT).show();  // ②
            }
        });
    }
}


其实一般当Acticity和Service进行通信的时候,每当activity通过intent启动一个Service的时候,
在Service中的onStartCommand()方法中最好是开启一个线程进行操作。也就是说Service子类的标准格式应该是:
   public int onStartCommand(Intent intent, int flags, int startId) {  
        new Thread(new Runnable() {  
           @Override  
          public void run() { 
              // 开始执行后台任务  
           }  
        }).start();  
        return super.onStartCommand(intent, flags, startId);  
   }  
           public IBinder onBind(Intent intent) {  
                MyBinder mBinder = new MyBinder();  
                    return mBinder;  
        }  
    class MyBinder extends Binder {  
      
      public void startDownload() {  
           new Thread(new Runnable() {  
               @Override  
                public void run() {  
                    // 执行具体的任务  
               }  
           }).start();  
       }  
     
   }  


二、使用广播通信的方式将Service或者IntentService与Activity进行联系
(在这里我只是编写了在Activity中写一个广播类,来实现从IntentService传递数据到Activity当然也可以在IntentService中写一个广播子类并实现onReceive()方法,来接受Activity传递过来的数据)

(1):使用广播通信的时候,要在Activity中,创建一个 BroadcastReceiver 子类处理收到的广播内容
(2):当然要也肯定要再Activity中注册Action
(3):因为在activity中接受内容的话,那么就必须要在IntentService中通过Intent中来发送广播
(4):加入发送的数据比较简单,可以直接通过Intent的Bundle来传递数据,也就是putExtral(),但是要是发送的数据比较
        多的话,或者说是可序列话的话,那么就必须使用Parcelable 接口或者使用Serializable接口来实现。传递数据的功能
        关于如何传递数据的话,看自己写的两者的差别和如何使用Bundle传递数据。(Parcelable 较为复杂但是建议使用 

在此处使用Parcelable  传递数据


实现Parcelable接口


假设我们下载任务完成后得到的是如下Item类的一组对象,那么我们将要怎么样将其传递给广播接收器呢?

public class Item {
    long id;
    String title;
    String img;
    int gallertClass;
    int count;
    int rcount;
    int fcount;
    long time;
    int size;
    *****
}

首先,必须要实现Item的序列化,序列化是通过实现Parcelable接口而实现的,这里我们将上面的类改造为ItemParcelable类,并实现Parcelable接口:

public class ItemParcelable  implements Parcelable {
    long    id;
    String  title;
    String  img;
    int     gallertClass;
    int     count;
    int     rcount;
    int     fcount;
    long    time;
    int     size;

    public ItemParcelable() {}

    public long getId() {
        return id;
    }

    public long setId(long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    @Override
    public int describeContents() {
        return 0;
}

    @Override
    public void  writeToParcel(Parcel dest, int flags) {
        dest.writeLong(id);
        dest.writeString(title);
        dest.writeString(img);
        dest.writeInt(gallertClass);
        dest.writeInt(count);
        dest.writeInt(rcount);
        dest.writeInt(fcount);
        dest.writeLong(time);
        dest.writeInt(size);
//根据类型写入数据
    }

        /**
    *实现Parcelable接口的类中,
    *必须有一个实现了Parcelable.Creator
    *接口的静态常量成员字段,并且它的名
    *字必须为CREATOR
    **/
    public static final  Parcelable.Creator<ItemParcelable> CREATOR = 
    new Parcelable.Creator<ItemParcelable>() {
        @Override
        public  ItemParcelable createFromParcel(Parcel in) {
             // 从包裹中读出数据,根据类型从in中读取数据,并且设置给item
            ItemParcelable item = new ItemParcelable();
            item.setId( in.readLong());
            item.setTitle(in.readString());
            item.setImg(in.readString());
            item.setGallertClass(in.readInt());
            item.setCount(in.readInt());
            item.setRcount(in.readInt());
            item.setFcount(in.readInt());
            item.setTime(in.readLong());
            item.setSize(in.readInt());
            return item;
        }

        @Override
        public  ItemParcelable[] newArray(int size) {
            return  new ItemParcelable[size];
        }
    };
}

        首先重写 writeToParcel 方法,将你的对象( ItemParcelable )序列化为一个 Parcel 对象,即:将类的数据写入外部提供的 Parcel 中,打包需要传递的数据到 Parcel 容器保存,以便从 Parcel 容器获取数据。
       接下来,重写 describeContents 方法,内容接口描述,默认返回0就可以。
      最后实例化静态内部对象 CREATOR 实现 Parcelable.Creator publicstatic final Parcelable.Creator CREATOR 接口。注意,其中 public static final 一个都不能少,内部对象 CREATOR 的名称也不能改变,必须全部大写。
      需重写本接口中的两个方法: createFromParcel(Parcelin) 实现从 Parcel 容器中读取传递数据值,封装成 Parcelable 对象返回逻辑层, newArray(int size)  创建一个类型为 T ,长度为 size 的数组,仅一句话即可( return new T[size] ),供外部类反序列化本类数组使用,这里的T就是 ItemParcelable 。还需要注意的是 writeToParcel createFromParcel 方法中序列化的顺序必须相同。



最后通过ItemParcelable传递数据

@Override
protected void o nHandleIntent(Intent intent) {
    ***
     ArrayList<ItemParcelable> items = downMethods(***);

    // 发送广播通知Activity
     Intent sendIntent = new Intent(MainClass.SERVICE_RECEIVER);
    sendIntent.putParcelableArrayListExtra(SERVICE_KEY_WORDS, items);
    getApplicationContext().sendBroadcast(sendIntent);
}

接受数据:
public class MainClass extends Activity {
     public  String SERVICE_RECEIVER = "com.art.zok.receiver";
    private Intent intent;              
    private MsgReceiver msgReceiver;

    public void onCreate(Bundle savedInstanceState) {
        // 动态注册广播接收器
        msgReceiver = new MsgReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(SERVICE_RECEIVER);
        registerReceiver(msgReceiver, intentFilter);

         //启动后台服务
        intent = new Intent(this, DownloadService.class);
        /*intent.putExtra(****)此处可以添加相应的参数*/
        startService(intent);
    }

    @Override
    public void onDestroy() {

       // 停止服务
        stopService(intent);

        // 注销广播
        unregisterReceiver(msgReceiver);

        super.onDestroy();
    }

    public class MsgReceiver extends BroadcastReceiver {
        @Override
 
public void onReceive(Context context, Intent intent) {
     ArrayList<ItemParcelable> items = intent
    .getParcelableArrayListExtra(DownloadService.SERVICE_KEY_WORDS);
    /**
     * for(ItemParcelable item : items) {
     *  item.getId();
     *    ***
     *}
     **/
****
}

    }
}





    当然上述只是使用了Intent和Activity通过广播进行数据的传输,当然也可以使用Service和
Activity通过广播进行数据的传输

猜你喜欢

转载自blog.csdn.net/qq_32400821/article/details/65706029