Android-知识点总结

Java知识点

抽象类与接口的区别:

  1. 抽象类可以有方法的具体实现,接口不可以。
  2. 由于Java单继承的特性,子类只能继承一个抽象类,但可以实现多了接口。
  3. 接口是为类的具体实现提供一个通用的规范,抽象类是为子类提供一个公共的类型,是为了类的继承而存在的。

说明:接口可以被接口继承,接口所有的方法自动被声明为public,接口可以定义成员变量,自动被声明为public static final类型。

集合继承结构

集合继承结构图

1.SparseArray、ArrayList对比
SparseArray是稀疏数组,主要是包括两个数组分别用来存放key、value,其中get和put元素时用到了二分查找。
ArrayList比较简单,就用一个对象数组来存储元素。
2. ArrayMap、HashMap的对比
HashMap
Java库里的HashMap其实是一个连续的链表数组,通过key计算hash值后插入对应的index里。当hash值发生碰撞时,可以采用线性探测,二次hash,或者后面直接变成链表的结构来避免碰撞。
说明:hash值不是连续的,所以hashmap实际需要占用的大小会比它实际能装的item的容量要大。
HashMap结构图

ArrayMap
先看看ArrayMap的结构图:
ArrayMap结构图

ArrayMap用两个数组来模拟Map,第一个数组存放存放item的hash值,第二数组是把key,value连续的存放在数组里。通过先算hash,在第一个数组里找到它的hash index,然后根据这个index在去第二个数组里找到这个key-value。
这里,在第一个数组里查找hash index的方法是用二分查找(binary search),过程如下图所示。
ArrayMap元素查找过程

说明:
查找元素达不到HashMap的O(1)时间复杂度。
3. HashMap、HashTable的区别
1). HashTable是继承Dictionary类,实现Map接口,HashMap是继承AbstractMap类并实现了Map接口,AbstractMap类也实现了Map接口。
2). HashTable的方法是同步的,HashMap是非同步。
3). HashTable、HashMap使用的哈希值的不同,HashTable直接使用对象的hashCode,而HashMap则重新计算了Hash值。

String、StringBuffer、StringBuilder的区别

  1. String是字符串常量,StringBuffer、StringBuilder是字符串变量。
  2. StringBuffer是线程安全的,StringBuilder是非线程安全的。
  3. 对于内容经常改变的字符串最好使用StringBuffer或者StringBuilder,因为StringBuffer或者StringBuilder是对字符串对象本身做修改,String是每次都会生成一个新的对象。

==、equals、hashCode的区别

  1. == : 它的作用是判断两个变量(基本变量)的值是否相等,或者判断两个对象的地址是不是相等,即判断两个对象是不是同一个对象。
  2. equals:不重写equals的时候,比较的是引用(Reference),也就是内存地址。
public boolean equals(Object o) {
        return this == o;
    }
  1. equals相等,则hasCode一定相等,而hashCode相等,equals不一定相等。因此,一般重写equals,就必须重写hashCode。

Android知识点

本地广播、全局广播的区别

本地广播仅在应用内发送,全局广播是在系统内发送。
本地广播不用担心隐私数据泄露的问题,全局广播需要防止别的应用伪造广播,从而造成不必要的安全隐患。

Service的启动方式

Service的启动方式有两种:startService,bindService,这两种启动的方式的区别如下:

1)startService来启动某个service,其生命周期与启动方(如Activity)无关,当Activity销毁后,service还在后台运行,除非执行stopService方法。
2)bindService来启动某个service,其生命周期与启动方(如Activity)有关,当Activity销毁后,service也跟着销毁,当然也可以调用unbind方法解除绑定。
3)生命周期的回调方法不同,如下:
startService: onCreate -> onStartCommand -> onDestroy
bindService:onCreate -> onBind -> onUnbind -> onDestroy

说明:Service仍然是在主线程中调用,还是要开线程才能处理长时间的工作。

引申:IntentService是处理异步任务,实现多线程。

Android动画类型

Android动画包括帧动画(Frame Animation)、补间动画(Tween Animation)、属性动画。

帧动画:连续地播放图片序列,有点类似于gif图,在Android中用AnimationDrawable来加载XML资源文件并进行播放。

补间动画:主要分为scale(缩放)、rotate(旋转)、translate(位移)、alpha(透明度渐变),一般是在XML文件中写好,然后通过AnimationUtils进行加载。

属性动画:主要是ObjectAnimator 这个类,其继承自ValueAnimator,使用这个类可以对任意对象的任意属性进行动画操作,可以很好地实现补间动画。

