android知识点五

Android应用里有几种Context对象,

Context类图如下所示:

可以发现Context是个抽象类,它的具体实现类是ContextImpl,ContextWrapper是个包装类,内部的成员变量mBase指向的也是个ContextImpl对象,ContextImpl完成了
实际的功能,Activity、Service与Application都直接或者间接的继承ContextWrapper。

2、Android哪些情况会导致内存泄漏,如何分析内存泄漏?

常见的产生内存泄漏的情况如下所示:

  • 持有静态的Context(Activity)引用。
  • 持有静态的View引用,
  • 内部类&匿名内部类实例无法释放(有延迟时间等等),而内部类又持有外部类的强引用,导致外部类无法释放,这种匿名内部类常见于监听器、Handler、Thread、TimerTask
  • 资源使用完成后没有关闭,例如:BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap。
  • 不正确的单例模式,比如单例持有Activity。
  • 集合类内存泄漏,如果一个集合类是静态的(缓存HashMap),只有添加方法,没有对应的删除方法,会导致引用无法被释放,引发内存泄漏。
  • 错误的覆写了finalize()方法,finalize()方法执行执行不确定,可能会导致引用无法被释放。

查找内存泄漏可以使用Android Profiler工具或者利用LeakCanary工具。

3、SharePreference性能优化

在Android中, SharePreferences是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件
存放在/data/data/ < package name > /shared_prefs目录下.

之所以说SharedPreference是一种轻量级的存储方式,是因为它在创建的时候会把整个文件全部加载进内存,如果SharedPreference文件比较大,会带来以下问题:

  1. 第一次从sp中获取值的时候,有可能阻塞主线程,使界面卡顿、掉帧。
  2. 解析sp的时候会产生大量的临时对象,导致频繁GC,引起界面卡顿。
  3. 这些key和value会永远存在于内存之中,占用大量内存。

优化建议

  1. 不要存放大的key和value,会引起界面卡、频繁GC、占用内存等等。
  2. 毫不相关的配置项就不要放一起,文件越大读取越慢。
  3. 读取频繁的key和不易变动的key尽量不要放在一起,影响速度,如果整个文件很小,那么忽略吧,为了这点性能添加维护成本得不偿失。
  4. 不要乱edit和apply,尽量批量修改一次提交,多次apply会阻塞主线程。
  5. 尽量不要存放JSON和HTML,这种场景请直接使用JSON。
  6. SharedPreference无法进行跨进程通信,MODE_MULTI_PROCESS只是保证了在API 11以前的系统上,如果sp已经被读取进内存,再次获取这个SharedPreference的时候,如果有这个flag,会重新读一遍文件,仅此而已。

4、理解序列化吗,Android为什么引入Parcelable?

所谓序列化就是将对象变成二进制流,便于存储和传输。

  • Serializable是java实现的一套序列化方式,可能会触发频繁的IO操作,效率比较低,适合将对象存储到磁盘上的情况。
  • Parcelable是Android提供一套序列化机制,它将序列化后的字节流写入到一个共性内存中,其他对象可以从这块共享内存中读出字节流,并反序列化成对象。因此效率比较高,适合在对象间或者进程间传递信息。
package com.tutor.objecttran;  
import java.io.Serializable;  
public class Person implements Serializable {  
    private static final long serialVersionUID = -7060210544600464481L;   
    private String name;  
    private int age;  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
      
} 


package com.tutor.objecttran;  
import android.os.Parcel;  
import android.os.Parcelable;  
public class Book implements Parcelable {  
    private String bookName;  
    private String author;  
    private int publishTime;  
      
    public String getBookName() {  
        return bookName;  
    }  
    public void setBookName(String bookName) {  
        this.bookName = bookName;  
    }  
    public String getAuthor() {  
        return author;  
    }  
    public void setAuthor(String author) {  
        this.author = author;  
    }  
    public int getPublishTime() {  
        return publishTime;  
    }  
    public void setPublishTime(int publishTime) {  
        this.publishTime = publishTime;  
    }  
      
    public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>() {  
        public Book createFromParcel(Parcel source) {  
            Book mBook = new Book();  
            mBook.bookName = source.readString();  
            mBook.author = source.readString();  
            mBook.publishTime = source.readInt();  
            return mBook;  
        }  
        public Book[] newArray(int size) {  
            return new Book[size];  
        }  
    };  
      
    public int describeContents() {  
        return 0;  
    }  
    public void writeToParcel(Parcel parcel, int flags) {  
        parcel.writeString(bookName);  
        parcel.writeString(author);  
        parcel.writeInt(publishTime);  
    }  
} 
    //Serializeable传递对象的方法  
    public void SerializeMethod(){  
        Person mPerson = new Person();  
        mPerson.setName("frankie");  
        mPerson.setAge(25);  
        Intent mIntent = new Intent(this,ObjectTranDemo1.class);  
        Bundle mBundle = new Bundle();  
        mBundle.putSerializable(SER_KEY,mPerson);  
        mIntent.putExtras(mBundle);  
          
        startActivity(mIntent);  
    }  
     Person mPerson = (Person)getIntent().getSerializableExtra(ObjectTranDemo.SER_KEY); 


    //Pacelable传递对象方法  
    public void PacelableMethod(){  
        Book mBook = new Book();  
        mBook.setBookName("Android Tutor");  
        mBook.setAuthor("Frankie");  
        mBook.setPublishTime(2010);  
        Intent mIntent = new Intent(this,ObjectTranDemo2.class);  
        Bundle mBundle = new Bundle();  
        mBundle.putParcelable(PAR_KEY, mBook);  
        mIntent.putExtras(mBundle);  
          
        startActivity(mIntent);  
    }  
     Book mBook = (Book)getIntent().getParcelableExtra(ObjectTranDemo.PAR_KEY);  

5、PathClassLoader与DexClassLoader有什么区别?

  • PathClassLoader:只能加载已经安装到Android系统的APK文件,即/data/app目录,Android默认的类加载器。
  • DexClassLoader:可以加载任意目录下的dex、jar、apk、zip文件。

6、如果防止过度绘制,如何做布局优化?

  1. 使用include复用布局文件。引入布局
  2. 使用merge标签避免嵌套布局。用include标签的时候根布局用merge减少层级
  3. 使用stub标签仅在需要的时候在展示出来。用到时在加载布局

Guess you like

Origin blog.csdn.net/qwildwolf/article/details/118153057