Android开发,感觉一直停留在原地,如何提升?

Posted 初一十五啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发,感觉一直停留在原地,如何提升?相关的知识,希望对你有一定的参考价值。

前言

可能有很多朋友在做了多年技术之后都会进入一个迷茫期,对自己所负责的业务逻辑非常熟悉,但是每天就只是和各种需求和Bug打交道而已,总感觉对自身能力的提升并不大。虽然在公司里属于不可缺少的一员,但是同时又担心离开了这家公司就找不到更好的工作了。

有这种焦虑的朋友或许应该思考一下这个问题:如何提升自己在 android 市场上的竞争力?

本文:
一丶Android应该学那些东西?
二丶2022最新Android十一位大厂面试专题

关注+私信(笔记)解锁《整套50W字Android体系PDF》,让学习更贴近未来实战。
50W字,腾讯T10级Android高级工程师成长;内容全在这里了

总共囊括

1.腾讯Android开发笔记(33W字)

2.2022最新Android十一位大厂面试专题(12W字)

3.音视频经典面试题(6W字)

一、提升通用技术能力

当你觉得进入到迷茫或者瓶颈期的时候其实更应该注重基础,也就是更加通用的技术。

一来通用技术如数据结构和算法、计算机网络、操作系统、计算机系统结构等,对技术的深层理解有很大的帮助,二来这类技术在不同的语言和技术方向上切换时是共通的。

比如:二叉树的层次遍历

本文主要介绍了二叉树的按层遍历。并且分别用如下三种方式实现:

  • 哈希表结合LinkedList
  • 使用系统自带的LinkedList
  • 自定义队列

以上方法只是空间复杂度有所差异,时间复杂度上都是一样的。

①示例二叉树

这个二叉树按层次遍历的结果就是
1->2->3->4->5->6->7->8->9->10->11->12->13

②数据结构

public static class TreeNode 
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() 
    

    TreeNode(int val) 
        this.val = val;
    

    TreeNode(int val, TreeNode left, TreeNode right) 
        this.val = val;
        this.left = left;
        this.right = right;
    

③流程

整个过程最核心的地方就是需要记录当前层什么时候遍历完毕以及当前弹出的节点在第几层。

方法1中,使用哈希表来存每个节点当前所在的层,头节点默认在第0层,且将头节点首先入队列,然后在弹出的过程中,将弹出节点的子节点放入哈希表,且把层数设置为当前节点的层数+1,同时把子节点放入队列,然后进行同样的队列弹出操作,直到队列空。

方法1的完整代码如下

  public static List<List<Integer>> levelOrder(TreeNode head) 
        if (head == null) 
            return new ArrayList<>();
        
        List<List<Integer>> ans = new ArrayList<>();
        // 记录某个节点在第几层
        Map<TreeNode, Integer> map = new HashMap<>();
        Queue<TreeNode> queue = new LinkedList<>();
        // 当前是第几层
        int curLevel = 0;
        TreeNode cur = head;
        queue.offer(cur);
        map.put(cur, curLevel);
        List<Integer> levelRecords = new ArrayList<>();
        while (!queue.isEmpty()) 
            TreeNode c = queue.poll();
            int level = map.get(c);
            if (c.left != null) 
                queue.offer(c.left);
                map.put(c.left, level + 1);
            
            if (c.right != null) 
                queue.offer(c.right);
                map.put(c.right, level + 1);
            
            if (curLevel == level) 
                levelRecords.add(c.val);
             else 
                ans.add(levelRecords);
                levelRecords = new ArrayList<>();
                levelRecords.add(c.val);
                curLevel = level;
            
        
        // 记得要存最后一层的数据
        ans.add(levelRecords);
        return ans;
    

方法2省略了一个哈希表,使用了两个变量来判断层数的变化,分别是:

// 遍历到的当前层的最后一个位置
TreeNode curEnd; 
// 下一层的最后一个位置
TreeNode nextEnd;

在队列每次弹出元素的时候,设置nextEnd变量,同时,如果弹出的元素等于curEnd,说明已经到当前层的结尾了,就可以收集这一层的答案了。

方法2的完整代码如下

