1. 程式人生 > >IntentService——自帶工作執行緒的服務

IntentService——自帶工作執行緒的服務

一、概念

  • 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、效果圖