Android基础知识——探究服务
发布日期:2021-05-19 15:52:52 浏览次数:21 分类:精选文章

本文共 12205 字,大约阅读时间需要 40 分钟。

Android服务与多线程编程指南

1. 服务是什么

服务是Android中实现程序后台运行的解决方案,非常适合执行那些不需要与用户交互且要求长期运行的任务。服务并不是运行在独立的进程中,而是依赖于创建服务时所在的应用程序进程。服务不会自动开启线程,所有代码默认运行在主线程中。


2. Android多线程编程

在Android中,当我们执行耗时操作(如发起网络请求)时,服务器可能无法立即响应,若不将此类操作放在子线程中运行,会导致主线程被阻塞,从而影响软件使用。以下将学习Android中的多线程编程。


2.1 线程的基本用法

要创建线程,可以选择以下方式:

  • 继承Thread类并重写run()方法

    class MyThread extends Thread {    @Override    public void run() {        // 处理具体逻辑    }}// 启动线程new MyThread().start();
  • 实现Runnable接口并重写run()方法

    class MyThread implements Runnable {    @Override    public void run() {        // 处理具体逻辑    }}// 创建并启动线程MyThread thread = new MyThread();new Thread(thread).start();
  • 使用匿名类实现Runnable接口

    public void onClick(View view) {    new Thread(new Runnable() {        @Override        public void run() {            // 处理具体逻辑        }    }).start();}

  • 2.2 在子线程中更改UI

    Android UI是线程不安全的,若要更新UI元素,必须在主线程中进行,否则会抛出异常。以下是两种常用的解决方法:

  • 使用Handler

    public class MainActivity extends AppCompatActivity {    TextView textView;    public final int CHANGE_TEXT = 1;    Handler handler = new Handler() {        @Override        public void handleMessage(@NonNull Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case CHANGE_TEXT:                    textView.setText("asdasd");                    break;                default:                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button = (Button) findViewById(R.id.button);        textView = (TextView) findViewById(R.id.text_View);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                new Thread(new Runnable() {                    @Override                    public void run() {                        Message message = new Message();                        message.what = CHANGE_TEXT;                        handler.sendMessage(message);                    }                }).start();            }        });    }}
  • 使用runOnUiThread

    public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button = (Button) findViewById(R.id.button);        final TextView textView = (TextView) findViewById(R.id.text_View);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                new Thread(new Runnable() {                    @Override                    public void run() {                        MainActivity.this.runOnUiThread(new Runnable() {                            @Override                            public void run() {                                textView.setText("asdsad");                            }                        });                    }                }).start();            }        });    }}

  • 2.3 解析异步处理机制

    Android中的异步消息处理主要由以下四个部分组成:

  • Message:包含描述和任意数据对象的消息,用于发送给Handler。
  • Handler:用于发送和处理消息。通过sendMessage()方法发送消息,消息经过一系列处理后传递到handleMessage()方法中。
  • MessageQueue:消息队列,内部以单链表存储消息。每个线程中只会有一个MessageQueue对象。
  • Looper:每个线程中的MessageQueue管家,调用loop()方法进入无限循环,处理消息。
  • 消息通过Looper和MessageQueue进行传递,最终在Handler的handleMessage()方法中执行,确保UI操作在主线程中进行。


    2.4 使用AsyncTask

    AsyncTask是Android提供的用于在子线程中对UI操作的工具,原理基于异步消息处理机制。创建AsyncTask子类时,需要指定三个泛型参数:

  • Params:传入的参数,用于后台任务使用。
  • Progress:后台任务执行时,若需显示进度,使用指定的泛型。
  • Result:任务执行完毕后,若需返回结果,使用指定的泛型。
  • 示例:

    public class DownloadTask extends AsyncTask
    { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Boolean doInBackground(Void... voids) { while (true) { publishProgress(56); if (downloadPercent >= 100) { break; } } return null; } @Override protected void onProgressUpdate(Integer... values) { Toast.makeText(context, values[0] + "%", Toast.LENGTH_SHORT).show(); super.onProgressUpdate(values); } @Override protected void onPostExecute(Boolean aBoolean) { super.onPostExecute(aBoolean); }}

    3. 服务的基本用法

    3.1 定义服务

  • 在Android Studio中依次选择File - New - Service,服务会在AndroidManifest.xml中自动注册。

  • 示例:

    public class MyService extends Service {    public MyService() {    }    @Override    public IBinder onBind(Intent intent) {        throw new UnsupportedOperationException("Not yet implemented");    }    @Override    public void onCreate() {        super.onCreate();        Log.e("MyService", "onCreate");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("MyService", "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        Log.e("MyService", "onDestroy");    }}

  • 3.2 启动和停止服务

  • 启动服务

    public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button startButton = (Button) findViewById(R.id.start_button);        startButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Intent intent = new Intent(MainActivity.this, MyService.class);                startService(intent);            }        });    }}
  • 停止服务

    public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button stopButton = (Button) findViewById(R.id.stop_button);        stopButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Intent intent = new Intent(MainActivity.this, MyService.class);                stopService(intent);            }        });    }}

  • 3.3 活动和服务通信

  • 服务中代码示例:

    public class MyService extends Service {    private DownloadBinder mBinder = new DownloadBinder();    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }    @Override    public void onCreate() {        super.onCreate();        Log.e("MyService", "onCreate");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("MyService", "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        Log.e("MyService", "onDestroy");    }    class DownloadBinder extends Binder {        public void startService() {            Log.e("MyService", "startService");        }        public void stopService() {            Log.e("MyService", "stopService");        }    }}
  • 活动中代码示例:

    public class MainActivity extends AppCompatActivity implements View.OnClickListener {    ServiceConnection connection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            MyService.DownloadBinder binder = (MyService.DownloadBinder) iBinder;            binder.startService();            binder.stopService();        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button startButton = (Button) findViewById(R.id.start_button);        startButton.setOnClickListener(this);        Button stopButton = (Button) findViewById(R.id.stop_button);        stopButton.setOnClickListener(this);        Button bindButton = (Button) findViewById(R.id.bind_button);        bindButton.setOnClickListener(this);        Button unBindButton = (Button) findViewById(R.id.unbind_button);        unBindButton.setOnClickListener(this);    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.stop_button:                Intent stopIntent = new Intent(MainActivity.this, MyService.class);                stopService(stopIntent);                break;            case R.id.start_button:                Intent startIntent = new Intent(MainActivity.this, MyService.class);                startService(startIntent);                break;            case R.id.bind_button:                Intent bindIntent = new Intent(MainActivity.this, MyService.class);                bindService(bindIntent, connection, BIND_AUTO_CREATE);                break;            case R.id.unbind_button:                unbindService(connection);                break;            default:                break;        }    }}

  • 4. 服务的生命周期

    服务的生命周期如下:

  • 被启动的服务(startService()):

    • onCreate():服务首次创建时调用。
    • onStartCommand():每次启动服务时调用。
    • 服务一直运行,直到调用stopService()或stopSelf()。
    • onDestroy():服务终止时调用。
  • 被绑定的服务(bindService()):

    • onBind():服务绑定时调用。
    • 服务一直运行,直到调用unbindService()或服务上下文不存在。
    • onDestroy():服务终止时调用。
  • 被启动又被绑定的服务

    • 需要同时调用stopService()和unbindService(),否则onDestroy()不会执行。
  • 服务终止时清除资源

    • 在onDestroy()方法中清理资源,如停止子线程等。

  • 5. 服务的更多技巧

    5.1 使用IntentService

    IntentService默认在主线程中运行耗时逻辑,容易导致ANR。示例:

    public class MyService extends IntentService {    public MyService() {        super("MyService");    }    @Override    protected void onHandleIntent(@Nullable Intent intent) {        // 在子线程中运行逻辑    }    @Override    public void onDestroy() {        super.onDestroy();    }}

    5.2 自动停止服务

    在服务中使用stopSelf()方法实现自动停止:

    public class MyService extends Service {    @Override    public void onCreate() {        super.onCreate();        Log.e("MyService", "onCreate");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        new Thread(new Runnable() {            @Override            public void run() {                Log.e("MyService", "onStartCommand");                stopSelf();            }        }).start();        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        Log.e("MyService", "onDestroy");    }}

    6. 扩展问题

    6.1 服务生命周期

  • 被启动的服务

    • onCreate()和onStartCommand()会被调用多次。
    • 服务会一直运行,直到被停止或系统资源不足。
  • 被绑定的服务

    • onBind()和onUnbind()会被调用。
    • 服务会在上下文存在时运行。
  • 被启动又被绑定的服务

    • 需要同时调用stopService()和unbindService()。
  • 服务终止时清理资源

    • 在onDestroy()方法中清理资源。

  • 6.2 服务的启动方式

  • startService()

    • 创建或重用服务实例。
    • 调用onCreate()和onStartCommand()。
    • 停止服务调用stopService()或stopSelf()。
  • bindService()

    • 绑定服务,调用onBind()。
    • 解除绑定调用unbindService()。
    • 服务可能在上下文不存在时终止。

  • 6.3 使用Handler传递数据

    Handler可以通过Bundle传递数据:

    public class MainActivity extends AppCompatActivity {    Handler handler = new Handler() {        @Override        public void handleMessage(@NonNull Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case 1:                    Bundle bundle = msg.getData();                    String name = bundle.getString("name");                    int age = bundle.getInt("age");                    Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();                    break;                default:                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button = (Button) findViewById(R.id.button);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                new Thread(new Runnable() {                    @Override                    public void run() {                        Message message = new Message();                        message.what = 1;                        Bundle bundle = new Bundle();                        bundle.putString("name", "Tom");                        bundle.putInt("age", 18);                        message.setData(bundle);                        handler.sendMessage(message);                    }                }).start();            }        });    }}

    以上内容涵盖了Android服务和多线程编程的核心知识,适合开发者在实际项目中参考和应用。

    上一篇:Android基础知识——运用手机多媒体
    下一篇:Android基础知识——使用网络技术

    发表评论

    最新留言

    做的很好,不错不错
    [***.243.131.199]2025年05月04日 15时30分18秒