public static List<List<Integer>> levelOrder2(TreeNode head) 
        if (head == null) 
            return new ArrayList<>();
        
        List<List<Integer>> ans = new ArrayList<>();
        List<Integer> levelRecords = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        TreeNode curEnd = head;
        TreeNode nextEnd = null;
        queue.offer(curEnd);
        while (!queue.isEmpty()) 
            TreeNode c = queue.poll();
            levelRecords.add(c.val);
            if (c.left != null) 
                queue.offer(c.left);
                // 弹出的时候,设置nextEnd
                nextEnd = c.left;
            
            if (c.right != null) 
                queue.offer(c.right);
               // 弹出的时候,设置nextEnd
                nextEnd = c.right;
            
            if (c == curEnd) 
                // 即将要来到新的一层了
                curEnd = nextEnd;
                ans.add(levelRecords);
                levelRecords = new ArrayList<>();
            
        
        return ans;
    

方法3只是把方法2中的链表和队列换成自己实现的链表和队列结构,大思路上和方法2一样,我们可以自己实现一个链表和队列,实现最简单的poll和offer方法即可,自定义的链表如下:

  // 自定义链表
  public static class MyNode 
        public TreeNode data;
        public MyNode next;
    
        public MyNode(TreeNode node) 
            data = node;
        
    
    // 自定义队列
    public static class MyQueue 
        public MyNode front;
        public MyNode end;
        public int size;

        public MyQueue() 
            front = null;
            end = null;
        

        public void offer(MyNode c) 
            size++;
            if (front == null) 
                front = c;
             else 
                end.next = c;
            
            end = c;
        

        public boolean isEmpty() 
            return size == 0;
        

        public MyNode poll() 
            size--;
            MyNode ans = front;
            front = front.next;
            ans.next = null;
            return ans;
        

    

然后把方法2中的Java自带的LinkedList换成我们自己实现的链表和队列,完整代码如下

    public static List<List<Integer>> levelOrder(TreeNode root) 
        List<List<Integer>> ans = new ArrayList<>();
        if (root == null) 
            return ans;
        
        MyNode head = new MyNode(root);
        MyQueue queue = new MyQueue();
        queue.offer(head);
        MyNode curEnd = head;
        MyNode nextEnd = null;
        List<Integer> item = new ArrayList<>();
        MyNode t;
        while (!queue.isEmpty()) 
            MyNode c = queue.poll();
            if (c.data.left != null) 
                t = new MyNode(c.data.left);
                queue.offer(t);
                nextEnd = t;
            
            if (c.data.right != null) 
                t = new MyNode(c.data.right);
                queue.offer(t);
                nextEnd = t;
            
            item.add(c.data.val);
            if (curEnd.data == c.data) 
                ans.add(item);
                item = new ArrayList<>();
                curEnd = nextEnd;
            
        
        return ans;
    

还有:排序,哈希表,数组,堆,栈等等。
算法面试PDF文档
关注+私信(算法)免费领取

二、提升软实力

软实力实际上也是一项通用的技能,甚至比第一条更加通用。

良好的沟通可以缩短开会的时长、节省相互之间的沟通成本,也使得团队合作更加愉快。不错的文档表达能力可以省去不少的重复沟通。

懂得规划自己的时间,上班时能更有条不紊地完成任务,下班也能高效地规划业余时间的学习。

懂得反思:为什么这个任务预计五小时能完成,却变成了三天;为什么这个需求要这样做,这么做是最合理的吗,还有更好的方式吗?

对问题、业务和自身的更多思考有助于更好地发挥和展现你的技术实力。

三、选择一个细分领域不断深入

可能一个较好的学习方式是先广度优先遍历,即粗略了解自己领域的各方面知识,然后深度优先遍历,即选择一个自己感兴趣或者觉得值得深入的方向深挖下去,等到这个方向学习研究得差不多了,再去深入下一个方向的技术知识。例如:

插件化技术、响应式编程、组件化框架、系统架构等进阶技术,承托着业务之下的基础框架,能够使得开发者在面对需求和功能变化的时候有更快的反应和更优雅的行动。

业务逻辑日渐成熟的形势下,用户体验越来越重要,突然的软件崩溃或是加载图标持续5秒,对于高质量应用都是阻碍。渲染速度、网络请求体验、I/O优化、热修复技术、耗电优化,都是性能优化需要重视的点。

