Android面试一天一题(1Day)

写在前面

该博客思路源于在简书看到goeasyway博主写的Android面试一天一题系列,无copy之意,仅为让自己总结知识点,成长一点点。先感谢各位大神的无私分享~!

关于题目,大部分则出自AndroidInterview-Q-ALearningNotes,当然既然是Android面试,主要是Android部分,Java基础之后再写。

IntentService作用是什么,AIDL解决了什么问题 — 小米

想知道IntentService的作用,当然需要先了解何为IntentService。

IntentService

官方解释是这样说的:

IntentService是一个基于Service的子类,其能够根据需求处理异步请求(作为Intent一样来表示)。客户端通过startService(Intent)发送异步请求调用;服务作为需要而开始,控制每个Intent来转向使用一个工作线程,并且当工作完成后自己会停止。

这个工作队列处理器部分通常用于从应用的主线程卸下任务IntentService类纯在为了简化这个部分和考虑到了mechanics。为了使用它,扩展IntentService和实现onHandleIntent(Intent)。IntentService会收到Intents,启动一个工作线程和恰当地停止服务。

所有请求被耽搁工作线程控制 — 他们可能只需要(切不会阻塞应用主线程),但每次只处理一个请求。

先抛开官方解释不说,其实我们应该想想为什么有了Service还需要一个IntentService呢?这里就引出Service与IntentService之间的区别,那么两者是否应该有联系,区别又是什么呢?考虑问题时我们应该往深度和广度去探索,当然别太深无法自拔最后自己都不知道想要了解什么问题。所以接下来的几个问题:

Service的弊端?为什么会出现IntentService,Service和IntentService的区别?

如果说Service是依附于主线程的,也就是说不能进行耗时操作,而继承于它的子类IntentService中新增了哪些代码呢,这就可以从源码入手了,下面是IntentService的几个重要元素:

public abstract class IntentService extends Service {
    // Looper可以知道需要与handler的套用,进行MessageQueue的资源存放和索取
  	private volatile Looper mServiceLooper; 
    private volatile ServiceHandler mServiceHandler;
	// ... 代码省略 ...
  
  	// 实际上也是通过Handler的机制来实现耗时操作
    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);
        }
    }
  
	// ... 代码省略 ...
      
    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

      	// 从上面实例化的线程中获取Looper,然后再传入ServiceHandler
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
  
   	// ... 代码省略 ...
  
   /**
     * This method is invoked on the worker thread with a request to process.
     * Only one Intent is processed at a time, but the processing happens on a
     * worker thread that runs independently from other application logic.
     * So, if this code takes a long time, it will hold up other requests to
     * the same IntentService, but it will not hold up anything else.
     * When all requests have been handled, the IntentService stops itself,
     * so you should not call {@link #stopSelf}.
     *
     * @param intent The value passed to {@link
     *               android.content.Context#startService(Intent)}.
     */
    @WorkerThread
    protected abstract void onHandleIntent(Intent intent);
}

注意onHandleIntent方法的注释:

该方法可以为唤起一个工作线程,而每次只能处理一个Intent,但是这个过程发生在工作线程中,并且运行在一个独立于其他的应用逻辑中,因此如果这部分代码会花一些时间的话,就会先拦截别的请求对于同一个IntentService,但不会拦截除此之外的事件。一旦所有请求都被处理了以后,IntentService会自动停止,你不需要调用stopSelf。

啰嗦一大堆,说白了IntentService就是为了实现让Service能够进行耗时操作的功能。

IntentService的用法

光知道概念和原理,但是不会用怎么行呢,我们以一个简单的Demo来进行示例,首先创建一个MainActivity负责事件开始,点击onClick的时候启动IntentService:

public class MainActivity extends AppCompatActivity {

    private boolean serviceRunning = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView serviceStates = (TextView) findViewById(R.id.tv_service_states);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent serviceIntent = new Intent(MainActivity.this, CustomIntentService.class);
                serviceIntent.putExtra("sleep_flag", true);
                if (!serviceRunning) {
                    startService(serviceIntent);
                    serviceStates.setText("Service is running...");
                } else {
                    stopService(serviceIntent);
                    serviceStates.setText("Service is stop...");
                }
                serviceRunning = !serviceRunning;
            }
        });
    }
}
public class CustomIntentService extends IntentService {
    public static final String TAG = CustomIntentService.class.getSimpleName();

    public CustomIntentService() {
        super("CustomIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.e(TAG, " onHandleIntent====> ");
        boolean flag = intent.getBooleanExtra("sleep_flag", false);
        Log.e(TAG, " onHandleIntent flag  ====> " + flag);
    }

    @Override
    public void onCreate() {
        Log.e(TAG, " onCreate ====>  executed ");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, " onDestroy ====>  executed ");
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, " onStartCommand ====>  executed ");
        boolean flag = intent.getBooleanExtra("sleep_flag", false);
        Log.e(TAG, " onStartCommand flag  ====> " + flag);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, " onBind ====>  executed ");
        return super.onBind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, " onUnbind ====>  executed ");
        return super.onUnbind(intent);
    }

    @Override
    public void onRebind(Intent intent) {
        Log.e(TAG, " onRebind ====>  executed ");

        super.onRebind(intent);
    }
}

因为我在Intent中传递了一个boolean值作为标记,可以在下面的执行结果中看到IntentService方法的执行顺序:

E/CustomIntentService:  onCreate ====>  executed 
E/CustomIntentService:  onStartCommand ====>  executed 
E/CustomIntentService:  onStartCommand flag  ====> true
E/CustomIntentService:  onHandleIntent====> 
E/CustomIntentService:  onHandleIntent flag  ====> true
E/CustomIntentService:  onDestroy ====>  executed 

当我在onHandleIntent()中使线程睡眠10s时,连续点击两次启动Button,可以看到并没有出现Service中ANR的问题,过了一会sleeping end才结束,因为IntentService通过新的子线程来进行耗时操作,从而不会影响主线程的业务逻辑。

@Override
protected void onHandleIntent(Intent intent) {
    Log.e(TAG, " onHandleIntent====> ");
    boolean flag = intent.getBooleanExtra("sleep_flag", false);
    Log.e(TAG, " onHandleIntent flag  ====> " + flag);
    Log.e(TAG, " onHandleIntent====> sleeping start");
    try {
        Thread.sleep(10 * 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Log.e(TAG, " onHandleIntent====> sleeping end");
}
// 第一次点击
E/CustomIntentService:  onCreate ====>  executed 
E/CustomIntentService:  onStartCommand ====>  executed 
E/CustomIntentService:  onStartCommand flag  ====> true
E/CustomIntentService:  onHandleIntent====> 
E/CustomIntentService:  onHandleIntent flag  ====> true
E/CustomIntentService:  onHandleIntent====> sleeping start
E/CustomIntentService:  onDestroy ====>  executed 
// 第二次点击  
E/CustomIntentService:  onCreate ====>  executed 
E/CustomIntentService:  onStartCommand ====>  executed 
E/CustomIntentService:  onStartCommand flag  ====> true
E/CustomIntentService:  onHandleIntent====> 
E/CustomIntentService:  onHandleIntent flag  ====> true
E/CustomIntentService:  onHandleIntent====> sleeping start
E/CustomIntentService:  onDestroy ====>  executed 
// sleep结束
E/CustomIntentService:  onHandleIntent====> sleeping end
E/CustomIntentService:  onHandleIntent====> sleeping end
posted @ 2016-08-31 01:41  Codios  阅读(825)  评论(0编辑  收藏  举报