互联网BAT大厂(百度、美团等)Android岗必问面试原题+解析(1)

当我们调用Acitivity的 setContentView方法的时候实际上是调用的Window对象的setContentView方法,所以我们可以看出Activity中关于界面的绘制实际上全是交给Window对象来做的。
Activity—>Window—>DecorView
Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图) LayoutInflater像剪刀,Xml配置像窗花图纸。

  • 在Activity中调用attach,创建了一个Window
  • 创建的window是其子类PhoneWindow,在attach中创建PhoneWindow
  • 在Activity中调用setContentView(R.layout.xxx)
  • 其中实际上是调用的getWindow().setContentView()
  • 调用PhoneWindow中的setContentView方法
  • 创建ParentView:作为ViewGroup的子类,实际是创建的DecorView(作为 FramLayout的子类)
  • 将指定的R.layout.xxx进行填充通过布局填充器进行填充【其中的parent指的>* 就是DecorView】
  • 调用到ViewGroup
  • 调用ViewGroup的removeAllView(),先将所有的view移除掉
  • 添加新的view:addView()

fragment 特点

  • Fragment可以作为Activity界面的一部分组成出现;
  • 可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;
  • 在Activity运行过程中,可以添加、移除或者替换Fragment;
  • Fragment可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主Activity的生命周期影响。
  1. 描述一次网络请求的流程(新浪)
  1. Handler、 Thread 和 HandlerThread 的差别(小米)
  • Thread是一个线程;
  • 我们知道Handler是用来异步更新UI的,更详细的说是用来做线程间的通信的,更新UI时是子线程与UI主线程之间的通信。那么现在我们要是想子线程与子线程之间的通信要怎么做呢?当然说到底也是用Handler+Thread来完成(不推荐,需要自己操作Looper)
  • HandlerThread就是(Handler+Thread结合),HandlerThread其实还是一个线程,它跟普通线程有什么不同之处是多了一个Looper,这个是子线程独有的Looper,用来做消息的取出和处理。
  1. 低版本 SDK 实现高版本 api(小米)

在使用高于minSdkVersion API level的方法需要:

  • 用@TargeApi($API_LEVEL) 使可以编译通过, 不建议使用@SuppressLint(“NewApi”);
  • 运行时判断API level; 仅在足够高,有此方法的API level系统中,调用此方法;
  • 保证功能完整性,保证低API版本通过其他方法提供功能实现。
  1. launch mode 应用场景(百度、小米、乐视)
  • standard:每次激活Activity时都会创建Activity实例,并放入任务栈中。这个是默认的;
  • singleTop:如果已经存在在栈顶在对方的任务一个同类型的活动实例,不会有任何新的activity创造,而是被发送到一个存在的activity实例通过onNewIntent() 方法的意图,即会重用该实例调用当前activity的onNewIntent() 方法。适合接收通知启动的内容显示页面。
    例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。
  • singleTask:如果系统中有一个存在的活动实例,整个任务将实例将被移动到顶部,Intent将通过onnewintent()方法交付。否则,新的activity将被创建并放置在适当的任务中。适合作为程序入口点。
    例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。
  • singleInstance适合需要与程序分离开的页面。
    例如闹铃提醒,将闹铃提醒与闹铃设置分离。
    singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。
  1. touch 事件传递流程(小米)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. view 绘制流程(百度)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://www.jianshu.com/p/5a71014e7b1b
11. 什么情况导致内存泄漏(美团)

  • 1.单例造成的内存泄漏
    由于单例的静态特性使得其生命周期和应用的生命周期一样长,如果一个对象已经不再需要使用了,而单例对象还持有该对象的引用,就会使得该对象不能被正常回收,从而导致了内存泄漏。

  • 2.非静态内部类创建静态实例造成的内存泄漏
    例如,有时候我们可能会在启动频繁的Activity中,为了避免重复创建相同的数据资源,可能会出现如下写法:

public class MainActivity extends AppCompatActivity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mResource == null){
mResource = new TestResource();
}
//…
}

class TestResource {
//…
}
}

这样在Activity内部创建了一个非静态内部类的单例,每次启动Activity时都会使用该单例的数据。虽然这样避免了资源的重复创建,但是这种写法却会造成内存泄漏。因为非静态内部类默认会持有外部类的引用,而该非静态内部类又创建了一个静态的实例,该实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用,从而导致Activity的内存资源不能被正常回收。

解决方法:将该内部类设为静态内部类或将该内部类抽取出来封装成一个单例,如果需要使用Context,就使用Application的Context。

  • 3.Handler造成的内存泄漏

