Android进阶之深入理解Service

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

1 概要

Service是一种计算型组件,主要用于在后台执行一系列计算任务,不直接与用户交互,执行任务的结果可以和外界进行通信。

由于Service组件工作在后台,因此用户无法直接感知到它的存在。Activity组件只有一种运行模式-启动状态,但是Service组件却有两种状态:启动状态和绑定状态。①通过startService启动的服务处于启动状态,它的内部可以执行一些后台计算,并且不需要和外界有直接的交互。②通过bindService启动的服务处于绑定状态,Service内部同样也可以执行后台计算,但是处于这种状态的Service可以通过ServiceConnection和外界进行通信。

1.1 Service的生命周期

在这里插入图片描述

1.2 什么时候使用Service

(1)播放多媒体的时候,用户启动了其他的Activity这个时候程序要在后台继续播放。
(2)后台service下载插件、更新包。
(3)检测SD卡上文件的变化。
(4)在后台记录你地理位置的改变等等。

1.3 Service分为本地服务(LocalService)和远程服务(RemoteService)

(1)默认情况下是在同一个主线程中。但可以通过配置android:process=”:remote” 属性让Service运行在不同的进程。
(2)本地服务依附在主进程上而不是独立的进程,不需要IPC,也不需要AIDL,主进程被Kill后,服务便会终止。
(3)远程服务为独立的进程,进程名格式为:包名 + android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响。

2 startService和bindService的区别

2.1 通过start方式开启服务

2.1.1 startService的步骤
1、定义一个类继承service
2、manifest.xml文件中配置service
3、使用context的startService(Intent)方法启动service
4、不使用时,调用stopService(Intent)方法停止服务
2.1.2 主要方法
// 开启服务
Intent service = new Intent(this, MyService.class);
startService(service);
// 结束服务
stopService(service);
2.1.3 生命周期

(1)完整生命周期

onCreate() -- > onStartCommand() -- > onDestory()

(2)调用一次startService,生命周期执行的方法依次是

TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }

(3)调用多次startService,onCreate只有第一次会被执行,而onStartCommand会执行多次

TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
TestService: onStartCommand---startId = 2 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
TestService: onStartCommand---startId = 3 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }

(4)结束服务时,调用stopService,执行onDestroy方法,并且多次调用stopService时,onDestroy只有第一次会被执行

TestService: onDestroy---
2.1.4 与activity之间的关系

(1)开启服务以后,与activity就没有关联,不受影响,独立运行。

2.2 采用bind的方式开启服务

2.2.1 bindService的步骤
1、定义一个类继承Service
2、在manifest.xml文件中注册service
3、使用context的bindService(Intent,ServiceConnection,int)方法启动service
4、不使用时,调用unbindService(ServiceConnection)方法停止该服务
2.2.2 主要方法
// 绑定服务
Intent bindIntent = new Intent(this, TestService.class);
// 参数1:Intent意图
// 参数2:是一个接口,通过这个接口接收服务开启或者停止的消息,并且这个参数不能为null
// 参数3:开启服务时的操作,BIND_AUTO_CREATE代表自动创建service
bindService(bindIntent, mConnection, BIND_AUTO_CREATE);

private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 只有当TestService的onBind方法返回值不为null时,才会被调用
            LogUtils.d(TAG, "onServiceConnected");
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // 只有出现异常时才会调用,服务正常退出不会调用。
            LogUtils.e(TAG, "onServiceDisconnected");
        }
    };
// 结束服务
unbindService(conn);
2.2.3 生命周期

bindService开启服务时,根据生命周期里onBind方法的返回值是否为空,有两种情况

@Override
public IBinder onBind(Intent intent) {
	LogUtils.d(TAG, "onBind---");
	// 返回mBinder对象或null
	return mBinder; 
}
2.2.3.1 onBind返回值是null

(1)完整生命周期

onCreate() -- > onBind() -- > onDestory()

(2)调用一次bindService,生命周期执行的方法依次是

TestService: onCreate---
TestService: onBind---

