Android基础学习之Service

本文详细介绍了Android中的服务组件,包括服务的基本概念、启动方式、绑定方式、生命周期回调等,并提供了多个示例代码,帮助读者理解服务的使用场景及其实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android四大应用组件:
Activity 可见可交互 前台 界面处理
Service 不可见不可交互 后台管理(耗时任务)
BroadcastRceiver 通信机制(活动和服务,应用和应用,应用和系统)
ContentProvider 数据共享机制

它们之间的共同之处:
用法相似
跨进程交互
使用intent来交互

Service类
java.lang.Object
android.content.Context
android.content.ContextWrapper
android.app.Service

ServiceConnection 接口

private ServiceConnection conn=new ServiceConnection() {

        @Override  //当检测到C/S连接断开调用该方法
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

        @Override //1.当检测到客户端(activity)和服务端(service)连接成功就会调用该方法
        //2.当调用该方法是会传入一个IBinder对象service
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub

        }
};

Service的特点:
1)与Activity是同级
2)不是一个单独的进程(默认没有特别指定,就在自己应用的进程空间中)
3)不是一个单独的线程(默认没有特别指定,就在主线程中运行,service中代码不能阻塞)
4)后台工作,不可见

服务的分类:
本地服务:同一个进程访问,当进程结束一起结束
远程服务:在不同进程访问,通过AIDL(接口)实现 当访问进程结束还可以在后台继续运行。
跨进程的进行服务访问图示:

这里写图片描述

service用两种用法 :
1.非绑定
2.绑定
这里写图片描述
这里写图片描述
这里写图片描述

service使用:
用法1:非绑定方式
1.启动
一般从活动中调用 startService() ==> 服务调用 onCreate()(创建时只调用一次)
onStartCommand() (可调用多次)
2.停止
一般从活动中调用 stopService() ==> 服务调用 onDestroy() (只调用一次) 或 服务直接调用stopSelf()
如果有绑定服务,不能停止服务

用法2:绑定方式
启动
绑定
一般从活动中调用 bindService() ==>服务调用 onBind() (只调用一次) 如果服务没有创建一般自动创建
松绑
一般从活动中调用 unbindService() ==>服务调用 onUnBind() 如果所有客户端都松绑服务还会调用
onDestroy()
停止

非绑定方式:
这里写图片描述
绑定方式:
这里写图片描述
注:图中ICount接口为自定义接口


基于本地服务示例
示例1:
使用非绑定的方式实现使用服务端运行两个子线程,分别做播放音乐和打印信息。

服务端:

public class MyService extends Service {
    private static final String TAG = "ql debug";
    private MediaPlayer mediaPlayer;
    private Thread printThread;//打印线程
    private int cnt = -1;
    private boolean active = false;//服务运行标识位

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mediaPlayer = MediaPlayer.create(this, R.raw.hold_my_hand);
        mediaPlayer.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        cnt = intent.getIntExtra("number", -1);//得到活动传过来的数值
        active = true;
        printThread = new Thread() {
            @Override
            public void run() {
                while (active) {
                    cnt--;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, "progress value--------->" + cnt);
                }
            }
        };
        printThread.start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mediaPlayer.stop();
        active=false;
        Log.e(TAG,"service destroy");
    }
}

活动端:

public class MainActivity extends Activity implements OnClickListener {
    int number = 100;
    private Button btn_satrtService;
    private Button btn_stopService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn_satrtService = (Button) findViewById(R.id.btn_satrtService);
        btn_stopService = (Button) findViewById(R.id.btn_stopService);
        btn_satrtService.setOnClickListener(this);
        btn_stopService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        switch (v.getId()) {
        case R.id.btn_satrtService:
            intent.setAction("com.ql.servicedemo.action");
            intent.putExtra("number", number);
            startService(intent);// 启动服务
            number++;
            break;
        case R.id.btn_stopService:
            intent.setAction("com.ql.servicedemo.action");
            stopService(intent);//停止服务
            break;

        default:
            break;
        }
    }
}

清单文件进行服务的注册和定义动作字符串:(组件的注册在< application>< /application>标签中)

<service
            android:name="com.ql.servicedemo.MyService"
            android:enabled="true"
            android:exported="true" >
            <intent-filter >
                <action android:name="com.ql.servicedemo.action"/>
            </intent-filter>
