https://blog.youkuaiyun.com/qq_33748378/article/details/52330382
https://blog.youkuaiyun.com/ryantang03/article/details/8146154
https://blog.youkuaiyun.com/hudashi/article/details/7986130
IntenteService使用姿势
1: IntenteService是 Service的 子类,用来处理异步请求,客户端通过 startService(intent) 将请求传递给 intentService, 其中 IntentService在onCreate() 函数中,通过HandlerThread 单独开启一个线程来处理所有的 intent请求对象,所对应的 任务,这样可以避免阻塞主线程,在执行完一个 inentServcie请求对象之后,如果没有新的 Intent请求到达,则自动停止 Service, 否则就执行下一个 intent 请求对应的任务
2 :IntenteService在处理事务时,还是采用Handler方式,创建一个名叫 ServiceHandler 的内部handler , 并绑定到 HandlerThread所对应的 子线程,ServiceHandler 吧处理一个Intent所对应的事务都封装在 onHandleIntent的虚函数中,因此我们需要实现 onHandleIntenth函数,在实现的函数里面 根据不同 intent 处理不同事务或者任务就可以了
3: 使用 IntentServcie的步骤
3-1 : 写构造函数
3-2 :实现 虚函数onHandleIntent()
3-3 启动 IntentServcie : startService(context, intentServcie.class) ; (注意 intentService默认实现了onBind() 函数,但是onBind() 函数返回值是 null )
3-4 另外,不建议通过 bindService() 启动 IntentService。IntentService 源码中的 onBind() 默认返回 null;不适合 bindService() 启动服务,如果你执意要 bindService() 来启动 IntentService,可能因为你想通过 Binder 或 Messenger 使得 IntentService 和 Activity 可以通信,这样那么 onHandleIntent() 不会被回调,相当于在你使用 Service 而不是 IntentService。
4 : intentService 停止:
onHandleIntent ( ) 里面的任务如果执行完毕,那么service会自动停止,不需要手动 stop, 如果任务没有执行完毕,service不会停止,而 onHandleIntent() 里面的任务 ,就是 通过 startService(context, intentServcie.class)传递的,多次启动会将任务依次放到 onHandleIntent () 中,并且 intentService 只会启动一次 (即多次启动,onCreate()运行一次,但是会运行多次 onStartCommand() 函数)
4 : 使用场景:
在Android开发中,我们或许会碰到这么一种业务需求,一项任务分成几个子任务,子任务按顺序先后执行,子任务全部执行完后,这项任务才算成功。
4-1 那么,利用几个子线程顺序执行是可以达到这个目的的,但是每个线程必须去手动控制,而且得在一个子线程执行完后,再开启另一个子线程。
4-2 或者,全部放到一个线程中让其顺序执行。这样都可以做到,
4-3 但是,如果这是一个后台任务,就得放到Service里面,由于Service和Activity是同级的,所以,要执行耗时任务,就得在Service里面开子线程来执行。那么,有没有一种简单的方法来处理这个过程呢,答案就是IntentService。
5 : 场景模拟
package com.application.intentservicedemo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final String ACTION_DOWN_LOAD_IMAGE = "action_down_load_image";
public static final String DOWN_LOAD_IMAGE_PATH = "down_load_image_path";
public static final String RESULT_DOWNLOAD_IMAGE = "result_download_image";
public static final String EXTRA_DOWNLOAD_IMAGE = "extra_download_image";
private TextView addTask;
private int i;
private BroadcastReceiver receiver = new DownloadBroadCast();
private LinearLayout content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addTask = findViewById(R.id.add_task);
content = findViewById(R.id.content_container);
addTask.setOnClickListener(this);
//注册广播
IntentFilter filter=new IntentFilter(RESULT_DOWNLOAD_IMAGE);
registerReceiver(receiver,filter);
}
@Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.add_task) {
// 点击按钮,添加图片下载任务
TextView textView = new TextView(this);
String path="/sdcard/imgs"+(++i)+".png";//模拟下载路径
textView.setText(path + " is downloading");
textView.setTag(path);
content.addView(textView);
startIntentServcieForDownload(path);
}
}
private void startIntentServcieForDownload(String imagePath) {
Intent intent = new Intent();
intent.setClass(this,MyIntentService.class);
intent.setAction(ACTION_DOWN_LOAD_IMAGE);
intent.putExtra(DOWN_LOAD_IMAGE_PATH,imagePath);
startService(intent);
}
public class DownloadBroadCast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (TextUtils.equals(intent.getAction(),RESULT_DOWNLOAD_IMAGE)) {
String imageResult = intent.getStringExtra(EXTRA_DOWNLOAD_IMAGE);
TextView textView = (TextView) content.findViewWithTag(imageResult);
textView.setText(imageResult + "is successful download");
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
package com.application.intentservicedemo;
import android.app.IntentService;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
import static com.application.intentservicedemo.MainActivity.DOWN_LOAD_IMAGE_PATH;
import static com.application.intentservicedemo.MainActivity.EXTRA_DOWNLOAD_IMAGE;
public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
public MyIntentService() {
super("download image");
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG,"onCreate enter");
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.e(TAG,"onStartCommand enter");
return super.onStartCommand(intent, flags, startId);
}
/**
* @param name
* @deprecated
*/
public MyIntentService(String name) {
super(name);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.e(TAG,"onHandleIntent enter");
if (intent != null) {
if (TextUtils.equals(intent.getAction(),MainActivity.ACTION_DOWN_LOAD_IMAGE)) {
String path = intent.getStringExtra(DOWN_LOAD_IMAGE_PATH);
//根据下载路径,模拟图片的下载,在后头 service 并且开启线程来 完成图片下载任务
downLoadWork(path);
}
}
}
private void downLoadWork(String path) {
try {
Log.e(TAG,"downLoadWork thread = " + Thread.currentThread().getName());
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 一般后台任务执行完毕后,怎么将 任务执行的结果给 传递出去了,就是通过广播的方式
Intent intent=new Intent(MainActivity.RESULT_DOWNLOAD_IMAGE);
intent.putExtra(EXTRA_DOWNLOAD_IMAGE,path);
sendBroadcast(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG,"onDestroy enter");
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.application.intentservicedemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyIntentService"
android:exported="true"
>
</service>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/content_container">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="添加任务"
android:id="@+id/add_task"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>