(3)调用多次bindService,onCreate和onBind也只在第一次会被执行

TestService: onCreate---
TestService: onBind---

(4)调用unbindService结束服务,执行onDestroy方法,并且unbindService方法只能调用一次,多次调用应用会抛出异常

TestService: onDestroy---

(5)注意:调用unbindService一定要确保服务已经开启,以及避免多次调用unbindService,否则应用会抛出异常,如下:在这里插入图片描述

2.2.3.2 onBind返回值不为null

(1)完整生命周期

onCreate() -- > onBind() --> onServiceConnected() -- > onDestory()

(2)调用一次bindService,onServiceConnected方法也被调用了,生命周期执行的方法依次是

TestService: onCreate---
TestService: onBind---
TestService + TestActivity: onServiceConnected

(3)调用多次bindService,onCreate和onBind也只在第一次会被执行

TestService: onCreate---
TestService: onBind---
TestService + TestActivity: onServiceConnected

(4)调用unbindService结束服务,执行onDestroy方法,并且unbindService方法只能调用一次,多次调用应用会抛出异常

TestService: onDestroy---
2.2.4 与activity之间的关系

(1)bindService开启服务以后,与activity存在关联,退出activity时必须调用unbindService方法,否则会报ServiceConnection泄漏的错误。

2.3 同时采用start和bind的方式开启服务

2.3.1 采用start和bind的方式开启服务,没有先后顺序的要求,TestService的onCreate只会执行一次。

(1)先start再bind

TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }

TestService: onBind---
TestService + TestActivity: onServiceConnected

// 重复bind,没有回调;重复start,回调如下
TestService: onStartCommand---startId = 2 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }

(2)先bind再start

TestService: onCreate---
TestService: onBind---
TestService + TestActivity: onServiceConnected

TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }

// 重复bind,没有回调;重复start,回调如下
TestService: onStartCommand---startId = 2 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
2.3.2 关闭服务需要stopService和unbindService都被调用,也没有先后顺序的影响,TestService的onDestroy也只执行一次

(1)如果只用一种方式关闭服务,不论是哪种关闭方式,onDestroy都不会被执行,服务也不会被关闭


(2)同时stopService和unbindService后执行,多次调用unbindService应用会抛出异常,如同2.2

TestService: onDestroy---

3 startService方式开启服务: onStartCommand诡异的返回值

3.1 源码分析

(1)源码实现方式

public int onStartCommand(Intent intent, int flags, int startId) {
	onStart(intent, startId);
	return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
 }

(2)默认实现方式

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	return super.onStartCommand(intent, flags, startId);
}

(3)默认实现方式返回的结果是START_STICKY

// 应用程序targetSdkVersion小于2.0就返回 START_STICKY_COMPATIBILITY,否则返回START_STICKY
mStartCompatibility = getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.ECLAIR; // 5 ,Android 2.0

(4)自定义的实现方式有4种

START_STICKY
START_NOT_STICKY
START_REDELIVER_INTENT
START_STICKY_COMPATIBILITY

3.2 TestService–>Runnable–>run制造异常,模拟系统杀死该进程

(1)START_STICKY(粘性的):服务被异常kill掉,当内存又存在的时候,service又被重新创建

TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
TestService: 2s after---
// 异常:com.seniorlibs.lifecycle E/AndroidRuntime: FATAL EXCEPTION: main
TestService: onCreate---
TestService: onStartCommand---startId = 2 and intent = null
TestService: 2s after---

解释:如果Service所在的进程,在执行了onStartCommand方法后,被清理了,那么这个Service会被保留在已开始的状态,但是不保留传入的Intent,随后系统会尝试重新创建此Service,由于服务状态保留在已开始状态,所以重启服务后一定会调用onCreate和onStartCommand方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null,startId=2

(2)START_NOT_STICKY(非粘性的):服务被异常kill掉,系统不会自动重启该服务

TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
TestService: 2s after---
// 异常:com.seniorlibs.lifecycle E/AndroidRuntime: FATAL EXCEPTION: main

