Android入门之IntentService的使用教程详解
开篇
在前一篇中我们讲了bindService的使用。并且我们留下了一个念想,即在bindService取值时故意阻塞30秒,引起了一次ANR并引出了今天的章节-IntentService。
IntentService的生命周期中有一个非常好的方法-onHandleIntent方法,它是一个abstract方法,开发者在实现IntentService时可以覆盖它来处理“长事务”。
IntentService
Android开发者官网说过:
- Service不是一个单独的进程,它和它的应用程序在同一个进程中
- Service不是一个线程,这样就意味着我们应该避免在Service中进行耗时操作
于是乎,Android给我们提供了解决上述问题的替代品,就是下面要讲的IntentService; IntentService是继承与Service并处理异步请求的一个类,在IntentService中有 一个工作线程来处理耗时操作,请求的Intent记录会加入队列。
这么神奇?
我们来看演示,如何来验证这个IntentService里的onHandleIntent处理这种长事务。
课程目标
设Service里有一个字符型数组:
private String[] stdNames = new String[]{"小王", "小明", "小张"};
在Activity里输入数组下标后、等待30秒、然后把相对应的数组下标所对应的StudentName显示在Toast里,看看是不是会发生ANR。
该点击动作可以反复点击,因为每次点击后都会执行unbindService。
代码核心设计
IntentService没什么特殊的,它只是extends 自 IntentService,同时它拥有一个可以被覆盖的:onHandleIntent方法。
- 我们这次使用CallBack模式来实现Service里长事务结束后回调activity里的handler实现数值传递;
- 我们使用intent.putExtra来实现activity里的数值传递到service中去;
service注册
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.DemoRealIntentService" tools:targetApi="31"> <service android:name=".LongWaitingService" android:exported="false"></service> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.lib_name" android:value="" /> </activity> </application> </manifest>
Service类-LongWaitingService
package org.mk.android.demorealintentservice; import android.app.IntentService; import android.content.Intent; import android.content.Context; import android.os.IBinder; import android.util.Log; public class LongWaitingService extends IntentService { private final String TAG = "LongWaitingService"; private String[] stdNames = new String[]{"小王", "小明", "小张"}; private Callback callback; private int stdNo; public class StudentBinder extends android.os.Binder { public LongWaitingService getService() { return LongWaitingService.this; } } public void setCallback(Callback callback) { this.callback = callback; } public static interface Callback { void onDataChange(String data); } public LongWaitingService() { super("LongWaitingService"); } @Override public void onStart(Intent intent, int startId) { Log.i(TAG, ">>>>>>onStart"); } @Override protected void onHandleIntent(Intent intent) { if (intent != null) { Log.i(TAG, ">>>>>>onHandleIntent"); Log.i(TAG, ">>>>>>into a long waiting"); new Thread() { public void run() { try { Thread.sleep(30000); if (callback != null) { String stdName = stdNames[stdNo]; callback.onDataChange(stdName); } } catch (Exception e) { } } }.start(); } } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. Log.i(TAG, ">>>>>>onBind方法被调用"); this.stdNo = intent.getIntExtra("stdNo", -1); onHandleIntent(intent); return new StudentBinder(); } //Service被关闭前回调 @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, ">>>>>>onDestroyed方法被调用!"); } @Override public boolean onUnbind(Intent intent) { Log.i(TAG,">>>>>>onUnbind"); return false; } }
主类-MainActivity.java
package org.mk.android.demorealintentservice; import androidx.appcompat.app.AppCompatActivity; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private final String TAG = "LongWaitingService"; private Button buttonGetValueFromBinder; private Button buttonClose; private Context ctx; private Intent intent; private LongWaitingService.StudentBinder stdBinder; private EditText etStdNo; Handler stdHandler = new StudentHandler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); buttonGetValueFromBinder = (Button) findViewById(R.id.buttonGetValueFromBinder); etStdNo = (EditText) findViewById(R.id.etStdNo); ctx = MainActivity.this; intent = new Intent(ctx, LongWaitingService.class); buttonGetValueFromBinder.setOnClickListener(new OnClickListener()); } private ServiceConnection conn = new ServiceConnection() { //Activity与Service断开连接时回调该方法 @Override public void onServiceDisconnected(ComponentName name) { Log.i(TAG, ">>>>>>Service DisConnected"); } //Activity与Service连接成功时回调该方法 @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG, ">>>>>>Service Connected"); stdBinder = (LongWaitingService.StudentBinder) service; LongWaitingService stdService = stdBinder.getService(); stdService.setCallback(new LongWaitingService.Callback() { @Override public void onDataChange(String data) { Message msg = new Message(); msg.obj = data; stdHandler.sendMessage(msg); } }); } }; class OnClickListener implements View.OnClickListener { @Override public void onClick(View view) { Intent eIntent; switch (view.getId()) { case R.id.buttonGetValueFromBinder: int stdNo = Integer.valueOf(etStdNo.getText().toString()); intent.putExtra("stdNo", stdNo); bindService(intent, conn, Service.BIND_AUTO_CREATE); break; } } } class StudentHandler extends Handler { @Override public void handleMessage(Message msg) { Log.i(TAG,">>>>>>Service的count" + "的值为:" + msg.obj.toString()); Toast.makeText(getApplicationContext(), "Service的count" + "的值为:" + msg.obj.toString(), Toast.LENGTH_LONG).show(); unbindService(conn); } } }
运行效果
来看看运行效果吧
看,再也没有ANR了,结果成功通过CALL BACK回传Activity。
因此我们一般都会这么使用IntentService来实现一些资源异步加载、第三方API回调。
到此这篇关于Android入门之IntentService的使用教程详解的文章就介绍到这了,更多相关Android IntentService内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Android编程实现点击EditText之外的控件隐藏软键盘功能
这篇文章主要介绍了Android编程实现点击EditText之外的控件隐藏软键盘功能,涉及Android控件的功能、属性及相关操作技巧,需要的朋友可以参考下2017-06-06
最新评论