</service>

示例2:
使用绑定的方式实现使用服务执行任务,并返回反馈信息。服务做打印任务,活动可以获取服务任务进度。

首先定义一个接口(因为Binder子类MyBinder已经继承),两个方法分别是取值和设置值:

public interface ICount {
    public int getCount();
    public void setCount(int cnt);
}

服务端:

public class MyService extends Service {
    private static final String TAG = "ql debug";
    private int cnt = 0;
    private boolean active = false;

    private class MyBinder extends Binder implements ICount{

        @Override
        public int getCount() {
            return cnt;
        }

        @Override
        public void setCount(int cnt) {
            MyService.this.cnt = cnt;
        }   
    }

    MyBinder binder = new MyBinder();

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.返回到服务的通信通道。
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        new Thread() {
            @Override
            public void run() {
                active = true;
                while (active) {
                    cnt++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, "progress value--------->" + cnt);
                }
            }
        }.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        active=false;
        Log.e(TAG,"service destroy");
    }
}

活动端:

public class MainActivity extends Activity implements OnClickListener {
    int number = 100;
    private Button btn_satrtService;
    private Button btn_stopService;
    private TextView txt_result;

    private ICount count;

    private class MyConn implements ServiceConnection {

        @Override// 当远程绑定成功传入IBinder对象是一个代理对象service
        public void onServiceConnected(ComponentName name, IBinder binder) {
            count = (ICount) binder;
        }

        @Override//在service被系统意外回收才会调用
        public void onServiceDisconnected(ComponentName name) {
            count = null;
        }
    }

    MyConn conn = new MyConn();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Intent service=new Intent("com.ql.servicedemo2.action");
        bindService(service, conn, BIND_AUTO_CREATE);//绑定服务

        txt_result = (TextView) findViewById(R.id.txt_result);

        btn_satrtService = (Button) findViewById(R.id.btn_satrtService);
        btn_stopService = (Button) findViewById(R.id.btn_stopService);
        btn_satrtService.setOnClickListener(this);
        btn_stopService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_satrtService:
            txt_result.setText("来自service子线程的计数值:" + count.getCount());//获取服务任务进度
            break;
        case R.id.btn_stopService:
            count.setCount(500);//改变服务任务的值
            break;

        default:
            break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);//松绑服务
    }
}

清单文件服务的注册和动作设置见示例1

示例3:
使用广播进行活动和服务进行通信,需要创建广播的子类和在服务端注册广播接收器。

本例原理图示
这里写图片描述

java代码:

服务端

public class MyService extends Service {
    //两个常量,读和写
    private static final String READREQ = "read service data request";
    private static final String WRITEREQ = "write service data request";
    private static final String TAG = "ql debug";
    private int cnt = 0;
    private boolean active = false;//服务存活标识位(优化处理)

    /**
     * 用于通信的广播类
     * 
     * @author qinlang
     * 
     */
    private class MyReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String command = intent.getStringExtra("command");
            Log.v(TAG, "service receive command:" + command);
            Intent i = new Intent("com.activity.receiver.action");
            if (READREQ.equals(command)) {
                i.putExtra("count", cnt);
                sendBroadcast(i);//发送广播
            }
            if (WRITEREQ.equals(command)) {
                cnt = 0;
            }
        }
    }

    MyReceiver receiver = new MyReceiver();
    IntentFilter filter = new IntentFilter();

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.返回到服务的通信通道。
        // throw new UnsupportedOperationException("Not yet implemented");
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //动态注册广播
        filter.addAction("com.service.receiver.action");
        registerReceiver(receiver, filter);//注册activity用的广播接收器

        new Thread() {
            @Override
            public void run() {
                active = true;
                while (active) {
                    cnt++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, "progress value--------->" + cnt);
                }
            }
        }.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        active = false;
        unregisterReceiver(receiver);//移除广播注册
        Log.e(TAG, "service destroy");
    }
}

活动端

public class MainActivity extends Activity implements OnClickListener {
    private static final String READREQ = "read service data request";
    private static final String WRITEREQ = "write service data request";
    int number = 100;
    private Button btn_satrtService;
    private Button btn_stopService;
    private TextView txt_result;