解析:如果Service所在的进程,在执行了onStartCommand方法后,被清理了,则系统不会重新启动此Service。

(3)START_REDELIVER_INTENT(重新提交intent):服务被异常kill掉,当内存又存在的时候,系统会自动重启该服务,并将Intent的值传入

TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
TestService: 2s after---
// 异常:com.seniorlibs.lifecycle E/AndroidRuntime: FATAL EXCEPTION: main
TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
TestService: 2s after---

解析:如果Service所在的进程,在执行了onStartCommand方法后,被清理了,则结果和START_STICKY一样,也会重新创建此Service并调用onCreate和onStartCommand方法。接着系统会自动重启该服务,将Intent的值传入,并且startId=1。说明该int可以保留上次的startId与intent。

(4)START_STICKY_COMPATIBILITY(STICKY的兼容版本):不保证服务被kill后一定能重启

TestService: onCreate---
TestService: onStartCommand---startId = 1 and intent = Intent { cmp=com.seniorlibs.lifecycle/.service.TestService }
TestService: 2s after---
// 异常:com.seniorlibs.lifecycle E/AndroidRuntime: FATAL EXCEPTION: main
TestService: onCreate---
TestService: 2s after---

解析:如果Service所在的进程,在执行了onStartCommand方法后,被清理了,只调用onCreate方法,没有调用onStartCommand方法。

5 问题解答

5.1 Service与Activity怎么实现通信?

5.1.1 通过Binder实现通信(进程内通信)

(0)概要

(1)Activity调用bindService(Intent service, ServiceConnection conn, int flags)方法,绑定一个Service的继承类TestService;
(2)通过实例化ServiceConnection接口的onServiceConnected()方法,获取TestService中的Binder对象;
(3)通过此对象调用Binder继承类TestBinder中的方法将消息传给Service;
(4)如果想实现Service将消息传给Activity的,可以在TestBinder里面提供一个回调方法,在Activity中实现方法。

(1)在manifest.xml文件中注册service

<service android:name=".service.TestService" />

(2)定义一个类继承Service

public class TestService extends Service {

    public static final String TAG = "TestService";
    private Handler sWork = new Handler();
    private TestBinder mBinder = new TestBinder();
    private OnTestListener mListener;

    @Override
    public void onCreate() {
        super.onCreate();
        LogUtils.d(TAG, "onCreate---");

        // 制造异常,模拟系统杀死该进程
//        sWork.postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                LogUtils.d(TAG, 2000 / 1000 + "s after---");
//                // 故意制造异常,使该进程挂掉
//                Integer.parseInt("ok");
//            }
//        }, 5000);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtils.d(TAG, "onStartCommand---startId = " + startId + " and intent = " + intent);
        // 实验中,可轮换这几个值测试 :START_NOT_STICKY | START_STICKY | START_STICKY_COMPATIBILITY | START_REDELIVER_INTENT;
//        return super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        LogUtils.d(TAG, "onBind---");
        // 返回mBinder对象
        return mBinder;
    }

    @Override
    public void onDestroy() {
        LogUtils.d(TAG, "onDestroy---");
        super.onDestroy();
    }

    /**
     * 新建一个继承自Binder的类TestBinder
     */
    public class TestBinder extends Binder {
        // Activity通过Binder来调用TestBinder的方法将消息传给Service
        public void sendMsgToService(String msg) {
            LogUtils.d(TAG, "收到来自Activity的消息: " + msg);
            // 并回调mListener.onTest告诉Activity已收到消息
            if (mListener != null) {
                mListener.onTest("hi, activity");
            }
        }

        // TestBinder里面提供一个注册回调的方法
        public void setOnTestListener(OnTestListener listener) {
            mListener = listener;
        }
    }

    /**
     * 自定义一个回调接口
     */
    public interface OnTestListener {
        void onTest(String str);
    }
}

(3)使用context的bindService(Intent,ServiceConnection,int)方法启动service

public class TestActivity extends Activity implements View.OnClickListener {