Android 现在细分的领域非常多,应用开发、音视频、物联网、逆向安全、SDK开发等等,可以在这些领域中选择一个并不断深入。若是从时代背景的角度考虑,当下处于信息时代,用户接收和喜爱信息传播的形式一路从文字、图片、音频、视频,到了如今的直播。音视频会是一个不错的选择。其中会涉及到音视频编解码和音视频同步处理、特效处理、合成等等技术,对于 Android 底层源码的理解也十分有帮助。

下图是我对整体Android的一个路线整理:

细分为九大板块,每一个专题板块都是非常值得我们去深入了解其原理的,每块内容都配套有对应的文档资料,可以将Android核心知识点全部串联起来,实现系统性的学习。

有需要完整版的朋友
50W字,腾讯T10级Android高级工程师成长;内容全在这里了

一丶 项目开发必备底层技术

不光是一线大厂,各大互联网公司Android研发岗位都要求有扎实的Java基础,并要求Android开发者掌握其原理,这一个部分就是Android开发中最常用的Java相关知识。

Android以Java语言为基础,以虚拟机为核心,经过Daivlk虚拟机再到Art虚拟机演变,所以需要学两大底层:一个是Java语言底层,一个是虚拟机底层。

Java底层涵盖:Java序列化、泛型与反射、JDK高级动态代理、 Java高级并发原理详解。

虚拟机底层涵盖:虚拟机层类加载机制、Android虚拟机原理剖析、dex运行机制,Android内存,高级数据结构与算法

Java知识点汇总:序列化、注解、泛型、反射、虚拟机、并发、Java IO、编译时技术、动态代理、高级数据结构与算法等

二丶Framework

Android Framework的一个整体学习也是为了让我们深入本质,了解谷歌如何去吧Android系统写出来的,同时这些方案会对我们日常写代码过程中出现的各种各样的问题会有一个怎么的反应和反馈,按照整体的学习路线的话,首先第一个先要去搞定一个BinderHandler相关的所谓的一个跨进程通信的问题,因为它肯定是多方软件在进行一个相关的协调处理,所以第一时间要去了解Handler和Binder的进程通信问题,接着了解如何开机,APK如何安装,如何启动,整个APP启动过程中画面如何渲染出来,以及触摸信号如何处理。了解了这些东西后基本上可以是一个初中级的一个开发者过度到高级开发的过程。


Framework知识点涉及

  • Framework通信:Handler,Binder,Livedata事件机制
  • Framework底层服务:AMS,PMS,WMS,IMS
  • Framework事件机制

三丶性能优化

作为一个Android程序员,性能优化是无法避开的事情,并且性能优化也是Android中最有挑战的工作之一,更是每个工程师都需要掌握的核心技能。

性能问题和Bug不同,后者的分析和解决思路更清晰,很多时候从应用日志即可直接找到问题根源,而性能问题,其排查思路更为复杂一些。

对App进行性能优化,是一个系统性的工程,对工程师的技术广度和技术深度都有所要求。一个简单的应用,它不仅包含了应用代码本身,还和虚拟机、存储、网络等紧密相关,线上应用一旦出现了性能问题,需要我们从多方面去考虑。

性能优化知识点汇总:启动优化、UI渲染优化、崩溃优化、内存优化、卡顿优化、存储优化、网络优化、耗电优化、多线程并发优化、安装包优化等

四丶引领5G时代 高级音视频技术

在音视频中H264和音视频应用中占比非常大,像H264编码学会了后才会对音视频真正有所了解,在音视频中最核心的在于它的编码原理,比如H264的码流,I/P/B帧的编码流程。

音视频剪映,比如Bilibili,IJKplayer,抖音直播特效,音视频通话这部分都属于音视频应用,当你把整个音视频编码和应用学好之后才能真正成为一个音视频开发工程师,而且音视频开发的薪资也是非常的可观的。

音视频技术知识点汇总:C/C++、JNI、H.265/H.265、MediaCodec、音视频剪辑、音视频直播、OpenGL与音视频解码、OpenGL特效、FFmpeg万能播放器、Webrtc音视频通话等

五丶架构

“没有最好的架构,只有最合适的架构。”