    /**
     * 用于通信的广播类
     * @author qinlang
     *
     */
    private class MyReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            // 这里可以操作UI线程的视图显示
            txt_result.setText("service端子线程当前计数值为:" + intent.getIntExtra("count", -1));
        }
    }

    MyReceiver receiver = new MyReceiver();
    IntentFilter filter = new IntentFilter();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //动态注册广播
        filter.addAction("com.activity.receiver.action");
        registerReceiver(receiver, filter);//注册service用的广播接收器

        Intent service = new Intent("com.ql.servicedemo3.action");
        startService(service);//启动服务

        txt_result = (TextView) findViewById(R.id.txt_result);

        btn_satrtService = (Button) findViewById(R.id.btn_satrtService);
        btn_stopService = (Button) findViewById(R.id.btn_stopService);
        btn_satrtService.setOnClickListener(this);
        btn_stopService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_satrtService:
            sendBroadcastToService(READREQ);//读取服务端任务进度
            break;
        case R.id.btn_stopService:
            sendBroadcastToService(WRITEREQ);//设置服务端任务值
            break;

        default:
            break;
        }
    }

    private void sendBroadcastToService(String command) {
        Intent intent=new Intent("com.service.receiver.action");
        intent.putExtra("command", command);
        sendBroadcast(intent);//发送广播
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

效果:
这里写图片描述


基于远程服务

基于远程,就是服务和使用服务的活动不是一个进程(一个app)内。在android中每个应用都运行自己进程中,一个应用不能直接访问其他应用内存空间。为了在应用之间进行通信,android提供一种IPC的实现:AIDL (android interface definition language),是IPC轻量级实现。采用java开发语法规则来定义AIDL文件,并提供一个工具(aidl.exe)生成stub存根(java代码文件)。
AIDL 用来让应用(client端)能够被其他应用service(server端)的方法。

AIDL是一种代理模式,应用在远程代理的实现。
代理模式示意图:
这里写图片描述
应用使用原理图:
这里写图片描述
.aidl文件过程:
这里写图片描述

AIDL支持有限的数据类型:
1.java 简单类型 int
2.java 引用类型 String CharSquence
3.List和Map
如果自定义类型在AIDL中使用,必须定义自定义类型的aidl文件。
AIDL文件语法:
类似java 接口定义
支持java 常见类型
自定义类型必须Pacelable序列化(Parcelable接口是在android中实现序列化的接口)

创建AIDL步骤:
1.工程中创建.aidl文件 类似java语法
不能加public
客户端设置 in
服务端设置 out
客户/服务端 inout
支持基本数据类型,不支持 流类 InputStream类.
2.如果.aidl文件编写正确ADT生成java接口文件
不用关心具体内容自动维护

远程调用步骤

客户端:
1.定义aidl文件(代理对象) 定义需要服务端提供功能方法
2.通过ServiceConnection接口的onServiceConnected() 获得代理对象,用aidl生成java代码中方法来获得

private class AddServiceConn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 当远程绑定成功传人IBinder对象是一个代理对象service
            proxy=IAddService.Stub.asInterface(service);
            proxy.foo1();//方法一
            proxy.foo2();//方法二
            proxy.foo3();//方法三
            //...
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            proxy=null;
        }
}

3.使用代理对象访问服务端的方法

服务端:
1.定义aidl文件(代理对象) 定义需要服务端提供功能方法
2.在onBind() 定义重写stub中的方法来构造stub子类对象
return new YourService.Stub(){
void foo1(){}
void foo2(){}
void foo3(){}
}

示例1:
使用代理对象来远程连接服务,示例实现服务的加法任务。
注:.aidl文件包名,cilent端必须要和service端一致,否则报错
如:
这里写图片描述

本例原理图和示意图:
这里写图片描述
这里写图片描述

代码:

服务端:
(别忘了注册服务和设置服务动作字符串)

1.编写.aidl文件,文件名IAddService.aidl。

package com.ql.testservice1;
interface IAddService{
    int add(in int value1,in int value2);
}

2.服务java代码

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return new IAddService.Stub() {

            @Override
            public int add(int value1, int value2) throws RemoteException {
                return value1 + value2;
            }
        };
    }
}

client端:
1.编写.aidl文件(与服务端的一致)
2.活动java代码

public class MainActivity extends Activity {
    private IAddService proxy;// 代理对象