    public static final String TAG = TestService.TAG + " + TestActivity";

    private Intent mStartIntent;
    private TestService.TestBinder mBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        initView();
    }

    private void initView() {
        findViewById(R.id.btn_start_service).setOnClickListener(this);
        findViewById(R.id.btn_bind_service).setOnClickListener(this);
        findViewById(R.id.btn_stop_service).setOnClickListener(this);
        findViewById(R.id.btn_unbind_service).setOnClickListener(this);
        findViewById(R.id.btn_send_msg_to_service).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_start_service:
                // 开启服务
                mStartIntent = new Intent(this, TestService.class);
                startService(mStartIntent);
                break;

            case R.id.btn_bind_service:
                // 绑定服务
                Intent bindIntent = new Intent(this, TestService.class);
                // 参数1:Intent意图
                // 参数2:是一个接口,通过这个接口接收服务开启或者停止的消息,并且这个参数不能为null
                // 参数3:开启服务时的操作,BIND_AUTO_CREATE代表自动创建service
                bindService(bindIntent, mConnection, BIND_AUTO_CREATE);
                break;

            case R.id.btn_stop_service:
                // 结束服务
                stopService(mStartIntent);
                break;
                
            case R.id.btn_unbind_service:
                // 结束连接服务
                unbindService(mConnection);
                break;

            case R.id.btn_send_msg_to_service:
                // 发送消息给Service
                if (mBinder != null) {
                    mBinder.sendMsgToService("hi, service");
                } else {
                    LogUtils.e(TAG, "请先绑定服务,再执行发送消息给Service");
                }
                break;

            default:
                break;
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 只有当TestService的onBind方法返回值不为null时,才会被调用
            LogUtils.d(TAG, "onServiceConnected");
            
            if (service != null) {
                // 取得Service里的binder对象
                mBinder = (TestService.TestBinder) service;
                // 注册自定义回调
                mBinder.setOnTestListener(new TestService.OnTestListener() {
                    @Override
                    public void onTest(String str) {
                        LogUtils.d(TAG, "收到来自Service的消息: "+str);
                    }
                });
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // 只有出现异常时才会调用,服务正常退出不会调用。
            LogUtils.e(TAG, "onServiceDisconnected");
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 结束连接服务
        unbindService(mConnection);
    }
}

(4)不使用时,调用unbindService(ServiceConnection)方法停止该服务

@Override
    protected void onDestroy() {
        super.onDestroy();
        // 结束连接服务
        unbindService(mConnection);
    }

(5)结果打印

TestService: 收到来自Activity的消息: hi, service
TestService + TestActivity: 收到来自Service的消息: hi, activity
5.1.2 通过Broadcast实现通信

(1)概要:Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好。

(2)参考链接:Android Service与Activity之间通信的几种方式

5.2 Service重要的方法运行在哪个线程?

(1)Service的onCreate、onStartCommand、onDestory等全部生命周期方法都运行在UI线程
(2)ServiceConnection里面的回调方法也是运行在UI线程;
(3)bindService后,onServiceConnected调用时机是在onCreate和onBind之后被调用 ;
(4)千万不能在Service的生命周期方法中做非常耗时的操作,否则会引起主线程卡顿,严重时还会引起ANR
(5)参考链接:【源码解析】Service几个重要的方法运行在哪个线程

5.3 Service里面可以弹出dialog或Toast吗?

(1)Toast通常使用Activity和Application的context,也可以使用Service、ContentProvider和BroadcastReceiver的context。但是在IntentService的onHandleIntent()不能使用,因为其在子线程中。
(2)Dialog只能在Activity中使用,其他组件使用会抛出异常。也有方法可以实现,如下(加个权限,在manifest中添加此权限以弹出dialog)。

<uses-permission Android:name="android.permission.SYSTEM_ALERT_WINDOW" />

dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
Builder builder = new AlertDialog.Builder(this);
builder.setMessage("是否重启服务");
builder.setNegativeButton("取消", new OnClickListense() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
           // to do
    }
});
builder.setPositiveButton("确定", new OnClickListense() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
           // to do
    }
});
final AlertDialog dialog = buidler.create();
//在dialog show前添加此代码,表示该dialog属于系统dialog。
dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
new Thread() {
     public void run() {
            SystemClock.sleep(2000);
            hanlder.post(new Runnable() {
                    @Override
                    public void run() {
                          dialog.show();
                    }
            });
     };
}.start();

参考来源于:developerzjy/ServiceDemo
(3)参考链接
Android Context 上下文 你必须知道的一切

5.4 为什么开启Service去创建子线程而不是Activity中?

(1)场景:①若直接在Activity中新开一条线程来做耗时操作,当该Activity退出到桌面或其他情况时将成为一个后台进程。②若在Service中新启动线程,则此时Android会依据进程中当前活跃组件重要程度,将其判断为服务进程,优先级比①高。
(2)因为服务进程的优先级比后台进程的优先级高,所以对于一个需要启动一个长时间操作的activity来说,开启service去创建子线程比Activity中创建子线程更好,尤其是对于操作将很可能超出activity的持续时间时。
(3)比如要上传一个图片文件,应该开启一个service来进行上传工作,这样在用户离开activity时工作仍在进行。使用service将会保证操作至少有服务进程的优先级。

5.5 如何保证Service在后台不被杀死,进程保活?

在我的另一篇博客详细解析:Android进阶之进程优先级及提高优先级的方法(进程保活)

5.6 Service与IntentService的区别?

(1)IntentService,它是继承于Service并处理异步耗时请求的一个类。
(2)可以通过startService(Intent)方式来提交请求,和启动传统Service一样;
(3)该Service会在需要的时候创建;
(4)当完成所有的任务以后会自动关闭;
(5)可以启动多次,而每一个耗时操作会以工作队列的方式在onHandleIntent()中执行,每次只会执行一个工作线程;
(6)解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题。
(7)在我的另一篇博客详细解析:Android基础之深入理解IntentService

7 参考链接

Android:Service生命周期最全面解析

Android中startService和bindService的区别 - 简书
【推荐理由】详细全面地回答了上面的问题。

Service: onStartCommand 诡异的返回值
【推荐理由】通过实例来演示onStartCommand那诡异的返回值。

【源码解析】Service几个重要的方法运行在哪个线程

15软件班安卓课程实训总结 本次安卓实训课程是一次将理论知识转化为实际开发能力的重要实践,旨在帮助同学们深入理解并熟练运用Android开发技术。在为期数周的实训过程中,邓超、李宇通和何俊松三位同学分别通过构建不同版本的音乐播放器项目,系统性地学习了从基于存储卡的本地音乐播放功能到利用媒体库及网络资源进行音乐播放的进阶技术。 阅读详情

相关推荐

目录大全_安卓面经_Android面经_150道安卓基础面试题全解析

网上安卓资料千千万,该专栏优势在于:由多方资料的精华浓缩为最经典面试题解析,并提供专栏内所有内容的免费解答和技术交流(私聊即可,当天必回),为读者保驾护航

a763450633的博客 1216

Android-Service端和Clinet端通讯-如果client被杀了

最近做了一个android的语音项目,service端集成了语音服务,该service提供相关的语音SDK,比如语音搜索音乐,然后音乐app service集成这个SDK,从而获得语音能力。 在实际开发的过程中遇到两个棘手的问题: 1 Voice Service起来了,如果Music并没有启动,有人请求语音搜索音乐,那么怎么能告诉你呢? 2 如果Music起来并且通过bind接口绑定了Voice,那么voice如何知道呢? 针对两个问题我们进行分析: 1 Voice Service起来而M..

HellDevil的专栏 750

Android跨进程通信Client Crash后Server端onDestroy

hi,粉丝朋友大家好!好久没有给大家写blog了,哈哈,这里说声抱歉!实在家里比较忙,今天就来给大家分享一个跨进程专题课中学员问的一个问题,blog就来解答一下这个问题。

learnframework的博客 1359

