IntentService——自帶工作執行緒的服務
阿新 • • 發佈:2019-01-10
一、概念
- IntentService 是繼承自Service用來處理非同步任務的類,其內部有一個工作執行緒來處理耗時操作。
- 當任務完成後,IntentService會自動停止,不需要我們手動去結束。
- 如果多次啟動IntentService,那麼每一個耗時任務會以工作佇列的方式在IntentService的onHandleIntent()方法中逐一執行,使用序列方式,執行完自動結束。
- 內部是通過HandlerThread和Handler來實現非同步操作。
二、使用步驟
- 建立一個類繼承自IntentService,並重寫它的構造方法和onHandleIntent()方法。在onHandleIntent()方法中執行耗時非同步任務。
- 通過BroadcastReceiver或者其他方式,將IntentService所處理的非同步任務的結果返回給呼叫它的Activity。
- 在Activiy或者其他元件中啟動該IntentService。
三、例項參考
該例實現了在IntentService中序列下載5張圖片的操作。在Activity中迴圈啟動5次IntentService,每次下載一張圖片,然後通過在IntentService中定義介面,Activity實現介面的方式把下載的圖片傳遞給Activiy,並顯示到ImageView中。觀察顯示結果,發現在下載過程中,onStart()和onStartCommand()多次啟動,而onHandleIntent()方法則只啟動了一次,這也證實了IntentService是序列處理任務。
1、Activity的程式碼。
package com.example.pc.intentservicetest; import android.annotation.SuppressLint; import android.content.Intent; import android.graphics.Bitmap; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import java.net.MalformedURLException; import java.net.URL; public class MainActivity extends AppCompatActivity implements View.OnClickListener,MyIntentService.UpdateUI{ private Button startDownload; private ImageView showPic; private String[] urls=new String[]{ "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529320312155&di=e3834c9df7cee843d588f4d64dd8756c&imgtype=0&src=http%3A%2F%2Fpic.baike.soso.com%2Fp%2F20130519%2F20130519223254-1988447061.jpg" ,"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529248203494&di=06d7ad840adb727deb01ffda45f0f27f&imgtype=0&src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01394556c6d4456ac7252ce641af6b.jpg" ,"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529320370669&di=678044a4763b0a2337c6f4907374c97f&imgtype=0&src=http%3A%2F%2Fupload.gezila.com%2Fdata%2F20180525%2F36771527214595.jpg" ,"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529320427329&di=3bc0e90a90dfb5e36c481aec8eb28ce3&imgtype=0&src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F015207554bfb57000001bf728db535.jpg" ,"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529320494492&di=d790d72dd471ea8c40482fc3f282f75d&imgtype=0&src=http%3A%2F%2Fimg3.redocn.com%2F20091020%2F20091020_fe33a4113c29b45ad7f5WRnBaQzQ3dnc.jpg " }; @SuppressLint("HandlerLeak") private Handler UIHandler=new Handler(){ @Override public void handleMessage(Message msg) { Bitmap bm= (Bitmap) msg.obj; showPic.setImageBitmap(bm); super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //把UpdateUI的例項傳遞給IntentService MyIntentService.setUpdateUI(this); } private void initView() { startDownload=findViewById(R.id.startDownload); showPic=findViewById(R.id.showPic); startDownload.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.startDownload: //迴圈啟動5次IntentService for(int i=0;i<4;i++){ Intent intent=new Intent(MainActivity.this,MyIntentService.class); intent.putExtra(MyIntentService.URLS,urls[i]); intent.putExtra(MyIntentService.FLAG,i); startService(intent); } break; } } //重寫UpdateUI類的方法,通過此方法實現intentService與Activity的通訊 @Override public void updateUI(Message message) { //主執行緒handler傳送在IntentService中建立的Message UIHandler.sendMessageDelayed(message,message.what*1000); } }
2、自定義MyIntentService繼承自IntentSerrvice,並在onHandleIntent()方法中執行下載任務。
package com.example.pc.intentservicetest;
import android.app.IntentService;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by pc on 2018/6/16.
*/
public class MyIntentService extends IntentService {
private URL url;
private Bitmap bm;
private int i;
private static UpdateUI updateUI;
public static String URLS="url_link";
public static String FLAG="flag_num";
public MyIntentService() {
super("name");
}
@Override
public void onCreate() {
Log.e("TAG",".........onCreate()............");
super.onCreate();
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
Log.e("TAG",".........onStartCommand()............");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Log.e("TAG",".........onStart()............");
super.onStart(intent, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e("TAG",".........onBind()............");
return super.onBind(intent);
}
@Override
public void onDestroy() {
Log.e("TAG",".........onDestroy()............");
super.onDestroy();
}
//此方法獲取Activity傳來的UpdateUI物件
public static void setUpdateUI(UpdateUI updateUIinterface){
updateUI=updateUIinterface;
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.e("TAG",".........onHandleIntent()............");
String urlStr= intent.getStringExtra(URLS);
int flag=intent.getIntExtra(FLAG,0);
try {
url=new URL(urlStr);
HttpURLConnection conn= (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
InputStream is=conn.getInputStream();
File file= new File(Environment.getExternalStorageDirectory(),"pic.jpg");
if(!file.exists()){
file.createNewFile();
}
OutputStream os=new FileOutputStream(file);
byte[] b=new byte[1024];
int len;
while((len=is.read(b))!=-1){
os.write(b,0,len);
}
InputStream in=new FileInputStream(file);
bm=BitmapFactory.decodeStream(in);
if(updateUI!=null){
Message msg=new Message();
msg.obj=bm;
msg.what=flag;
//呼叫在Activity中建立的UpdateUI例項物件的updateUI方法給主執行緒傳送訊息
updateUI.updateUI(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 定義介面UpdateUI
public interface UpdateUI{
void updateUI(Message message);
}
}
3、效果圖