    private class ServiceConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 当远程绑定成功传入IBinder对象是一个代理对象service
            proxy = IAddService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            proxy = null;
        }
    }

    ServiceConn conn = new ServiceConn();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 绑定服务
        Intent intent = new Intent("com.ql.testservice.action");
        bindService(intent, conn, BIND_AUTO_CREATE);

        final EditText editText1 = (EditText) findViewById(R.id.editText1);
        final EditText editText2 = (EditText) findViewById(R.id.editText2);
        final TextView textView = (TextView) findViewById(R.id.textView3);
        Button button = (Button) findViewById(R.id.button1);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                int v1, v2, res = -1;
                v1 = Integer.parseInt(editText1.getText().toString().trim());
                v2 = Integer.parseInt(editText2.getText().toString().trim());
                try {
                    res = proxy.add(v1, v2);//步骤3的“使用代理对象访问服务端的方法”
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                textView.setText("计算结果:" + res);
            }
        });
    }
}

效果:
这里写图片描述

示例2
本例演示自定义类型在AIDL中的使用,自定义类型中有三个对象。
用法步骤:
1.编写自定义bean类,必须实现Parcelable接口进行序列化
2.编写bean类的.aidl文件
3.加入.aidl代理文件

自定义bean类写法步骤:
1.实现Parcelable接口,重写writeToParcel(Parcel dest, int flags)方法。
2.要有一个带Parcel类型参数的构造方法
public XXX(Parcel in) {

}
3.定义常量CREATOR给aidl生成的代码用到的(这是个写死了的写法,照着写。范型类XXX为你的bean类)

public static final Parcelable.Creator<XXX> CREATOR = new Parcelable.Creator<XXX>() {

        @Override
        public XXX createFromParcel(Parcel in) {
            return new XXX(in);
        }

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

测试demo
1.定义bean类,文件名:Product.java

//必须实现Parcelable接口否则AIDL编译出错
public class Product implements Parcelable {
    private int id;
    private String name;
    private float price;

    public Product() {

    }

    //2.将Parcel对象中数据取出来.
    public Product(Parcel in) {
        id = in.readInt();
        name = in.readString();
        price = in.readFloat();
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

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

    @Override//1.将序列化用的数据写Parcel对象,dest是输出参数
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
        dest.writeFloat(price);
    }

    // 3.定义常量 给aidl生成代码用到的. 
    public static final Parcelable.Creator<Product> CREATOR = new Parcelable.Creator<Product>() {

        @Override
        public Product createFromParcel(Parcel in) {
            return new Product(in);
        }

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

2.编写bean的.aidl文件,文件名:Product.aidl

package com.ql.testservice2;
parcelable Product;

3.加入代理.aidl文件,文件名:IAddService.aidl
要导入具体包名和类名,它不会自动寻找类所在位置
说明:
文件中定义了一个Product类型(自定义类型)的getProduct()方法,一个Map类型的getMap()方法。

package com.ql.testservice2;
import com.ql.testservice2.Product;
interface IAddService{
    int add(in int value1,in int value2);
    Product getProduct();
    Map getMap(in String country,in Product product);
}

4.服务端java代码

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        //返回IBinder对象  对应客户端用来生成代理对象用的.
        return new IAddService.Stub() {

            @Override
            public Product getProduct() throws RemoteException {
                Product product=new Product();
                product.setId(1000);
                product.setName("宝马");
                product.setPrice(1000000);
                return product;
            }

            @Override
            public Map getMap(String country, Product product) throws RemoteException {
                Map map=new HashMap();
                map.put("country", country);
                map.put("id",product.getId());
                map.put("name", product.getName());
                map.put("price", product.getPrice());
                return map;
            }

            @Override
            public int add(int value1, int value2) throws RemoteException {
                return value1 + value2;
            }
        };
    }
}

以下为另一个应用的代码,用于测试连接远程服务
1.自定义bean,自定义bean的.aidl 文件和代理.aidl文件和服务端的一致(包名也要一致)。
2.活动测试代码

public class MainActivity extends Activity {
    private IAddService proxy;// 代理对象

    private class ServiceConn implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 当远程绑定成功传入IBinder对象是一个代理对象service
            proxy = IAddService.Stub.asInterface(service);
        }

        @Override//在service被系统意外回收才会调用
        public void onServiceDisconnected(ComponentName name) {
            proxy = null;
        }

    }

    ServiceConn conn = new ServiceConn();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 绑定服务
        Intent intent = new Intent("com.ql.testservice2.action");
        bindService(intent, conn, BIND_AUTO_CREATE);

        final EditText editText1 = (EditText) findViewById(R.id.editText1);
        final EditText editText2 = (EditText) findViewById(R.id.editText2);
        final TextView textView = (TextView) findViewById(R.id.textView3);
        final TextView textView2 = (TextView) findViewById(R.id.result2);
        Button button = (Button) findViewById(R.id.button1);
        Button button2 = (Button) findViewById(R.id.button2);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                int v1, v2, res = -1;
                v1 = Integer.parseInt(editText1.getText().toString().trim());
                v2 = Integer.parseInt(editText2.getText().toString().trim());
                try {
                    res = proxy.add(v1, v2);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                textView.setText("计算结果:" + res);
            }
        });

        button2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    Product product = proxy.getProduct();
                    StringBuilder builder = new StringBuilder();
                    builder.append("product:" + product + "\n");
                    builder.append("id:" + product.getId() + "\n");
                    builder.append("name:" + product.getName() + "\n");
                    builder.append("price:" + product.getPrice() + "\n");
                    Map map = proxy.getMap("china", product);
                    builder.append("map object:" + map);
                    textView2.setText(builder.toString());

                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