Android-Service的生命周期

与Activity类似,Service也有自己的生命周期函数,在不同的时刻,系统会调用对应的Service生命周期函数,不过与Activity声明周期相比,Service的声明周期更加简单,我们通过官方给出的一张图片来体会一下: Service 作为 Android四大组件之一,应用非常广泛。和Activity一样,Service 也有一系列的生命周期回调函数,我们可以用来监测 Service状态变化,并且在适当的时候执行适当的工作。 1、生命周期状态 生命周期方法说明: onCreate() :

qq_43401941的博客 1万+

Android实训八

实训8 service服务 一、【实训目的】 (1) service的生命周期。 (2) 跨进程调用AIDLserver 二、【实训内容和步骤】 1、按下图写一个布局管理,使用Service原理并实现以下按键功能, 单击“启动Service”启动一个后台service,依次输出素数(时间间隔1秒); 单击“停止Service”,停止后台service服务; 单击“绑定Service”,绑定后台service服务,依次输出素数(时间间隔1秒)...

weixin_47077788的博客 1075

web前端和安卓开发前景分析!9次Android面试经验总结,真香!

前言 作为一个3-5年的Android工程师,我们经常会遇到这些瓶颈: 1.技术视野窄 长期在小型软件公司,外包公司工作,技术视野被限制的太厉害 2.薪资提升难 初中级Android岗位薪资上升空间有限,基本上你想拿15k以上,不会点源码层的东西是根本拿不到的 3.学习资源少 入门之后想要提升很难,靠自己接触的简单业务项目,去反复操练那些cv技术。博客和书本上的技术大多比较抽象并且零散,可以借鉴和指导,但是没办法复制成自己的 有了这份阿里P7大神整理的Android开发核心知识笔记,所有的瓶颈通通都能快速打

984

双向绑定原理,面试官6个灵魂拷问,安卓系列学习进阶视频

