zoukankan      html  css  js  c++  java
  • 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
    
  • 相关阅读:
    为什么常见编程语言中数组的索引都是从0开始?
    【转载】计算机经典论文选读
    Jetbrains-别人家的公司
    2019.9沉淀反思
    HttpUrlConnection流传输问题(正确传输包含中文的JSON字符串)
    记一次SpringBoot启动缓慢问题的解决过程
    Maven发布jar包到私库
    2016年回顾
    Java集合框架源码分析之ArrayList
    关于哔哩哔哩直播姬
  • 原文地址:https://www.cnblogs.com/raomengyang/p/5824327.html
Copyright © 2011-2022 走看看