第十章 后台默默的劳动者-探究服务

10.1 服务是什么
    服务(service)是实现程序后台运行的解决方案,适合执行那些不需要和用户交互而且还要求长期运行的任务


    注意1:它依赖于创建服务时所在的应用程序进程. 应用程序被杀死,服务结束。
    注意2:它不会在应用程序切换时,关闭掉

10.2 Android 多线程编程

    10.2.1 线程的基本用法
        方法一:
        class MyThread extends Thread{
            @Override
            public void run(){            
            

            }
        }
        //启动方法
        new MyThread().start()

        方法二:
        class MyThread implements Runnable{
            @Overried
            public void run(){

            }            
        }
        //启动方法
        MyThread myThread = new MyThread();
        new thread(myThread).start();


        方法三:
        new Thread(new Runnable(){        
            @Override
            public void run(){

            }        
        });

    10.2.2 在子线程中更新UI
        android 更新应用程序的UI元素,必须在主线程中更新。

        为了解决这个问题:google提供了Hander, 这个Handler,是在主线程运行的,
        通过子线程发送更新UI数据,handler再通过数据更新UI。        
        类似队列,子线程发送数据进队列,handler取队列数据处理

        public static final int UPDATE_TEXT = 1

        private Hander handler = new Handler(){
            public void handleMessage(Message msg){
            
                switch(msg.what){
                    case UPDATE_Text:
                        //UI 操作
                }
            
            }
        }
        


        new Thread(new Runnable){
        
            @Override
            public void run(){
                Message message = new Message();
                message.what = UPDE_TEXT;
                handler.sendMessage(message);
            }
            
        }
    

    10.2.3 解析异步消息处理机制
        android 的异步消息处理主要由4个部分组成:Message, handler, MessageQueue 和 Looper

        a, Message,  是用于不同线程之间交换少量数据。
        b, Handler,  用于发送消息(handler.sendMessage)和处理消息(handler中的handlerMessage)的,
        c, MessageQueue, 消息队列,主要存放Handler发送的消息。每个线程只会有一个MessageQueue队列
        d, Looper, 是每个线程中的MessageQueue的管家,调用了Looper的loop()方法后,就会进入到无限循环,
            每当发现MessageQueue存在一条消息,则将它取出,并传递到Handler的MandleMessage中
            每个线程也只会有一个Looper对象

    10.2.4 使用AsyncTask
        AsyncTask也是基于异步消息处理机制
        
        AsyncTask有三个参数,
            params, 执行Aysnc时,需要传入的参数,可用于后台操作
            Progress, 后台任务执行时,如果要在界面上显示当前的进度,则使用指定的泛型作为进度单件
            Result, 当任务执行完毕后,如果需要对结果进行返回,则使用指定的泛型作为返回值类型

        public class DownloadTask  extends AsyncTask<Void, Integer, Boolean> {

             @Override
            protected void onPreExecute() {
                    progressDialog.show();      //显示进度对话框
         }

        @Override
         protected Boolean doInBackground(Void... voids) {
                while(true){
                    int downloadPercent = doDownLoad();     //虚构的下载方法
                    publishProgress(downloadPercent);
                    if(downloadPercent >= 100){
                            break;
                        }
         }
                return true;
        }

            @Override
            protected void onProgressUpdate(Integer... values) {
                progressDialog.setMessage("Downloaded" + values[0] + "%");
            }

            @Override
            protected void onPostExecute(Boolean result) {
                progressDialog.dismiss(); //关闭进度对话框
                if(result){
                    Toast.makeText(context, "Download succeeded", Toast.LENGTH_LONG).show();
                }else {
                    Toast.makeText(context, "Download failed", Toast.LENGTH_LONG).show();
                }
            }
        }
        //启动这个任务
        new DownloadTask().execute();

10.3 服务的基本用法
    10.3.1 定义一个服务
        new->Service->Service
        