作为一名即将求职的程序员,面对一个可能跟近些年非常不同的 2020年,你的就业机会和风口会出现在哪里?在这种新环境下,工作应该选择大厂还是小公司?已有几年工作经验的老兵,又应该如何保持和提升自身竞争力,转被动为主动? 就目前大环境来看,跳槽成功的难度比往年高很多。一个明显的感受:今年的面试,无论一面还是二面,都很考验Android程序员的技术功底。 最近搜集了一些基础问题以及阿里、腾讯2020年一些精选的面试题,最后还把把技术点梳理成一份大而全的“Android高级工程师”面试xmind(实际上比预期多花了

m0_56051002的博客 116

Android程序员该如何进阶?,一招教你看懂Netty

针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!Android前沿技术大纲全套体系化高级架构视频。

2301_77118221的博客 1036

2024腾讯Android面试题精选,offer拿到手软

发送出去的广播被广播接收者按照先后顺序接收,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,且优先级(priority)高的广播接收器会先收到广播消息。:表示Activity正在停止,此时可做一些存储数据、停止动画等工作,但是不能太耗时,因为这会影响到新Activity的显示,onPause必须先执行完,新Activity的onResume才会执行;:这种广播会一直滞留,当有匹配该广播的接收器被注册后,该接收器就会收到此条广播;

2401_85030317的博客 783

Android framework有多重要!学懂了至少15K(经验总结+内核解析 附源码)

framework解析

m0_56255097的博客 275

retrofit动态代理原理,腾讯T3团队整理,offer拿到手软

前言 这些题目是网友去百度、小米、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。 熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。 欢迎一线公司员工以及网友提交面试题库,欢迎留言。 网上的都是按照公司划分的,想找具体某一方面的知识点有点不好找,我这里就根据知识点分门别类的整理了一下,想看哪一块可以快速找到。 这是我印象深刻的一道题,很明显它是我的第一次,那时我去一家公司(暂时叫它T公司吧)面试外派到韩国三星的工作机会。T公司的面试官是一个叫Bely架构师,显然那个时候

m0_56051002的博客 139

Android学习进阶路线导航线路

一、 基础篇         需要掌握的技能如下:                1、熟练掌握基本控件以及容器控件的使用 ;                          常用的基本控件有:Button 、TextView、EditText、ListView等                          常用的容器控件有:FrameLayout、LinearLayout、Relat

hoachen的专栏 355

2021年抓住金三银四涨薪好时机,已开源

Android面试相关整理 最近有一点找工作的打算,想补下面试题。但是发现网上面试相关的文章特别多,不知道从何看起,所以简单的总结了一下我有印象的一些,方便自己随时查看,本想带下个人评价,但有些没有仔细看,而且也不敢说自己比得过下面这些大佬的水平,所以没有轻易评价,大家自己分辨好坏。 如果大家有推荐,可以给我留言,我好补上。 因为我自己喜欢看比较新的面试题,我想大家都有这个需求,所以把最后更新时间也列了出来。 正文 1、要做一个尽可能流畅的ListView,你平时在工作中如何进行优化的? 2、对于Andr

m0_53537576的博客 261

Android开发技巧!我的头条面试经历分享,深度好文

背景 惯例,先简单陈述一下自己的,91年生人,164年三本毕业后在深圳工作,末流小公司,工资13k,无房,无车,无户口。 那时候感觉生活也还行,父母有退休金,我基本上不用太操心,女朋友在一起很久了,很体贴,没有怎么要求我。 本来生活就这样一帆风顺下去我就满足了,但是去年初,女朋友家里出了一些事情,一点积蓄全给她了,后面疫情来了,家里开始催婚了,我感觉到了压力。 目前的工资无法满足生活,虽然这些年来有一点点的提升,但是,房价物价涨的更快,于是我决定跳槽。 从去年年底开始瞎投简历,回顾了一下,一共投了33份简历

m0_52308677的博客 142

【大牛疯狂教学】面试的时候突然遇到答不上的问题怎么办?2年以上经验必看

前言 许多 Android 开发者经常会问我,要学会哪些东西才能成为一个优秀的 Android 工程师?对于这个问题,他们的描述或多或少都有些差异,但是,总体来说,我们都需要学习一系列的技能,才能成为一个优秀的 Android 工程师。 在我看来,存在这样的困惑是正常的。Android 是一个巨大并且动态的生态系统,你可能需要花好几周时间去了解并学习它相关的一些工具和概念,但是最后你会发现,它们有好多都不是很重要,或者说并不是非常有用。因此,在本文中,我将分享我在 Android 开发中所使用到的重要技能,

m0_56051002的博客 119

Android深入理解Context--Service中Context的创建过程

我们分为四篇文章详细介绍Context, 这是第三篇 Android深入理解Context–Application中Context的创建过程 Android深入理解Context–Activity中Context的创建过程 Android深入理解Context–Service中Context的创建过程 Context使用的误区 因为本文是分析Service的Context创建流...

周将的博客 3325

深入理解Android相机体系结构之四

Camera Service Camera Service被设计成一个独立进程,作为一个服务端,处理来自Camera Framework 客户端的跨进程请求,并在内部进行一定的操作,随后作为客户端将请求再一次发送至作为服务端的Camera Provider,整个流程涉及到了两个跨进程操作,前者通过AIDL机制实现,后者通过HIDL机制实现,由于在于Camera Provider通信的过程中,Service是作为客户端存在的,所以此处我们重点关注AIDL以及Camera Service 主程序的实现。 Ca

u012596975的博客 1万+

Android进阶解密②—Service的启动

文章目录一 StartServiceContextImpl到AMSContextImpl.startServiceCommon()AMS到ActivityThreadActivityThread.scheduleCreateService()H的处理二 BindService:AMS的bindService逻辑都交给了`ActiveServices`ActiveServices.requestServiceBindingLocked():ActivityThread.scheduleBindService(

weixin_46824291的博客 382
上一篇: Android进阶之深入理解BroadcastReceiver
下一篇: Android进阶之深入理解ContentProvider
一枚-狗子
博客等级 码龄14年 1619粉丝 192原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值