代码优化

来源:互联网 发布:多层嵌套 知乎 编辑:程序博客网 时间:2024/06/14 15:28

【 不用静态变量存储数据 】

1、静态变量等数据由于进程已经被杀死而被初始化。

2、使用其他暑假传输方式:文件 / sp / contentProvider。


【 有关sp的安全问题 】

不能跨进程同步;存储SP的文件过大问题;

尽量不要去做跨进程的东西,这非常会影响数据的安全问题。

【 Context的种类及注意事项 】

Application:Android应用中默认单例类,在Activity或Service中通过getApplication()可以获取到这个单例,通过context.getApplicationContext()可以获取到应用全局唯一的Context实例。

Activity/Service:都是ContextWrapper的子类,在这两个类中可以通过getBaseContext()获取到它们的Context实例,不同的Activity或Service实例,它们的Context都是独立的,不会复用。

BroadcastReceiver:本身不是Context的子类,而是在回掉函数onReceive()中由Android框架传入一个Context的实例。系统传入的这个Context实例是经过功能裁剪的,它不能调用registerReceiver()以及bindService()这两个函数。

ContentProvider:也不是Context的子类,但在创建时系统会传入一个Context实例,这样在CP中可以通过调用getContext()函数获取,如果CP和调用者处于相同的应用进程中,那么getContext()将返回应用全局唯一的Context实例。如果是其他进程调用的CP,那么CP将持有自身所在的进程的Context实例。


getApplicationContext():Application的Context, 生命周期贯穿整个App。                

 getContext() / this:组件的Context,与组件生命周期同步。                             

getBaseContext():(Google Android 工程师Dianne Hackborn 不建议使用,具体原因没详述)。



【 使用建议 】

 数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task。一般情况不推荐。

 数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。  

数字3:在receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视)。


【 注意Context引用的持有,防止内存泄漏 】

建议一:不要长时间持有 组件的Context,(持有的情况可能有 workThread, static 变量,non-static inner Class)。

建议二:对于不受控的非静态内部类,建议修改成静态内部类,同时采用弱引用的方式 引用 Activity/Service 的Context。

建议三:其他可以使用Application Context 的地方,就用Application Context。


【 java四种引用方式 】


【内存对象序列化】


【 SparseArray 】



【Handler和内部类的正确用法】

导致大量的内存泄漏:

public class SampleActivity extends Activity {  private final Handler mLeakyHandler = new Handler() {    @Override    public void handleMessage(Message msg) {      // ...    }  }  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    // Post a message and delay its execution for 10 minutes.    mLeakyHandler.postDelayed(new Runnable() {      @Override      public void run() { /* ... */ }    }, 1000 * 60 * 10);    finish();     // Go back to the previous Activity.  }}

在Java中,非静态的内部类或者匿名类会隐式的持有其外部类的引用,而静态的内部类则不会。

当activity被finish的时候,延迟发送的消息仍然会存活在UI线程的消息队列中,直到10分钟后它被处理掉。这个消息持有activity的Handler的引用,Handler又隐式的持有它的外部类(这里就是SampleActivity)的引用。这个引用会一直存在直到这个消息被处理,所以垃圾回收机制就没法回收这个activity,内存泄露就发生了。需要注意的是:15行的匿名Runnable子类也会导致内存泄露。非静态的匿名类会隐式的持有外部类的引用,所以context会被泄露掉。


问题解决:

在新的类文件中实现Handler的子类或者使用static修饰内部类。

静态的内部类不会持有外部类的引用,所以activity不会被泄露。

如果你要在Handler内调用外部activity类的方法的话,

可以让Handler持有外部activity类的弱引用,

这样也不会有泄露activity的风险。

关于匿名类造成的泄露问题,我们可以用static修饰这个匿名类对象解决这个问题,

因为静态的匿名类也不会持有它外部类的引用。

 

【 对常亮使用static final修饰 】
对基本数据类型和String类型常量的调用不会涉及类的初始化,而是直接调用字面量。

【 避免内部的Getters/Setters】
如果是在类内部还使用Getters/Setters函数访问变量的话,会降低访问的速度。














原创粉丝点击