Android四大组件——Service——和Activity的通信

任务描述:在MyService里提供一个下载功能,然后再Activity中可以决定何时开始下载,以及随时查看下载进度。

按照之前的思路:在MyService中创建一个方法,用以对下载进行管理。然后在MainActivity中调用该方法。

1.修改布局如下:

 

 添加了一个控制下载的按钮。

2.在MyService中添加管理下载的方法

    public void startDownload(){
        Toast.makeText(this,"开始下载",Toast.LENGTH_LONG).show();
    }

3.在MainActivity中调用该方法

    public void startDownload(View view) {
        MyService myService = new MyService();
        myService.startDownload();
    }

现在运行看看效果:

 

 毫不意外的,崩掉了。

原因是空指针异常。

Toast.makeText(this,"开始下载",Toast.LENGTH_LONG).show();

this这里的上下文空指针异常。

不能通过该形式实现,换一个思路,借助前一篇中我们忽略的onBind()方法便可。如下:

实现思路:在MyService里创建一个专门的Binder对象来对下载进行管理。(通过绑定的形式来启动服务)

修改MyService的代码,修改后如下:

public class MyService extends Service {

    private static final String TAG = "MyService";
//新建DownloadBinder类,并让它继承Binder,任何在其内部提供开始下载的方法。
public class DownloadBinder extends Binder{ public void startDownload(){ Log.d("MyService","开始下载"); Toast.makeText(getApplicationContext(),"开始下载",Toast.LENGTH_LONG).show(); } } @Override public IBinder onBind(Intent intent) { return new DownloadBinder(); //将返回值修改为创建一个DownloadBinder的对象 } @Override public void onCreate() { super.onCreate(); Log.d(TAG,"onCreate"); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG,"onDestroy"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG,"onStartCommand"); return super.onStartCommand(intent, flags, startId); } }

修改MainActivity的代码,修改后如下:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    public MyService.DownloadBinder downloadBinder;

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

    //开启服务
    public void startService(View view) {
        Intent intent = new Intent();
        intent.setClass(this, MyService.class);
        startService(intent);
    }

    //结束服务
    public void stopService(View view) {
        Intent intent = new Intent();
        intent.setClass(this, MyService.class);
        stopService(intent);
    }

    private ServiceConnection serviceConnection = new ServiceConnection() { //创建一个ServiceConnection的内部类,并重写里面的方法。
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) { //该方法会在Activity和Service绑定成功的时候调用。
            Log.d(TAG,"onServiceConnected");
            downloadBinder =(MyService.DownloadBinder) service; //通过向下转型得到了DownloadBinder的实列
            downloadBinder.startDownload();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) { //该方法只有在Service的创建崩溃或者被杀掉的时候才会调用,并不常用。

        }
    };
    //开始下载
    public void startDownload(View view) {
        Intent intent = new Intent();   
        intent.setClass(this,MyService.class); 
        bindService(intent,serviceConnection, BIND_AUTO_CREATE);//绑定服务
    //第一个参数是Intent对象,第二个参数是前面创建出来的ServiceConnection实例,
//第三个参数是一个标志位,这里的BIND_AUTO_CREATE表示在Activity和Service绑定后自动创建Service.
} }

现在来运行一下:

 

 可以看到,以及运行成功了。

 

任何一个Service在整个应用程序范围内都是通用的。即MyService不仅可以和MainActivty绑定,还可以和任何一个其他的Activity进行绑定,并且在绑定完成后,它们都可以获取相同的DownloadBinder实例。

posted @ 2022-08-19 21:08  虞美人体重90  阅读(350)  评论(0编辑  收藏  举报