示例:创建匿名内部类的静态对象

public class MainActivity extends AppCompatActivity {
private final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// …
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
// …
handler.sendEmptyMessage(0x123);
}
});
}
}

1、从Android的角度
当Android应用程序启动时,该应用程序的主线程会自动创建一个Looper对象和与之关联的MessageQueue。当主线程中实例化一个Handler对象后,它就会自动与主线程Looper的MessageQueue关联起来。所有发送到MessageQueue的Message都会持有Handler的引用,所以Looper会据此回调Handle的handleMessage()方法来处理消息。只要MessageQueue中有未处理的Message,Looper就会不断的从中取出并交给Handler处理。另外,主线程的Looper对象会伴随该应用程序的整个生命周期。
2、 Java角度
在Java中,非静态内部类和匿名类内部类都会潜在持有它们所属的外部类的引用,但是静态内部类却不会。

对上述的示例进行分析,当MainActivity结束时,未处理的消息持有handler的引用,而handler又持有它所属的外部类也就是MainActivity的引用。这条引用关系会一直保持直到消息得到处理,这样阻止了MainActivity被垃圾回收器回收,从而造成了内存泄漏。

**解决方法:**将Handler类独立出来或者使用静态内部类,这样便可以避免内存泄漏。

  • 4.线程造成的内存泄漏

示例:AsyncTask和Runnable
AsyncTask和Runnable都使用了匿名内部类,那么它们将持有其所在Activity的隐式引用。如果任务在Activity销毁之前还未完成,那么将导致Activity的内存资源无法被回收,从而造成内存泄漏。
**解决方法:**将AsyncTask和Runnable类独立出来或者使用静态内部类,这样便可以避免内存泄漏。

  • 5.资源未关闭造成的内存泄漏

对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,从而造成内存泄漏。
1)比如在Activity中register了一个BraodcastReceiver,但在Activity结束后没有unregister该BraodcastReceiver。
2)资源性对象比如Cursor,Stream、File文件等往往都用了一些缓冲,我们在不使用的时候,应该及时关闭它们,以便它们的缓冲及时回收内存。它们的缓冲不仅存在于 java虚拟机内,还存在于java虚拟机外。如果我们仅仅是把它的引用设置为null,而不关闭它们,往往会造成内存泄漏。
3)对于资源性对象在不使用的时候,应该调用它的close()函数将其关闭掉,然后再设置为null。在我们的程序退出时一定要确保我们的资源性对象已经关闭。
4)Bitmap对象不在使用时调用recycle()释放内存。2.3以后的bitmap应该是不需要手动recycle了,内存已经在java层了。

  • 6.使用ListView时造成的内存泄漏

初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的View对象,同时ListView会将这些View对象缓存起来。当向上滚动ListView时,原先位于最上面的Item的View对象会被回收,然后被用来构造新出现在下面的Item。这个构造过程就是由getView()方法完成的,getView()的第二个形参convertView就是被缓存起来的Item的View对象(初始化时缓存中没有View对象则convertView是null)。
构造Adapter时,没有使用缓存的convertView。
**解决方法:**在构造Adapter时,使用缓存的convertView。

  • 7.集合容器中的内存泄露

我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。
解决方法:
在退出程序之前,将集合里的东西clear,然后置为null,再退出程序。

  • 8.WebView造成的泄露

当我们不要使用WebView对象时,应该调用它的destory()函数来销毁它,并释放其占用的内存,否则其长期占用的内存也不能被回收,从而造成内存泄露。
解决方法:
为WebView另外开启一个进程,通过AIDL与主线程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

  1. ANR 定位和修正

如果开发机器上出现问题,我们可以通过查看/data/anr/traces.txt即可,最新的ANR信息在最开始部分。

  • 主线程被IO操作(从4.0之后网络IO不允许在主线程中)阻塞。
  • 主线程中存在耗时的计算
  • 主线程中错误的操作,比如Thread.wait或者Thread.sleep等 Android系统会>* 监控程序的响应状况,一旦出现下面两种情况,则弹出ANR对话框
  • 应用在5秒内未响应用户的输入事件(如按键或者触摸)
  • BroadcastReceiver未在10秒内完成相关的处理
  • Service在特定的时间内无法处理完成 20秒
    修正
  • 使用AsyncTask处理耗时IO操作。
  • 使用Thread或者HandlerThread时,调用Process.setThreadPriority(Process.THREADPRIORITYBACKGROUND)设置优先级,否则仍然会降低程序响应,因为默认Thread的优先级和主线程相同。
  • 使用Handler处理工作线程结果,而不是使用Thread.wait()或者Thread.sleep()来阻塞主线程。
  • Activity的onCreate和onResume回调中尽量避免耗时的代码
  • BroadcastReceiver中onReceive代码也要尽量减少耗时,建议使用IntentService处理。
  1. 什么情况导致 oom(乐视、美团)

