
本文共 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中的异步消息处理主要由以下四个部分组成:
消息通过Looper和MessageQueue进行传递,最终在Handler的handleMessage()方法中执行,确保UI操作在主线程中进行。
2.4 使用AsyncTask
AsyncTask是Android提供的用于在子线程中对UI操作的工具,原理基于异步消息处理机制。创建AsyncTask子类时,需要指定三个泛型参数:
示例:
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服务和多线程编程的核心知识,适合开发者在实际项目中参考和应用。
发表评论
最新留言
关于作者
