读android源码有什么用_android studo 读源码 - CSDN
  • 平时我们在用Android Studio开发项目的时候,如果想要查看源码,直接 Ctrl + 左键 查看对应的源码,你可能会发现一些具体源码看不到,或者部分代码飘红。我们就来说说这一部分。

    文章最早发布于我的微信公众号 Android_De_Home 中,欢迎大家扫描下面二维码关注微信公众获取更多知识内容。
    本文为sydMobile原创文章,可以随意转载,但请务必注明出处!

    平时我们在用Android Studio开发项目的时候,如果想要查看源码,直接 Ctrl + 左键 查看对应的源码,你可能会发现有一些具体源码看不到,或者部分代码飘红。我们就来说说这一部分。

    IDE查看源码出现的问题

    我们的Android项目都是需要依赖Android SDK里对应的API Level的android.jar包的,这样才可以使用Android提供的API,在IntelliJ里面,查看具体类的源码的时候,如果Android SDK里对应的API Level的Source包有下载的话,IDE会打开对应的Source包,如果没有下载的话,IDE会把对应的API Level的android.jar包反编译场成Java代码,这个规则对于其他的一些第三方的开源项目也是一样的。但是你最好还是下载Source源码来查看,有的时候反编译的Java代码不可能完全和源代码一样,有时候反编译的代码的执行逻辑可能完全等价,但是可阅读性不好,有可能会缺少重要的代码注释。

    因为Android SDK自带的Source源码包很小(你可能会说已经好几个G了还小啊,后面会讲到真正的Android源码,哪个时候你就知道了),并没有包括所有的Android Framework的源代码仅仅是提供给应用开发者参考使用,有一些比较少的系统类的源码没有给出,所有你有可能在查看源代码的时候看到这种情况
    RuntimeException(“Stub”)
    runtimeexception
    查看代码的时候遇到这种情况,表示实际运行的时候逻辑会到Android ROM(这里Android ROM可以理解为你Android手机的Android系统,里面同样也包含了你在开发的时候用到的类)里面找相对应的类和方法来代替执行。
    此外我们在IDE中查看源代码的时候,还会经常看到一些类和方法中会出现报红(也就是找不到)的情况,这种情况在我们查看源代码的时候是很常见的。
    飘红

    这种情况并不是说这些方法或者变量是不存在的,而是这些方法因为出于安全或者某些原因被我们使用的Android SDK隐藏了,这些API不直接暴露给应用层的开发者,这些类和方法在Android源码编译完成的android.jar包里面会把这些API隐藏(如果是你自己编译的Android源码的话就不会了,后面的文章会讲),而我们的Android项目是依赖这个编译后的android.jar包的,所以我们在查看源码的时候,IDE就会自动去android.jar里面找对应的API,所以就会出现这种情况了,实际上这种API同样在ROM中是存在的,有些开发者发现了一些可以修改系统行为的隐藏API,在应用层通过反射的方式强行调用这些API执行系统功能,这种手段也是一种HACK。

    上面讲了我们在IDE中直接查看源码有可能会出现的问题,下面就介绍一下怎么查看完整的源码。

    查看完整源码

    当你需要查看完整源码的时候,需要去AOSP(Android Open Source Project)项目里面找了,(需要科学上网)这个里面放着Android真正的完整源码,这里所说的完整源码不仅仅包括Android系统的源码还包括了一些开发工具比如:aapt、adb等等。
    android源码
    选择自己需要的下先来,如果全部下载下来估计有几个T吧,不过其实是不需要的,作为应用层的开发,我们看应用层源码就好了
    应用层源码

    介绍查看源码工具:

    1. Chrome扩展工具
      Android SDK Search
      使用这个插件在谷歌浏览器中,打开Android的官网查看API说明的时候,会有个按钮,通过点击这个按钮就可以直接跳转到AOSP中对应的源码中
      插件

      注意仅适用于Android开发者官网上查看API文档,不适用国内的那个镜像网址。
    2. Source Insight查看完整源码
      一个强大的查看源码的软件,把你在AOSP中下载的源码导入到这个软件中就可以快速的查看源码了
      Source Insight
      破解方法:http://www.cnblogs.com/Napoleon-Wang/p/6706773.html
      具体操作方式:
      http://blog.csdn.net/shulianghan/article/details/50553001
    3. 直接将编译后源码导入Android Studio查看
      具体操作步骤:
      http://www.jianshu.com/p/fb16fa459acf
      关于源码的学习:
      http://www.jianshu.com/p/a4b40a9d1b4f

    参考:
    http://kaedea.com/2016/02/09/android-about-source-code-how-to-read/




    AndroidInterviewQuestions
    关注微信公众号,及时获取内容更新

    展开全文
  • 作为一个优秀的Android开发者,Kaede对于没有必要阅读Android源码这个问题给出自己一些见解,希望对在学习之路的你,有所帮助。 或许对于许多Android开发者来说,所谓的Android工程师的工...

    文章目录

    刚开始时候的故事

    为什么要阅读源码

    其一,了解基层,高层才能更好地工作。

    其二,能够理解Android设计者的意图。

    其三,能够学习优秀开源项目的代码风格和设计理念


    作为一个优秀的Android开发者,Kaede对于有没有必要阅读Android源码这个问题给出自己一些见解,希望对在学习之路的你,有所帮助。

    或许对于许多Android开发者来说,所谓的Android工程师的工作“不过就是用XML实现设计师的美术图,用JSON解析服务器的数据,再把数据显示到界面上”就好了,源码什么的,看也好不看也罢,反正应用层的开发用不上,再加上现在优秀的轮子越来越多,拿来主义泛滥,能用就是,反正老板也不关心是不是你自己写的,用我现在老大的话来说,阅读源码似乎只是一种“锦上添花”的事,有自然好,没有也罢。

    那么,作为Android开发者的自我修养,到底有没有必要阅读AOSP以及其他开源项目的源码呢?

    刚开始时候的故事

    对于我来说,选择编程是因为我看见了 MoeLoader 这款收图应用实在是漂亮才开始写代码,我要的目的只是应用漂亮,不用在乎代码写成什么样,而且我觉得代码是我写的,这么辛苦的作品可不能白白开源给别人看。所以对于这个时候的我,那时候虽然没有考虑过类似的问题,但是很可能觉得阅读源码是没有必要的。

    后来我开始学习Android,原因非常简单,C#根本无法找到合适的工作,而学生党我的我根本无法买得起苹果三套件,此外,IE6的兼容工作让我实在是对前端敬而远之,所以选择只剩下Android了。说实在的,一开始我是不太喜欢Android开发,特别是IDE从Visual Studio切换到万恶的Eclipse,丑,卡顿,动不动就找不到依赖,甚至有时候编译一直报红Error,定位了半天找不到问题,到最后把红色的Error删除掉后居然就编译通过了!这时候的我,别说阅读源码了,我只求同一份代码在运行的时候有同样的逻辑就好。

    再到后来,我已经有一些Android程序设计的经验了,IDE也开始换到Android Studio(Preview版本刚出来的时候,我在Android Studio和Eclipse之间切换过好几次,不得不说习惯这种东西有时很有帮助,有时候也会很可怕),换到Android Studio很大一个原因是因为Github上面许多开源项目用Android Studio来部署很方便。这个时候我接触的开源项目已经比较多了,许多时候一些开源项目总有一些BUG,我会给其提交ISSUE,不过更多时候我不能等项目所有者来解决,需要我自己解决BUG;许多时候开源项目并不能直接满足业务的需要,所以我也需要先阅读源码再改造成自己的项目能用的。

    这里需要特别说明的是,我的第一份工作的项目是一个SDK项目,整体使用了基于ClassLoader的动态加载的框架。那时候还比较早,国外对动态加载不感兴趣,国内的话也只有零星的技术博客对这有讨论,不过大多是介绍如何实现动态加载而没有分析其工作机制。所以,当有新的技术需求,或者项目出现BUG的时候,我都需要自己阅读源码去解决问题。比如,有一次设计师需要一个全圆角的菜单背景,然而Android的点九图是X轴和Y轴都需要拉伸的,当Y轴拉伸的时候就无法实现全圆角。我能做的就是,先把点九图的原图等比缩放到Y轴填满,这样Y轴就不会被拉伸了,但是原图缩放后,点九图X轴的拉伸却出现了扭曲的样式。通过阅读NinePatchDrawable的源码,我发现点九图的原理就是一个普通的Drawable加上一个用于描述拉伸坐标的数组chunk,当我缩放Drawable的时候,也必须更新chunk,不然拉伸的坐标就对不上,后面通过阅读源码中关于chunk的描述,把对应的拉伸坐标更新后,全圆角的点九图 也就实现了。

    为什么要阅读源码

    说了这么多,到底有没有必要阅读源码?有必要,而且非常有必要!原因有三。

    其一,了解基层,高层才能更好地工作。

    比如,了解View的绘制过程,了解TouchEvent的分发和拦截过程的细节,才能写出酷炫的UI,要不然,只知道大概的原理的话,你可能要在“无法接收到触摸事件”或者“滑动事件和点击事件冲突”的这些问题上折腾半天。

    又比如,如果哪里出现异常,你能快速定位到源码抛异常类的地方,就能快速解决BUG,对症下药,一招撂倒,有些时候,修复BUG的时间不是用在解决问题上,而是用在定位问题上。

    这里有必要提一下,当Logcat把异常的栈信息打印出来的时候,有些异常出现的原因并不真的是Logcat的信息里描述的原因,因为Logcat里的异常的信息也只是由系统源码打印出来的,而这些源码大多时候只是普通的Java代码,和你自己写的没什么区别,如果源码抛出异常的代码的逻辑不够严谨的话,那实际的异常和Logcat里描述的异常可能对不上。比如之前搞动态加载的时候,在使用LayoutInflator渲染一个外部的XML布局时,抛了一个“Class not found”的异常,我要渲染的类可是LinearLayout啊,怎么可能没有!定位到源码里才发现,这里只要是类渲染失败就会抛这个异常,再定位到具体抛异常的地方,发现实际是Dimens资源找不到,困扰半年的问题立刻解决。

    其二,能够理解Android设计者的意图。

    这个描述可能不好,比如说,许多人都觉得Android开发其实就是Java开发,通过阅读Context类的设计,你能够理解Google是如何在Java的基础上加上Android的特性的,你能够理解Context被叫做“环境”的原因。此外,阅读Activity/Service的源码,你能理解到四大组件类明明就是普通的JAVA类,为什么他们就是组件而别的类就不是组件。阅读Handler/Message/Looper的源码,你还能理解到Handler的精髓,数据驱动比事件驱动更适合用于设计需要经常改动的框架。阅读源码,你能知道Android是怎么管理Window以及向控制View的触摸事件的,你能知道基本上所有的res资源都有等价的Java代码的实现方式,你还能知道Dalvik是怎么无缝向ART过度的,在看通的那一瞬间,保证你觉得“水可载舟,亦可赛艇”!

    其三,能够学习优秀开源项目的代码风格和设计理念

    这也是最重要的,看多了源码之后,你会发现所谓的源码也不过是普通的的Java代码,在不知不觉中受到这些优秀设计思想的影响。相信许多人在看 Volley 源码此前,对异步任务控制的想法基本就是毫无想法,看完之后简直是醍醐灌顶,原来代码也能写得这么有魅力,再看看自己之前写的异步任务,“new Thread().start”…,简直是“too young, sometime naive”有没有。

    看了越来越多Android的源码,自己的写应用的时候,也就能写出更加“Best Performance”的代码,见识了越来越多的开源项目,自己也能够更容易找到最符合自己应用的框架和技术方案,学习了越来越多的优秀的代码风格,自己也就更能写出漂亮以及容易扩展的代码。

    或许对许多做Android开发来说,平时的工作就是按照设计的图写个布局,再解析后台的数据,下班了把测试用的安卓机扔进抽屉拿出自己的苹果手机…… 但有时候花点时间看看源码,或许会觉得设计代码还是挺有意思的,特别是,当你花了两天的时间构思代码,再花两天的时间写代码,这时你可能觉得你还有许多代码要写,但是突然发现只要把你写好的接口衔接一下就都完成了,而且写了两天的代码居然一次编译通过!更甚,产品突然改了个需求,你在抱怨了一顿后发现只要花10分钟把原来的接口换个实现就搞定了,这或许是程序员工作中为数不多的乐趣吧。

     

     

    展开全文
  • 断断续续的,《Android源码设计模式解析》也看了一遍,书中提到了很多的设计模式,但是部分在开发中见到的几率很小,所以掌握不了也没有太大影响。 我觉得这本书的最大价值两点,一个是从设计模式的角度去...

    断断续续的,《Android源码设计模式解析》也看了一遍,书中提到了很多的设计模式,但是有部分在开发中见到的几率很小,所以掌握不了也没有太大影响。

    我觉得这本书的最大价值有两点,一个是从设计模式的角度去理解Android源码,结合着日常开发中的常用类,对设计模式的理解会更加的深刻;另外一个好处就是了解常用模式,再看其他人写的代码的时候,更容易理解代码思路。下面是我的读书笔记和一些思考,设计模式只整理我认为重要的部分。

    建造者模式

    建造者模式最明显的标志就是Build类,而在Android中最常用的就是Dialog的构建,Notification的构建也是标准的建造者模式。

    建造者模式很好理解,如果一个类的构造需要很多参数,而且这些参数并不都是必须的,那么这种情况下就比较适合Builder。

    比如构建一个AlertDialog,标题、内容、取消按钮、确定按钮、中立按钮,你可能只需要单独设置几个属性即可;另外在我的OkHttpPlus项目中,构造一个Http请求也是这样的,有可能你只需要设置URL,有可能需要添加请求参数、Http Header等,这个时候建造者模式也是比较合适的。

    单例模式

    单例在Android开发中经常用到,但是表现形式可能不太一样。

    以ActivityManager等系统服务来说,是通过静态代码块的形式实现单例,在首次加载类文件时,生成单例对象,然后保存在Cache中,之后的使用都是直接从Cache中获取。

    class ContextImpl extends Context {
    
        static {
            registerService(ACTIVITY_SERVICE, new ServiceFetcher() {
                    public Object createService(ContextImpl ctx) {
                        return new ActivityManager(ctx.getOuterContext(),       ctx.mMainThread.getHandler());
                    }});
        }
    }

    当然,还有更加明显的例子,比如AccessibilityManager内部自己也保证了单例,使用getInstance获取单例对象。

     public static AccessibilityManager getInstance(Context context) {
            synchronized (sInstanceSync) {
                if (sInstance == null) {
    
                   ......
    
                    IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
                    IAccessibilityManager service = iBinder == null
                            ? null : IAccessibilityManager.Stub.asInterface(iBinder);
                    sInstance = new AccessibilityManager(context, service, userId);
                }
            }
            return sInstance;
        }

    除此之外,还有一些伪单例,比如Application,默认情况下在一个进程中只存在一个实例,但是Application不能算是单例,因为它的构造方法未私有,你可以生成多个Application实例,但是没有用,你没有通过attach()绑定相关信息,没有上下文环境。

    public Application() {
            super(null);
        }

    单例的使用场景也很简单,就是一个App只需要存在一个类实例的情况,或者是类的初始化操作比较耗费资源的情况。在很多开源框架中,我们只需要一个对象即可完成工作,比如各种网络框架和图片加载库。

    除此之外,因为单例的实现方式很多,比如懒汉式、饿汉式、静态内部类、双重锁检查、枚举等方式,所以要清楚每种实现方式的主要特点和使用场景。

    原型模式

    原型模式在开发中使用的并不多,但是在源码中却有所体现。

    书中以Intent介绍了原型模式,是通过实现Cloneable接口来做的

    public class Intent implements Parcelable, Cloneable {
        @Override
            public Object clone() {
             return new Intent(this);
            }
        }

    其实这样来看的话,原型模式也比较好理解,就是你想更快的获取到一个相同属性的对象,那么就可以使用原型模式,比如这里就获取到了一个Intent对象,Intent里面的属性与被clone的相同,但是两者并无关联,可以单独使用。

    除了实现Cloneable接口,你完全可以自己定义一个方法,来获取一个对象。我这里以PhoneLayoutInflater为例子介绍。

    PhoneLayoutInflater是LayoutInflater的子类,如果我们在Activity中获取LayoutInflate的话,是通过下面方法

     @Override public Object getSystemService(String name) {
            if (LAYOUT_INFLATER_SERVICE.equals(name)) {
                if (mInflater == null) {
                    mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
                }
                return mInflater;
            }
            return getBaseContext().getSystemService(name);
        }

    可以看到,如果为null,就会调用cloneInContext(),这个方法在LayoutInflate是抽象方法,具体实现在PhoneLayoutInflater中

      public LayoutInflater cloneInContext(Context newContext) {
            return new PhoneLayoutInflater(this, newContext);
        }

    可以看到,这也是一个原型模式,所以我们不要太纠结于形式,更重要的是理解这样做的好处。

    除了在源码中可以看到原型模式,在开源框架中也可以看到,比如OkHttpClient中就存在着下面的方法

    /** Returns a shallow copy of this OkHttpClient. */
      @Override public OkHttpClient clone() {
        return new OkHttpClient(this);
      }

    可以看到,实现和前面的完全相同,也是new了一个对象返回,因为OkHttpClient的构造过程比较复杂,参数众多,所以用这种方式来直接生成新对象,成本很低,而且能保留之前对象的参数设置。

    工厂方法模式

    书中对于工厂方法模式的一个观点很新奇,就是Activity.onCreate()可以看做是工厂方法模式,来生成不同的View对象填充界面。

    但是我对这个说法不太苟同,原因有两点:一是这种形式不太符合工厂方法,没有抽象,没有实现,不符合一般格式,也不是静态方法,不可看做是静态工厂方法;二是没有以生成对象为结果,即不是return view来生成对象,只是通过setContentView()来设置了属性而已。这就像是给一个Activity设置了背景颜色一样。当然,设计模式这东西一个人有一个人的看法。

    静态工厂方法在Android中比较明显的例子应该就是BitmapFactory了,通过各种decodeXXX()就可以从不同渠道获得Bitmap对象,这里不再赘述。

    策略模式

    在书中策略模式讲得非常好,结合动画的插值器用法,我们可以很好的理解策略模式的形式和用法。

    在我看来,策略模式就相当于一个影碟机,你往里面插什么碟子,就能放出什么电影。

    同样,在OkHttpPlus的封装中,为了对网络返回值进行解析,我使用了策略模式。当然我写代码的时候还不知道策略模式,是写完了之后突然想到,这就是策略模式啊!

    策略模式的精髓就在于,你传入一个类,后面的处理就能按照这个类的实现去做。以动画为例,设置不同的插值器对象,就可以得到不同的变化曲线;以返回值解析为例,传入什么样的解析器,就可以把二进制数据转换成什么格式的数据,比如String、Json、XML。

    责任链模式

    书中对于责任链模式选取的例子非常有代表性,那就是Android的触摸机制,这个看法让我从另一个维度去理解Android中的触摸事件传递。

    我在这里提到这个模式,并不想说太多,只是简单的推荐你读一下这一章的内容,相信你也会有收获的。

    观察者模式

    Android中的观察者模式应该是用的非常频繁的一种模式了,对于这个模式的使用场景就一句话:你想在某个对象发生变化时,立刻收到通知。

    书中介绍观察者模式使用的是ListView的Adapter为例子,我之前知道Adapter属于适配器模式,不知道这里还有观察者模式的身影,学到了。

    Android里面的各种监听器,也都属于观察者模式,比如触摸、点击、按键等,ContentProvider和广播接收者也有观察者模式的身影,可以说是无处不在。

    除此之外,现在很多基于观察者模式的第三方框架也是非常多,比如EventBus、RxJava等等,都是对观察者模式的深入使用,感兴趣的同学可以研究一下。

    模板方法模式

    这个模式我之前见的比较少,但是理解之后,就会发现这个模式很简单。

    我觉得,模板方法模式的使用场景也是一句话:流程确定,具体实现细节由子类完成。

    这里要关注一下『流程』这个关键字,随便拿一个抽象类,都符合”具体实现细节由子类完成”的要求,关键就在于是否有流程,有了流程,就叫模板方法模式,没有流程,就是抽象类的实现。

    书中讲这个模式用的是AsyncTask,各个方法之间的执行符合流程,具体实现由我们完成,非常经典。

    另外一个方面,Activity的生命周期方法可以看做是模板方法模式,各个生命周期方法都是有顺序的,具体实现我们可以重写,是不是和前面的要求很符合?关于这方面的理解,可以参考我的这篇文章:对Activity生命周期的理解

    除了Android里面的模板方法模式,在其他开源项目中也存在着这个模式的运用。比如鸿洋的OkHttp-Utils项目,就是模板方法模式的典型实现。将一个Http请求的过程分割成几部分,比如获取URL,获取请求头,拼接请求信息等步骤,这几个步骤之前有先后顺序,就可以这样来做。

    代理模式和装饰器模式

    之所以把这两个放在一起说,是因为这两种模式很像,所以这里简单介绍下他们之间的区别,主要有两点。

    1. 装饰器模式关注于在一个对象上动态的添加方法,而代理模式关注于控制对对象的访问
    2. 代理模式,代理类可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。而当我们使用装饰器模式的时候,通常的做法是将原始对象作为一个参数传给装饰者的构造器

    这两句话可能不太好理解,没关系,下面看个例子。

    代理模式会持有被代理对象的实例,而这个实例一般是作为成员变量直接存在于代理类中的,即不需要额外的赋值。

    比如说WindowManagerImpl就是一个代理类,虽然名字上看着不像,但是它代理的是WindowManagerGlobal对象。从下面的代码中就可以看出来。

    public final class WindowManagerImpl implements WindowManager {
        private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
        private final Display mDisplay;
        private final Window mParentWindow;
    
        ......
    
        @Override
        public void addView(View view, ViewGroup.LayoutParams params) {
            mGlobal.addView(view, params, mDisplay, mParentWindow);
        }
    
        @Override
        public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
            mGlobal.updateViewLayout(view, params);
        }
    
        @Override
        public void removeView(View view) {
            mGlobal.removeView(view, false);
        }
    
        @Override
        public void removeViewImmediate(View view) {
            mGlobal.removeView(view, true);
        }
    
        @Override
        public Display getDefaultDisplay() {
            return mDisplay;
        }
    }

    从上面的代码中可以看出,大部分WindowManagerImpl的方法都是通过WindowManagerGlobal实现的,而WindowManagerGlobal对象不需要额外的赋值,就存在于WindowManagerImpl中。另外,WindowManagerGlobal中其实有大量的方法,但是通过WindowManagerImpl代理之后,都没有暴露出来,对开发者是透明的。

    我们再来看一下装饰器模式。装饰器模式的目的不在于控制访问,而是扩展功能,相比于继承基类来扩展功能,使用装饰器模式更加的灵活。

    书中是以Context和它的包装类ContextWrapper讲解的,也非常的典型,我这里就不在赘述了,贴出一些代码来说明装饰器模式的形式。

    public class ContextWrapper extends Context {
        Context mBase;
    
        public ContextWrapper(Context base) {
            mBase = base;
        }
    }

    但是还有一个问题,就是在ContextWrapper中,所有方法的实现都是通过mBase来实现的,形式上是对上号了,说好的扩展功能呢?

    功能扩展其实是在ContextWrapper的子类ContextThemeWrapper里面。

    在ContextWrapper里面,获取系统服务是直接通过mBase完成的

    @Override
        public Object getSystemService(String name) {
            return mBase.getSystemService(name);
        }

    但是在ContextThemeWrapper里面,对这个方法进行了重写,完成了功能扩展

    @Override public Object getSystemService(String name) {
            if (LAYOUT_INFLATER_SERVICE.equals(name)) {
                if (mInflater == null) {
                    mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
                }
                return mInflater;
            }
            return getBaseContext().getSystemService(name);
        }

    当然,如果不存在功能扩展就不算是装饰器模式了吗?其实设计模式本来就是『仁者见仁,智者见智』的事情,只要你能理解这个意思就好。

    外观模式

    外观模式可能看到的比较少,但是其实不经意间你就用到了。

    这里以我的一个开源项目KLog来说吧,在最开始写这个类的时候,就只有KLog这一个类,完成基本的Log打印功能,后来又添加了JSON解析、XML解析、Log信息存储等功能,这个时候一个类就不太合适了,于是我把JSON、XML、FILE操作相关的代码抽取到单独的类中,比如JSON打印的代码

    public class JsonLog {
    
        public static void printJson(String tag, String msg, String headString) {
    
            String message;
    
            try {
                if (msg.startsWith("{")) {
                    JSONObject jsonObject = new JSONObject(msg);
                    message = jsonObject.toString(KLog.JSON_INDENT);
                } else if (msg.startsWith("[")) {
                    JSONArray jsonArray = new JSONArray(msg);
                    message = jsonArray.toString(KLog.JSON_INDENT);
                } else {
                    message = msg;
                }
            } catch (JSONException e) {
                message = msg;
            }
    
            Util.printLine(tag, true);
            message = headString + KLog.LINE_SEPARATOR + message;
            String[] lines = message.split(KLog.LINE_SEPARATOR);
            for (String line : lines) {
                Log.d(tag, "║ " + line);
            }
            Util.printLine(tag, false);
        }
    }

    代码很简单,就一个方法,但是在使用的时候,无论打印哪种格式,都是这样使用的

    //普通打印
     KLog.d(LOG_MSG);
     //JSON格式打印
     KLog.json(JSON);
     //XML格式打印
     KLog.xml(XML);

    可以看到,虽然功能不同,但是都通过KLog这个类进行了封装,用户只知道用KLog这个类能完成所有需求即可,完全不需要知道代码实现是几个类完成的。

    实际上,在KLog内部,是多个类共同完成打印功能的。

     private static void printLog(int type, String tagStr, Object... objects) {
    
            if (!IS_SHOW_LOG) {
                return;
            }
    
            String[] contents = wrapperContent(tagStr, objects);
            String tag = contents[0];
            String msg = contents[1];
            String headString = contents[2];
    
            switch (type) {
                case V:
                case D:
                case I:
                case W:
                case E:
                case A:
                    BaseLog.printDefault(type, tag, headString + msg);
                    break;
                case JSON:
                    JsonLog.printJson(tag, msg, headString);
                    break;
                case XML:
                    XmlLog.printXml(tag, msg, headString);
                    break;
            }
        }

    但是通过外观模式,这些细节对用户隐藏了,这样如果以后我想更换JSON的解析方式,用户的代码不需要任何改动,这也是这个设计模式的优势所在。

    总结

    唠唠叨叨的,总算是把这几种设计模式介绍完了,看完这篇文章,你应该就会发现其实Android中的设计模式确实到处都存在,不是缺少设计模式,而是缺少一双发现的眼睛。

    当然,设计模式的提出是为了解决特定的问题,当我们遇到类似问题的时候,可以从设计模式的角度思考和解决问题,这应该是我最大的收获吧。

    关于我

    江湖人称『凯子哥』,Android开发者,喜欢技术分享,热爱开源。

    展开全文
  • 1. 安装 Source Insight(1) Source Insight 相关资源安装相关资源 :-- 下载地址 : http://www.sourceinsight.com/down35.html;... 导入 Android 源码导入 Android 源码 :-- 创建工程 : Project -> New Project, 输入

     

     

     

    1. 安装 Source Insight

     

     

     

     

    (1) Source Insight 相关资源

     

     

    安装相关资源

    -- 下载地址 : http://www.sourceinsight.com/down35.html;

    -- 注册码 : 自行购买或百度.

     

     

     

    2. 导入 Android 源码

     

     

     

     

    导入 Android 源码

    -- 创建工程 : Project -> New Project, 输入一个工程名, 文件路径设置为 Android 源码路径, 这个一定要注意, 否则会拷贝整个 Android 源码, 几十个 G ...

    -- 设置工程 : 默认即可;

    -- 导入源码 : 选择全部导入, 前提是电脑配置好, 如果电脑配置一般, 可以一个一个导入.

    -- 选择导入子目录 : 不仅导入目录, 子目录迭代导入. 

    -- 扫描源码文件

    -- 扫描完成 : 只有 22万个文件.

    -- 开始导入

     

     

     

     

    3. 查找阅读源码

     

     

     

     

    查找阅读源码

    -- 查找 IBinder 源码

    -- 查找 init.rc 源码

     

     

     

     

    Source Insight 参考快捷键 : http://www.cnblogs.com/mengdd/p/3506526.html.

     

    展开全文
  • 很多时候为了解决一个问题必须先理解Android系统的运行原理,这...那么,如何阅读并分析Android源码呢? 这里我只讲一些初级的、基础的方法,很快就可以上手,不需要下载和编译系统源码。 我们下载Android SDK的时...

    很多时候为了解决一个问题必须先理解Android系统的运行原理,这时候就得阅读应用层框架的源码。学会阅读系统源码或者他人的代码,这是研发必备的技能之一,只有了解别人写的东西才能在他之上更好的行事,同时也能去学习和借鉴他人优秀的代码思想。

    那么,如何阅读并分析Android源码呢?

    这里我只讲一些初级的、基础的方法,很快就可以上手,不需要下载和编译系统源码。

    我们下载Android SDK的时候一般都会下载相应版本的源码(sdk/sources目录下),在AS(Android Studio)上追踪系统代码时会自动打开源码文件,如果没有源码则会在右上角提示下载:

    系统的源码一般多且复杂,虽然有不少注释,但如果纯靠阅读去理解会相当吃力,很难把握整体流程。我们需要结合实际使用场景,通过debug去分析代码的运行逻辑。那么SDK的版本有那么多,应该查看哪个版本的源码呢?这个根据需要,如果要查看最新7.0的源码就查看相应的。如果没有指定的版本,一般你打开的SDK自带的虚拟机的版本是多少就查看相应版本的代码。我们可以通过在项目build.gradle文件里面配置compileSdkVersion为指定的版本,这样在AS上追踪代码时跳转的即是对应版本的源码文件。(这里我强调的是自带的虚拟机,而不是真机或其他第三方的虚拟机。因为自带的虚拟机的rom可以保证代码是没有修改过的,跟官方源码的行数可以对得上。)

    例如,一般情况下,我使用版本22的虚拟机:

    接着把项目的compileSdkVersion配置为22:

    android {
        compileSdkVersion 22
        buildToolsVersion "22.0.0"
        ...
    }

    然后在AS上追踪系统代码,或者通过双击shift键,输入需要查找的系统类:

    我们可以看到这时候的源码版本都是android-22。

    接下来我们就要根据使用场景,寻找一个入口的地方,打一个断点,同时在其他觉得可疑的关键地方也打入断点,进入debug模式,这样逻辑就会在断点的地方停止,这时候就可以查看代码的运行逻辑,借助AS强大的debug功能分析代码。debug一定要有耐心,而且要多尝试设置可疑断点,让代码在关键地方停止。多运用几次就可以快速阅读和分析系统源码,明白其中的代码逻辑。

    这里给个建议,一开始只需要把握某一个功能的整体代码逻辑,设置几个关键断点,通过断点阅读代码,不要深入细节无法自拔。等理解了整体逻辑之后,再考虑从细节地方入手,一句句代码debug下去。

    最后,我们通过一个实际场景运用上面的方法去分析"View的OnClickListener.onClick()方法是怎样被触发的"。

    首先新建一个项目,build.gradle里的配置如下:

    android {
        compileSdkVersion 22
        ...
    }

    创建一个页面,里面存在一个按钮,设置了OnClickListener,启动自带的api版本为22的虚拟机,运行项目,效果如下:

    那么接下来debug从哪里入手呢?我们并不知道OnClickListener在哪里被回调,因此并不能预先在系统代码里打断点。这里我们可以观察调用view.setOnClickListener()的代码,然后查看OnClickListener对象保存在哪,什么时候调用,然后在关键地方打入断点。但其实还有更简单的方法,我们采用逆向思维,直接在OnClikcListener.onClick()方法里面打入断点:

    进入debug模式:

    点击按钮,然后代码会执行到断点的地方,这个时候我们查看左下角调用栈:

    可以看到onClick方法是被View.performClick()方法调用,继续下查看调用栈发现performClick方法又是在PerformClick对象中执行:

    PerformClick对象实现了Runnable,run()方法是在主线程消息队列执行的,所以接下来我们需要在View的源码里追踪代码,借助AS强大的功能查看PerformClick对象哪里被创建和被调用:

    从上面可以看出关键地方,PerformClick在View.onTouchEvent()方法被调用。想必接下来要分析"View的OnClickListener.onClick()方法是怎样被触发的"这个问题就知道如何下手了,比如我们可以在View.onTouchEvent()打入断点,一步步代码查看具体的代码逻辑:

    整个的过程大概就这样,当然不同问题要灵活处理,重要的是多实践多操作,就会得出一套自己解决问题的方法。

    不要怕啰嗦,最后再重复一下分析源码的步骤:

    • 1. 下载 Android 源码。如果没有下载,当点击查看源码的时候 AndroidStudio 的右上角会有提示,点击下载即可。
    • 2. 创建虚拟机,且虚拟机的 Android 版本和项目的 compileSdkVersion 保持一致。
    • 3. 在相应的代码出标记断点。
    • 4. 运行代码,进入debug模式。

    展开全文
  • 或许对于许多Android开发者来说,所谓的Android工程师的工作“不过就是XML实现设计师的美术图,JSON解析服务器的数据,再把数据显示到界面上”就好了,源码什么的,看也好不看也罢,反正应用层的开发不上,再...
  • 在上一篇文章Android AOSP基础(三)Android系统源码的整编和单编中,我们对系统源码进行了编译,这篇文章我们接着来学习如何将系统源码导入到编辑器中,以便于查看和调试源码。关于查看源码,可以使用Android ...
  •  Android源码文件很多,想要记住所有源代码的路径,是基本不可能的,所以一般都会借用IDE来操作,使用过source insight,intellij idea来分析Android源码,感觉还是intelij好用,最近手头只...
  • 显然Eclipse不是阅读Android源码的好工具,不流畅,搜索低效,继承性关系/调用关系都无法有效查看。推荐Source Insight,在这个工具帮助下,你才可以驾驭巨大数量的Android 源码,你可以从容在Java,C++,C代码间遨游...
  • 下载安装破解版 ... ... 安装sourceinsight_4.0.86.0-setup.exe sourceinsight4.exe替换掉安装路径里的同名文件 ...运行出现一下弹框,选择第三个,导入下载包里的si4.pediy.lic文件...查看android源码 打开sourcein...
  • 作者:王宇龙 ... 来源:知乎 著作权归作者所有,转载请...如果想深入的了解Android系统, 那么可以看下我的一些简单的总结. 知识 Java Java是AOSP的主要语言之一. 没得说, 必需熟练掌握. 熟练的Android A
  • 做系统开发的,比如手机,平板,需要编译修改源码。 做源码开发,不像开发纯app,调试起来有些麻烦,但还是可以实现的,可以将整个源码导入AS,实现打断点调试 我这边使用的是Android Studio 2.3 要调试的源码是...
  • 在之前的工作中,由于不仅要分析和调试Android系统源码中Framework以及Telephony部分的Java代码,而且还要兼顾RIL和Modem相关的C/C++代码。然而Android Studio对于C/C++代码的支持并不是很好,...
  • 通过Git去官网下载Android源码。步骤1:git clone http://android.googlesource.com/platform/frameworks/base.git步骤2:git base ls -l步骤3:git tag //查看发行版本http://img.blog.csdn.net/2013122419400
  • 之前我也写过了一篇文章从源码层面分析了Android的异步消息处理机制,感兴趣的朋友可以参考 Android Handler、Message完全解析,带你从源码的角度彻底理解 。 不过为了更加方便我们在子线程中更新UI元素,Android从...
  • 第一章、面向对象的六大原则《Android源码设计模式解析与实战》这本书在出版前就关注。出版前阅读了样章感觉真是太棒了。出版后也是迅速入手,但种种原因吧,现在才开始阅读,有点惭愧。那么既然买了、看了,那我...
  • 本篇博客只是记录了阅读源码的几种方法,如果想知道怎么阅读源码的话推荐: 大牛们是怎么阅读 Android系统源码的? 我们必须先知道几个网站: AOSP项目官方(Android Open Source Project) 这个一定要先. 项目...
  • 读Android蓝牙通信源码

    2015-11-21 23:32:06
    我说的读android蓝牙通信源码并不是说,读google官方api,那个我也看了一下,里面全是英文倒不说,英文好的,直接无视掉。关键是代码写的我实在难以理解。当然,这也和我的阅读源码的能力关联的。不过,幸好我在...
  • #简介 ...本篇我们来研读一下Toast的源码,并探明它的显示及隐藏机制。 #源码解析 ##Toast 我们从Toast的最简单调用开始,它的调用代码是: ```java Toast.makeText(context,"Show toast",Toast.LE
  • Android Camera源码分析

    2018-11-23 20:55:40
    回顾这半年做的项目基本都...这两天好好了一下Camera的源码,大概理清了整体架构,总结了一下,其实没多少东西,Android的各个模块都差不多,都是个系统服务,然后Java封一层,Native封一层,Java层和Native层的...
1 2 3 4 5 ... 20
收藏数 38,867
精华内容 15,546
关键字:

读android源码有什么用