这个跟11好像差不多

  1. Android Service 与 Activity 之间通信的几种方式
  • 通过Binder对象
  • 通过Intent
  • 通过Broadcast广播
  • 自定义接口回调
  1. Android 各个版本 API 的区别

http://blog.csdn.net/u012964796/article/details/50662564

  1. 如何保证一个后台服务不被杀死,比较省电的方式是什么?(百度)
  • 双进程守护(就是开启二个service,二个service是不同的进程中,用aidl监听,有一个service杀死了,另一个service监听到了就重新启动刚杀死的service),这个有时间时专门写文章介绍;
  • service绑定通知栏成为前台服务,
  • 还有一个就是锁屏时启动一个像素的activity,哈哈,好像某应用就是这么干的;
  • AlarmManager不断启动service
  • 通过jni调用,在c层启动多进程
  1. Requestlayout, onlayout, onDraw, DrawChild 区别与联系(猎豹)

requestLayout()方法 :会导致调用measure()过程 和 layout()过程 。 将会根据标志位判断是否需要ondraw
onLayout()方法(如果该View是ViewGroup对象,需要实现该方法,对每个子视图进行布局)
调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法)
drawChild()去重新回调每个子视图的draw()方法

  1. invalidate()和 postInvalidate() 的区别及使用(百度)

postInvalidate() 方法在非 UI 线程中调用,通知 UI 线程重绘。
invalidate() 方法在 UI 线程中调用,重绘当前 UI。

  1. Android 动画框架实现原理

Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是整个View,实现原理是每次绘制视图时View所在的ViewGroup中的drawChild函数获取该View的Animation的Transformation值,然后调用canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧,如果动画没有完成,继续调用invalidate()函数,启动下次绘制来驱动动画,动画过程中的帧之间间隙时间是绘制函数所消耗的时间,可能会导致动画消耗比较多的CPU资源,最重要的是,动画改变的只是显示,并不能相应事件。

  1. Android 为每个应用程序分配的内存大小是多少?(美团)

android程序内存一般限制在16M,也有的是24M

  1. Android View 刷新机制(百度、美团)

由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些“需要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图需要重绘时,就会为该View添加该标志位。

调用流程 :

mView.draw()开始绘制,draw()方法实现的功能如下:

绘制该View的背景为显示渐变框做一些准备操作(见5,大多数情况下,不需要改渐变框)调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法)调用dispatchDraw ()方法绘制子视图(如果该View类型不为ViewGroup,即不包含子视图,不需要重载该方法)值得说明的是,ViewGroup类已经为我们重写了dispatchDraw ()的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。

  1. LinearLayout 对比 RelativeLayout(百度)(Ricky)

RelativeLayout会让子View调用2次onMeasure,LinearLayout 在有weight时,也会调用子View2次onMeasure,RelativeLayout的子View如果高度和RelativeLayout不同,则会引发效率问题,当子View很复杂时,这个问题会更加严重。如果可以,尽量使用padding代替margin。在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。
最后再思考一下文章开头那个矛盾的问题,为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。

  1. 优化自定义 view(百度、乐视、小米)

为了加速你的view,对于频繁调用的方法,需要尽量减少不必要的代码。先从onDraw开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致GC,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。

你还需要尽可能的减少onDraw被调用的次数,大多数时候导致onDraw都是因为调用了invalidate().因此请尽量减少调用invaildate()的次数。如果可能的话,尽量调用含有4个参数的invalidate()方法而不是没有参数的invalidate()。没有参数的invalidate会强制重绘整个view。

另外一个非常耗时的操作是请求layout。任何时候执行requestLayout(),会使得Android UI系统去遍历整个View的层级来计算出每一个view的大小。如果找到有冲突的值,它会需要重新计算好几次。另外需要尽量保持View的层级是扁平化的,这样对提高效率很有帮助。

如果你有一个复杂的UI,你应该考虑写一个自定义的ViewGroup来执行他的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,这避免了遍历整个view的层级结构来计算大小。这个PieChart 例子展示了如何继承ViewGroup作为自定义view的一部分。PieChart 有子views,但是它从来不测量它们。而是根据他自身的layout法则,直接设置它们的大小。

  1. ContentProvider(乐视)