架构这块主要是对各大主流框架和一线大厂核心框架进行剖析,理解其中原理,并学习架构设计思想。我们在架构设计中最本质的目的就是管理复杂度,你听过的各种思想、原则、方法大多都是为了控制复杂度而设计出来的。

而提升架构设计硬实力,唯有不断地实战,任何一个架构师都是身经百战的老兵!

架构涉及知识点:Arraylist,Okhttp,Retrofit,图片加载,Dagger2,MVC.MVP.MVVM,Jetpack Room

六丶Flutter3.0开发

Flutter现在最新版本是3.0版本,flutter如何学习,首先第一步是Dart语法接着是Flutter3.0的应用比如Widget和普通的UI。如果想要达到Flutter的进阶哪还要去了解FlutterFrameworkflutter FrameworkAndroid Framework有很大的不一样,这个时候要了解到Skiaflutter应用启动,Dart虚拟机等。

Flutter知识涉及:Dart语法,Flutter动画丶组件丶网络请求以及Flutter3.0简介

七丶车载应用

车载系统开发,包括蔚来汽车,比亚迪汽车他们如何开发车机,车机会涉及到通信。所以通信又是车载中很重要的一环,车载通信里包含串口,USB。车载中Automotive系统会涉及到系统原理,车载网络模型,以及开发一个车载应用APP。

车载系统会涉及到一些Framework,Android系统和车载系统有一些东西是相通的,至少在Framework这一层是相通的,所以在学习车载之前还是要掌握Framework,包括Framework启动模式,所以又会涉及到一些启动模式启动流程的理解。最后再以专业的CarLauncher开发去开发出一个完整的车载系统出来,包括车载的多媒体如何调动车载的硬件比如空调,车窗以及一些偏底层硬件。时代在进步,科技在进步,很多大厂都在进军车载应用,我们要紧跟时代的脚步。

涉及:Android Auto,汽车媒体应用,构建Android Auto即时通信应用,构建车载导航和地图注点应用,构建Android Automotive OS视频应用,测试Android车载应用,分发Android汽车应用,适用于汽车的Google Play服务,Android Automotive OS的通知.

八丶Kotlin入门到精通

Kotlin在2017年被作为Android一级开发语言,又在2019年被确立为Android的首选开发语言,这门语言近些年的发展得到了前所未有的支持和关注。在一些大厂的开发岗位中也对Kotlin语言青睐有加,越来越多的岗位对Kotlin语言掌握程度提出新的要求和标准,所以这块也是非常有必要深入学习的。

九丶鸿蒙系统专题

鸿蒙作为5G时代万物互联的时代性产品,历经了一段时间的发酵,现在再去讨论是不是Android套皮已经没有任何意义,它的出现直接改变了移动端物联网格局,在全世界范围内掀起一股热潮,作为国产系统也是经受了国内外媒体的验证,相信在不远的将来,鸿蒙系统将会在物联网领域产生非常重要的作用。

而物联网作为移动开发的细分领域,移动开发者掌握了鸿蒙开发必然掌握先机,在面试及企业项目中会产生意想不到的效果。

十丶2022最新Android十一位大厂面试专题

包含:腾讯,阿里,百度,京东,字节,小红书,爱奇艺,携程,小米,Bilibili,网易。十一大厂最新128道面试真题

Android路漫漫,时代在进步,技术也在不断更替,只有不断地学习,不断地突破技术壁障,很多时候技术提升上来了,其他各方面也都会感觉非常如意。

关注+私信(笔记)解锁《整套50W字Android体系PDF》,让学习更贴近未来实战。
50W字,腾讯T10级Android高级工程师成长;内容全在这里了

总共囊括

1.腾讯Android开发笔记(33W字)

2.2022最新Android十一位大厂面试专题(12W字)

3.音视频经典面试题(6W字)

以上是关于Android开发,感觉一直停留在原地,如何提升?的主要内容,如果未能解决你的问题,请参考以下文章

生活计划

感觉技术停滞时,该怎么办?(离开舒适区,刻意练习)

移动层导致物理对象停留在原地

学会编写Android Studio插件 别停留在用的程度了

Java虚拟机,这是值得你去进阶的方向

普通Android开发如何进阶为Android高级工程师?