Android基础之深入理解IntentService

1 IntentService

1.1 为什么需要IntentService

我们遇到耗时的操作会交给Service去做,比如:我们上传多张图,上传的过程用户可能将应用置于后台,然后干别的去了,Activity就很可能会被杀死,所以可以将上传操作交给Service去做;如果担心Service被杀,通过设置startForeground(int, Notification)方法提升其优先级。

那么,在Service里面肯定不能直接进行耗时操作,都需要去开启子线程来完成耗时操作,自己去管理Service的生命周期以及子线程并非是个优雅的做法。

而官方给我们提供了IntentService,它是继承于Service并处理异步耗时请求的一个类

1.2 作用?(或IntentService与Service的区别)

(1)可以通过startService(Intent)方式来提交请求,和启动传统Service一样;
(2)该Service会在需要的时候创建;
(3)当完成所有的任务以后会自动关闭;
(4)可以启动多次,而每一个耗时操作会以工作队列的方式在onHandleIntent()中执行,每次只会执行一个工作线程;
(5)解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题。

1.2 本质与原理

(1)本质是:Service+HandlerThread+Intent。在我的另一篇博客:拥有Looper的线程–HandlerThread
(2)实现原理:onStartCommand中回调了onStart,onStart中通过mServiceHandler发送消息到该handler的handleMessage中去。最后handleMessage中回调onHandleIntent(intent),并且执行stopSelf()关闭服务。

1.3 优点

(1)不需要自己去新建线程,不需要考虑在什么时候关闭该Service;
(2)提高子线程的优先级;
(3)减轻主线程的压力。

2 IntentService使用例子

(1)MainApplication.java

public class MainApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 启动服务执行耗时操作
        InitializeService.start(this);
    }
}

(2)InitializeService.java

/**
 * 启动初始化Service
 */
public class InitializeService extends IntentService {

    // IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
    public static final String ACTION_INIT_WHEN_APP_CREATE = "com.guesslive.caixiangji.service.action.app.create";
    public static final String EXTRA_PARAM = "com.guesslive.caixiangji.service.extra.PARAM";

    /**
     * 至少要有一个空的构造方法
     */
    public InitializeService() {
        super("InitializeService");
    }

    /**
     * 启动调用
     * @param context
     */
    public static void start(Context context) {
        Intent intent = new Intent(context, InitializeService.class);
        intent.setAction(ACTION_INIT_WHEN_APP_CREATE);
        context.startService(intent);
    }
    
    /**
     * UI线程发送Intent后执行
     * 子线程中执行(主要执行的方法)
     */
    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_INIT_WHEN_APP_CREATE.equals(action)) {
                performInit(EXTRA_PARAM);
            }
        }
    }

	/**
	 * UI线程中执行
	 */
	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
	}

    /**
     * 启动初始化操作
     */
    private void performInit(String param) {
        initImageLoader();//初始化图片加载控件
        initRealm();//初始化Realm数据库
        initUser();//初始化用户(Realm数据库)
        initPush();//初始化推送
        initTuSdk();//初始化图sdk
        initQiNiu();//初始化七牛
        initQiyu();//网易七鱼
        initLogger();//注释启动,打开屏蔽打印
    }
}

3 IntentService源码解析

3.1 源码

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    protected abstract void onHandleIntent(Intent intent);
}

3.2 解析

(1)原理:就是每次调用onStartCommand的时候,onStartCommand中回调了onStart,onStart中通过mServiceHandler发送消息到该handler的handleMessage中去,消息包含我们的intent。然后在该mServiceHandler的handleMessage中去回调onHandleIntent(intent)。

(2)注意下:回调完成后回调用 stopSelf(msg.arg1),注意这个msg.arg1是个int值,相当于一个请求的唯一标识。每发送一个请求,会生成一个唯一的标识,然后将请求放入队列,当全部执行完成(最后一个请求也就相当于getLastStartId == startId),或者当前发送的标识是最近发出的那一个(getLastStartId == startId),则会销毁我们的Service。

(3)如果传入的是-1则直接销毁。当任务完成销毁Service回调onDestory,可以看到在onDestroy中释放了我们的Looper:mServiceLooper.quit()。

4 CursorLoader

4.1 问题:Activity中启动子线程

(1)内存泄露
(2)无效的更新UI
Loader保证子线程与Activity或者Fragment的生命周期一致
Activity和Fragment自带LoaderManager

4.2 优点

(1)方便
(2)Activity或者Fragment的生命周期一致
(3)数据缓存与更新通知

4.3 例子(也可以模仿写一个网络加载器)

/**
 * 使用加载器加载通话记录
 */
public class MainActivity extends Activity {
	private static final String TAG = "jason";
	// 查询指定的条目
	private static final String[] CALLLOG_PROJECTION = new String[] { CallLog.Calls._ID, CallLog.Calls.NUMBER,
			CallLog.Calls.CACHED_NAME, CallLog.Calls.TYPE, CallLog.Calls.DATE };
	private ListView mListView;
	private MyLoaderCallback mLoaderCallback = new MyLoaderCallback();
	private MyCursorAdapter mAdapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mListView = (ListView) findViewById(R.id.lv_list);
		mAdapter = new MyCursorAdapter(MainActivity.this, null);
		mListView.setAdapter(mAdapter);

		//执行Loader的回调
		getLoaderManager().initLoader(0, null, mLoaderCallback);
	}

	private class MyLoaderCallback implements LoaderManager.LoaderCallbacks<Cursor> {
		//创建Loader
		@Override
		public Loader<Cursor> onCreateLoader(int id, Bundle args) {
			//加载的过程在子线程中进行
			CursorLoader loader = new CursorLoader(MainActivity.this, CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION,
					null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
			Log.d(TAG, "onCreateLoader");
			return loader;
		}

		//Loader检测底层数据,当检测到改变时,自动执行新的载入获取最新数据
		//Activity/Fragment所需要做的就是初始化Loader,并且对任何反馈回来的数据进行响应。
		@Override
		public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
			if (data == null)
				return;
			mAdapter.swapCursor(data);
			Log.d(TAG, "onLoadFinished data count = " + data.getCount());
		}

		//OnDestroy,自动停止load
		@Override
		public void onLoaderReset(Loader<Cursor> loader) {
			Log.d(TAG, "onLoaderReset");
			mAdapter.swapCursor(null);
		}
	}
}

5 参考链接

Android IntentService完全解析 当Service遇到Handler

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值