http://blog.csdn.net/coder_pig/article/details/47858489
https://www.jianshu.com/p/f5ec75a9cfea

  1. fragment 生命周期

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. volley 解析(美团、乐视)

https://www.jianshu.com/p/15e6209d2e6f

  1. Android Glide 源码解析

http://blog.csdn.net/guolin_blog/article/details/53759439

  1. Android 属性动画特性(乐视、小米)

https://www.jianshu.com/p/8076fe970a0c

  1. Handler 机制及底层实现

http://blog.csdn.net/lmj623565791/article/details/38377229

  1. Binder 机制及底层实现

http://blog.csdn.net/weijinqian0/article/details/52233529

Java 基础
  1. 接口的意义(百度)

1、重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。

2、简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。

3、维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类。可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦。

如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。

4、安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。

  1. 抽象类的意义(乐视)

抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。具体分析如下:

1.因为抽象类不能实例化对象,所以必须要有子类来实现它之后才能使用。这样就可以把一些具有相同属性和方法的组件进行抽象,这样更有利于代码和程序的维护。

2.当又有一个具有相似的组件产生时,只需要实现该抽象类就可以获得该抽象类的那些属性和方法。

  1. 内部类的作用(百度,乐视)

定义:放在一个类的内部的类我们就叫内部类。

作用:

1.内部类可以很好的实现隐藏,一般的非内部类,是不允许有 private 与protected权限的,但内部类可以

2.内部类拥有外围类的所有元素的访问权限

3.可是实现多重继承

4.可以避免修改接口而实现同一个类中两种同名方法的调用。

  1. 父类的静态方法能否被子类重写,为什么?(猎豹)

父类的静态方法是不能被子类重写的,其实重写只能适用于实例方法,不能用于静态方法,对于上面这种静态方法而言,我们应该称之为隐藏。

Java静态方法形式上可以重写,但从本质上来说不是Java的重写。因为静态方法只与类相关,不与具体实现相关。声明的是什么类,则引用相应类的静态方法(本来静态无需声明,可以直接引用)。并且static方法不是后期绑定的,它在编译期就绑定了。换句话说,这个方法不会进行多态的判断,只与声明的类有关。

  1. 举 1-2 个排序算法,并使用 java 代码实现(美团)

  2. 列举 java 的集合和继承关系(百度、美团)

  3. java 虚拟机的特性(百度、乐视)

Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。

  1. 哪些情况下的对象会被垃圾回收机制处理掉(乐视、美团、小米)

Java 垃圾回收机制最基本的做法是分代回收。内存中的区域被划分成不同的世代,对象根据其存活的时间被保存在对应世代的区域中。一般的实现是划分成3个世代:年轻、年老和永久。内存的分配是发生在年轻世代中的。当一个对象存活时间足够长的时候,它就会被复制到年老世代中。对于不同的世代可以使用不同的垃圾回收算法。进行世代划分的出发点是对应用中对象存活时间进行研究之后得出的统计规律。一般来说,一个应用中的大部分对象的存活时间都很短。比如局部变量的存活时间就只在方法的执行过程中。基于这一点,对于年轻世代的垃圾回收算法就可以很有针对性。
(1)超出对象的引用句柄的作用域时,这个引用句柄引用的对象就变成垃圾。

(2)没有超出对象的引用句柄的作用域时,给这个引用句柄赋值为空时,这个引用句柄引用的对象就变成垃圾。

(3)创建匿名对象时,匿名对象用完以后即成垃圾。

  1. 进程和线程的区别(猎豹)

进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同。

  1. 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
  2. 线程的划分尺度小于进程,使得多线程程序的并发性高。
  3. 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
  4. 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
  5. 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

这里我特地整理了一份《Android开发核心知识点笔记》,里面就包含了自定义View相关的内容

除了这份笔记,还给大家分享 Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。

分享上面这些资源,希望可以帮助到大家提升进阶,如果你觉得还算有用的话,不妨把它们推荐给你的朋友~

喜欢本文的话,给我点个小赞、评论区留言或者转发支持一下呗~

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

jtfqA-1713501732055)]

除了这份笔记,还给大家分享 Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。

[外链图片转存中…(img-8wMWOUul-1713501732056)]

分享上面这些资源,希望可以帮助到大家提升进阶,如果你觉得还算有用的话,不妨把它们推荐给你的朋友~

喜欢本文的话,给我点个小赞、评论区留言或者转发支持一下呗~

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值