效果:
这里写图片描述


(此处未整理)

当service被意外销毁时如何处理?
1.使用本地绑定service(activity和service绑定) 随activity销毁而销毁.
2.服务被系统意外销毁后,继续服务处理
public int onStartCommand (Intent intent, int flags, int startId)
返回值决定重启服务的方式:
2.1 START_STICKY 默认 销毁服务,重新创建服务会按空的intent对象执行任务
2.2 START_NOT_STICKY 不重启
2.3 START_STICKY_COMPATIBILITY 根据之前intent来启动

service 要指定其他进程运行,可设置:
android:process=”:remote” 可将服务放在单独的进程中,参数:用包名:retmote(如无包名表示本进程)


上文中代理模式示意图demo在这里:
main.java

public class Main {
    public static void main(String[] args) {
        Printable p=new PrintProxy("rose");
        System.out.println("现在是:"+p.getPrinterName());
        p.setPrinterName("alice");
        System.out.println("现在是"+p.getPrinterName());
        p.print("hello proxy world");

    }

}

Printable.java

public interface Printable {
    public abstract void setPrinterName(String name);
    public abstract String getPrinterName();
    public abstract void print(String string);
}

Printer.java

public class Printer implements Printable{
    private String name;
    public Printer() {
        // TODO Auto-generated constructor stub
        heavyJob("正在产生Printer对象实例");
    }

    public Printer(String name) {
        // TODO Auto-generated constructor stub
        this.name=name;
        heavyJob("正在产生Printer对象实例");

    }

    private void heavyJob(String string) {
        // TODO Auto-generated method stub
        System.out.println(string);
        for(int i=0;i<5;i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.print(".");
        }
        System.out.println("完成");
    }

    @Override
    public void setPrinterName(String name) {
        // TODO Auto-generated method stub
        this.name=name;
    }

    @Override
    public String getPrinterName() {
        // TODO Auto-generated method stub
        return this.name;
    }

    @Override
    public void print(String string) {
        // TODO Auto-generated method stub
        System.out.println("<<<"+this.name+">>>");
        System.out.println(string);
    }
}

PrintProxy.java

//代理:要用再建立
//不需要本人处理的工作交出去,需要建立一个代理 
//代理能力有限的,遇到超出能力范围还是找本人来处理

public class PrintProxy implements Printable{
    private String name;
    private Printer real;//委托对象

    public PrintProxy() {
        // TODO Auto-generated constructor stub
    }
    public PrintProxy(String name) {
        // TODO Auto-generated constructor stub
        this.name=name;
    }

    @Override
    public void setPrinterName(String name) {
        // TODO Auto-generated method stub
        if(real!=null){
            real.setPrinterName(name);
        }
        this.name=name;
    }

    @Override
    public String getPrinterName() {
        // TODO Auto-generated method stub
        return this.name;
    }

    @Override
    public void print(String string) {
        // TODO Auto-generated method stub
        realize();
        real.print(string);

    }

    private void realize(){ //产生本人对象
        if(real==null){
            real=new Printer(name);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值