内存泄漏

1. 内存泄漏

我们知道Java虚拟机会帮我们进行垃圾回收操作,即GC操作,如果一些无用的对象没有被回收,就会发生了内存泄漏,在讲内存泄漏之前,我们先来看看Java四种引用类型。

强引用: 如果对象具有强引用,即便内存不足抛出OOM,也不会回收该对象,强引用一般是这样的:Object object = new Object()。

软引用: 如果对象具有软引用,当内存不足时,虚拟机会回收该对象。

弱引用:软引用发生在垃圾回收时,不管内存是否不足,都会对弱引用的对象进行回收。

虚引用:如果一个对象具有虚引用,其实跟没有任何引用一样,任何时候都会被垃圾回收器回收。

2. 内存泄漏分析

1)长生命周期对象持有短生命周期对象的引用

public class SingleInstance {
    private Context mContext;
    private static SingleInstance instance;

    public SingleInstance(Context context){
        mContext = context;
    }

    public static SingleInstance getInstance(Context context){
        if(instance == null){
            instance = new SingleInstance(context);
        }
        return instance;
    }
}

假设,我们这里传入的是Activity-A的Context,在Activity-A的生命周期内,上面的单例能够正常使用,如果Activity-A销毁了,我们在其它地方使用上面的单例时,就会出现内存泄漏。
我们知道单例的生命周期一般是跟整个应用的生命周期一样长,因此,我们应该传入Application的Context,为了让每次使用单例时不用额外传入一个变量,上面的代码可以修改如下:

public class SingleInstance {
    private final Context mContext = Application.appContext;
    private static SingleInstance instance;

    private  SingleInstance(){
    }

    public static SingleInstance getInstance(){
        if(instance == null){
            instance = new SingleInstance();
        }
        return instance;
    }
}

2) 匿名内部类的使用
在Activity或者Fragment中,我们一般会使用Handler更新UI操作,先来看看下面的代码有什么问题没。

public class MainActivity extends Activity {

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler.sendEmptyMessageDelayed(0, 6*1000);
    }
}

上面代码,在onCreate方法里面发送一个延迟Message,这时如果Activity销毁,则会发生内存泄漏。因为非静态的内部类持有外部类的引用,而mHandler的生命周期还没结束,其持有MainActivity的引用,但这时Activity已经销毁。
对于上面的代码,我们可以进行如下修改:

public class MainActivity extends Activity {
    private final Handler mHandler = new  MyHandler(this);
    public static class MyHandler extends Handler{
        private final WeakReference<MainActivity> mActivity;
        public MyHandler(MainActivity activity){
            mActivity = new WeakReference<MainActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            if(mActivity.get() != null){

            }
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler.sendEmptyMessageDelayed(0, 6*1000);
    }
}

引申:线程造成的内存溢出
异步任务AsyncTask和Runnable都是一个匿名内部类,它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成, 那么将导致Activity的内存资源无法回收,造成内存泄漏。

3) 非静态的内部类创建静态实例
下面的代码中,我们创建了一个静态的资源对象mResouce,每次Activity启动都会使用该资源的数据,避免了重复创建,但是这样会造成内存泄漏,原因如下:
~ 非静态内部类默认会持有外部类的引用。
~ 使用了该非静态内部类创建了一个静态的实例。
~ 静态实例的生命周期和应用的一样长,这就导致了该静态实例一直会持有该Activity的引用,导致Activity的内存资源不能正常回收。

private static XMLResource mResource = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(mResource == null){
            mResource = new XMLResource();
        }

    }
    class XMLResource {

    }

解决方案:将非静态内部类XMLResource修改为静态内部类。

4)使用了静态的Activity和View
解决方案:应该及时将静态的应用 置为null,而且一般不建议将View及Activity设置为静态。

5)其它
注册了系统的服务,但onDestory没有注销,不需要用的监听器未移除。

3. 应用的 Context数量

Context是一个抽象类,子类有ContextWrapper,ContextWrapper 的子类有ContextThemeWrapper,ContextWrapper有一个成员变量mBase,类型是Context,下面我们来看看有哪些组件间接继承ContextWrapper。

1) Activity

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback,
        AutofillManager.AutofillClient

2) Service

public abstract class Service extends ContextWrapper implements ComponentCallbacks2

3) Application

public class Application extends ContextWrapper implements ComponentCallbacks2 

综上可知:

APP Context总数 = Application数 + Activity数 + Service数

说明:多进程下Application可能被创建多次,因此多进程环境下,Application的Context数可能不止一个。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容