public class MyService extends Service {
    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();
    }
    //执行体
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
    //销毁时
    @Override
    public void onDestroy() {
        super.onDestroy();
    }

}

    同时在AndroidManifest.xml中注册

    10.3.2 启动和停止服务
        //启动
        Intent startIntent = new Intent( this, MyService.class );
        startService(startIntent);
        //关闭
        Intent stopIntent = new Intent(this, MyService.class);
        stopService(stopIntent);
        
        
    10.3.3 活动和服务进行通信
        第一步,在MyService中创建一个类,继承Binder, 改相关代码,如下
        

public class MyService extends Service {

    private DownloadBinder mBinder = new DownloadBinder();

    class DownloadBinder extends Binder {

        public void startDownload(){
            Log.d("MyService", "startDownload executed");
        }
        public int getProcess(){
            Log.d("Myservice", "getProgredd executed");
            return 0;
        }
    }

    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MyService", "onCreate executed");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MyService", "onStartCommand executed");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.d("MyService", "onDestroy executed");
        super.onDestroy();
    }
}

    第二步:在MainActivity中创建一个MainActivity中的类中类,再创建一个ServiceConnection的匿名类.
        
    
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private MyService.DownloadBinder downloadBinder;

    private Button start_service;
    private Button stop_service;

    private Button bind_service;
    private Button unbind_service;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downloadBinder = (MyService.DownloadBinder) service;
            downloadBinder.startDownload();
            downloadBinder.getProcess();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

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

        start_service = (Button) findViewById(R.id.start_service);
        stop_service = (Button) findViewById(R.id.stop_service);

        start_service.setOnClickListener(this);
        stop_service.setOnClickListener(this);

        bind_service = (Button) findViewById(R.id.bind_service);
        unbind_service = (Button) findViewById(R.id.unbind_service);

        bind_service.setOnClickListener(this);
        unbind_service.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.start_service:
                Intent startIntent = new Intent(MainActivity.this, MyService.class);
                startService(startIntent);
                break;
            case R.id.stop_service:
                Intent stopIntent = new Intent(MainActivity.this, MyService.class);
                stopService(stopIntent);
                break;
            case R.id.bind_service:
                Intent bindIntent = new Intent(this, MyService.class);
                bindService(bindIntent, connection, BIND_AUTO_CREATE);
                break;
            case R.id.unbind_service:
                unbindService(connection);
                break;
            default:
                break;
        }
    }
}

        
    第三步:开启服务,看打印日记,那些方法运行,关闭服务,那些方法被调用,还有绑定服务,和解绑服务

    注意,绑定服务,再解绑服务,就好,不然,会报错, 因为要绑定,才能解绑

    
10.4 服务的生命周期

    第一点:服务只会存在一个实例,
    第二点:调用了context中StartCommand方法,则会启动onStartCommand()方法,如果没有创建启动过,则先会调用OnCreate;
        结束时,一定要调用unbindService,和stopService;

    第三点:如果,开启服务,以绑定服务,要依次,停止服务和解绑服务

10.5 服务的更多技巧
    
    10.5.1 使用前台服务
        前台服务的后台服务最大的区别是,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息
        
        这里不列出代码了,有问题,看这个https://blog.csdn.net/julicliy/article/details/104313756

    10.5.2 使用IntentService
            服务的代码都默认是在主线程运行了,很容易出现ANR( Application Not Responding )
            
        onStartCommand中加入
        new Thread(new Runnable){
            @Override
            public void run(){
                
                //处理具体事物
                stopSelf();  //停止服务
                
            
            }
        }
        


        intentService类为了创建一个异步的,会自动停止的服务。    


public class MyIntentService extends IntentService {

    public MyIntentService(){
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        Log.d("MyIntentService", "SubThread id is " + Thread.currentThread().getId());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("MyIntentService", "onDestroy executed");
    }
}

在Mainfest.xml中注册  <application><service android:name=".MyIntentService"/></application>

启动该服务
                Intent intentService = new Intent(MainActivity.this, MyIntentService.class);
                startService(intentService); 
    
        
        
        


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值