Git Product home page Git Product logo

diary's People

Contributors

qqiabc521 avatar

Stargazers

 avatar

Watchers

 avatar

Forkers

bww126

diary's Issues

Android GC机制实践调研

  1. 不同系统不同型号的手机的GC机制是不同的
  2. System.gc()调用结果不同(立即GC或无反应)
  3. 废弃内存回收频率不同
  4. 大规模GC临界值不同
  5. 对于加载图片来说,内存增加量是远大于图片大小的。
  6. 临时变量的GC时机是完全不能保证的,我们可以理解为,GC线程还没有转到这个地方。
  7. System.gc()并不是立刻执行GC的。
  8. 每点击一次按钮,内存消耗增加0.02MB,世界上没有免费的午餐,点击事件内部是会有新的对象产生的
  9. 有时,内存占用只有达到一定限度时,GC才会开始被触发。
  10. 一个空白Activity的内存占用量是0.4MB,返回后再次进入每次增加0.15MB左右,返回键每次增加0~0.01MB左右
  11. 无论Activity是否占用大量内存,其销毁的时间都是迟钝的。
  12. 类成员置NULL,对防止内存溢出崩溃是有必要的
  13. 无论对象大小,都应避免在循环内创建对象
  14. 注意软引用与弱引用的正确使用(弱引用比软引用更容易被销毁,内存抖动更大)

最后告诫一点:尽量不要在应用中调用System.gc(); 如果调用了System.gc()可能会为系统性能带来严重的波动,即便调用System.gc()系统也未必立即响应去执行垃圾回收。

java 序列化的遗漏点---static、transient

什么是序列化和反序列化

Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程。

什么情况下需要序列化
当你想把的内存中的对象保存到一个文件中或者数据库中时候(数据持久化);
利用序列化实现远程通信,即在网络上传送对象的字节序列;
如何实现序列化

将需要序列化的类实现Serializable接口就可以了,Serializable接口中没有任何方法,可以理解为一个标记,即表明这个类可以序列化.

静态变量能否序列化?
序列化会忽略静态变量,即序列化不保存静态变量的状态。静态成员属于类级别的,所以不能序列化。即 序列化的是对象的状态不是类的状态。这里的不能序列化的意思,是序列化信息中不包含这个静态成员域。transient后的变量也不能序列化。

transient使用小结

_1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。_

注:一个静态变量不管是否被transient修饰,均不能被序列化,反序列化后类中static型变量值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的

特殊情况:
对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。

日常开发中,如何给团队留下财富?

技术团队中,财富即代码,但并不是所有的代码都是财富,有些代码可能是毒药。前段时间看到一篇文章,“你写的代码,是别人的噩梦吗?”,虽然标题针对我们技术人员来说,可能有点刺耳,但有时候确实是不争的事实。

在码奴圈,有一句话很流行:“能运行工作的代码就是好代码”。这句话没有对与错,在小的创业团队或人员能力不足的情况,能运行工作的代码确实是好代码,因为它解决了我们当时的问题。在对于有追求的技术人员来说,特别是在一个多人开发的团队中,产品功能在不停的迭代、优化,好代码就会我们的开发效率与维护效率带来成倍的提升。

何谓“好代码”,每个人的答案其实是不一样的。但说到“坏代码”,大家应该都能说出一箩筐来。

我先说一下我认为的“坏代码”:可读性差、业务逻辑相互缠绕、代码复用性低,这样带来的后果将是隐藏bug、团队其他人员调用或维护难以入手,更严重的可能就是重构。有时候可能陷入不停的重构循环当中去。原因有二:1.自己写的代码,没有重构到关键点上;2.下一个重构者与上一个开发者不分伯仲。

那好代码就是坏代码的反面:可读性强、业务逻辑低耦合高内聚、代码复用性高、有良好的可拓展性。

说了这么多,解决问题才是王道,如何才能按照上面说的好代码的目标开发,下面分享给大家一个容易入手的方法。

一、面向用例编程(横向):

1.先把系统按照功能进行划分,细化成多个功能模块。做到每个模块的功能是相对独立的,但也有可能一个模块与另一个模块有交互。

2.将功能需求进行抽象,达到高内聚、低耦合的标准,明确该功能模块的参与者是什么。

3.对每一个功能模块进行业务分析,看看是否能再按照子功能进行细分,细分后形成具体的用例。

4.对具体用例进行分析,理清用例与参与者的关系、参与者与参与者的关系、以及用例与用例的关系。

将功能需求划分成一个个独立的用例后,我们就能很清晰的表达功能需求的分离与组合。即先造一个个通用的轮子,然后对这些轮子按照业务需求进行组装。这样就能达到有良好的组件颗粒度,很好的满足了代码结构清晰、复用性强、组件可任意插拔、各个功能可以独立测试(单元测试)的目标。

面向用例编程的核心是把业务分解成一个个小的独立的case(解耦),在根据业务需求将相关case聚集、组装在一起(内聚)。最终又回归到我们经常说的低耦合、高内聚的目标之上。大到模块划分、小到函数定义,都是同样的方法。业务case集成一个模块,功能函数聚集成一个类。

面向用例编程也是封装的一种体现。将内部逻辑封装在一个盒子(case)里,对外只需要暴露接口。调用者也只需要关注接口,不关心底层逻辑。

所以在我们开发之前,进行业务建模,还是很重要的。

二、分层架构(纵向)

上面说的面向用例编程是从横向对业务功能进行解耦,那分层架构就是从纵向上对功能职责的划分。不论是后端开发、前端开发还是客户端开发,分层架构很普遍。通常我们会在纵向上对项目进行三层划分:展示层、业务逻辑层、数据访问层。MVC、MVP、MVVM都是为了更好的分层。

在团队成员中,经常会有人质疑分层,认为有时候明明是一个很简单的逻辑,非要搞几层数据转换,把结构搞的比较复杂。这个观点也没有错,在生活中能用简单的方法完成一件事情却故意把事情搞的很复杂,确实是多此一举。但我们通常是做一个复杂、庞大且不停迭代更新的项目,功能业务可能会像网状一样交织在一起。如果没有清晰的结构、各个组件各司其职,如何能保证多人开发的团队敏捷高效的共同开发,发现问题及时定位问题所在。

三、建立约束(规则)

约束即规范,团队成员按照一套统一的规范开发,尽可能的降低沟通成本(了解现有代码逻辑成本、业务调用成本、维护成本等)。约束包括一下几个方面:

1.命名规范:按照规范进行合理的命名,BEAN、ENTITY、DTO、API等都分别代表不同的标签或职责。看到名称就知道它能做什么事情。

2.分模块、分包:每一个组件或包都有自己明确定义的职责,不可以乱放。presenter包只放Presenter,config包只放配置文件等。

3.统一的结构:项目主体要统一结构,坚决不能出现相似业务不同代码结构,这样只会让参与项目的其他成员不知所错。

4.代码检查:如果有可能或有条件的话,通过工具或插件进行项目代码的检查,可以是静态的编译检查,也可以是动态的运行时检查。

总之,建立约束,就是让项目的参与者开发出来的代码尽可能的保持风格一致。

上面说了这么多,我们在开发过程中,只要代码具有低耦合、高内聚、可拓展、有良好的可读性,就是给团队创造财富。

RxJava2使用过程中遇到的坑

1. 初始化RxJava回收执行周期

背景:RxJava开启一个循环线程在后台默默回收Publisher,默认是1秒循环一次,但是这样比较耗费cpu,纯净后台检测时,cpu唤醒率无法达到标准。
解决方案:设置垃圾检测回收周期为5分钟。

初始化RxJava回收执行的周期
@see io.reactivex.internal.schedulers.SchedulerPoolFactory
PURGE_ENABLED_KEY与PURGE_PERIOD_SECONDS_KEY非public属性参数,外界不能直接访问,需要通过转换,在项目代码中新建io.reactivex.internal.schedulers包

package io.reactivex.internal.schedulers;
public class SchedulerPoolConfig {
public static final String PURGE_ENABLED_KEY = SchedulerPoolFactory.PURGE_ENABLED_KEY;
public static final String PURGE_PERIOD_SECONDS_KEY = SchedulerPoolFactory.PURGE_PERIOD_SECONDS_KEY;
}

private static void initRxPurgeProperties() {
System.setProperty(SchedulerPoolConfig.PURGE_ENABLED_KEY, "true");
System.setProperty(SchedulerPoolConfig.PURGE_PERIOD_SECONDS_KEY, "30");
}

2. RxJava2 取消订阅后,抛出的异常无法捕获,导致程序崩溃

最近在项目中,就遇到了host解析失败导致程序崩溃的情况:
io.reactivex.exceptions.UndeliverableException: java.net.UnknownHostException: Unable to resolve host "api-test.zhangyuke.com": No address associated with hostname

当时遇到这个问题,百思不得其解。因为Rxjava有一个很大的优势,就是可以帮助使用者捕获异常,而且在对应了异常捕获中,已经有针对性的对UnknownHostException异常做了处理,并给用户以提示。后来在跟踪这个错误日志发现, java.net.UnknownHostException仅仅是被包裹的异常,最外面的一层异常是io.reactivex.exceptions.UndeliverableException,UndeliverableException从字面意思看,意思是不可送达的异常。通过源码跟踪,发现抛出io.reactivex.exceptions.UndeliverableException唯一地方是RxJavaPlugins类:

public static void onError(@nonnull Throwable error) {
Consumer<? super Throwable> f = errorHandler;

if (error == null) {
error = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
} else {
if (!isBug(error)) {
error = new UndeliverableException(error);
}
}
if (f != null) {
try {
f.accept(error);
return;
} catch (Throwable e) {
// Exceptions.throwIfFatal(e); TODO decide
e.printStackTrace(); // NOPMD
uncaught(e);
}
}
error.printStackTrace(); // NOPMD
uncaught(error);
}

背景:RxJava2的一个重要的设计理念是:不吃掉任何一个异常。产生的问题是,当RxJava2“downStream”取消订阅后,“upStream”仍有可能抛出异常,这时由于已经取消订阅,“downStream”无法处理异常,此时的异常无人处理,便会导致程序崩溃。

示例代码:
mDisposable = Flowable("token")
.map(new Function<String, Object>() {
@OverRide
public List apply(String token) throws Exception {
//...
//code A
throw new InterceptorIOException("io error");//throw exception when mDisposable.isCanceled()
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@OverRide
public void accept(Objeect data) throws Exception {
// do something when success
}
}, new Consumer() {
@OverRide
public void accept(Throwable throwable) throws Exception {
//do something when error!
//code B
//注意:当mDisposable.isCanceled()时抛出的异常,这里不会补货,因为已经取消了订阅
}
});

上述代码code A出抛出的异常code B处无法捕获,便会导致程序崩溃。

解决方案:在Application设置RxJavaPlugin的ErrorHandler
/**
*RxJava2 当取消订阅后(dispose()),RxJava抛出的异常后续无法接收(此时后台线程仍在跑,可能会抛出IO等异常),全部由RxJavaPlugin接收,需要提前设置ErrorHandler
*详情:http://engineering.rallyhealth.com/mobile/rxjava/reactive/2017/03/15/migrating-to-rxjava-2.html#Error Handling
*/

private void setRxJavaErrorHandler() {
RxJavaPlugins.setErrorHandler(new Consumer() {
@OverRide
public void accept(Throwable throwable) throws Exception {
throwable.printStackTrace();;
AppLog.d("ljj", "throw : "+throwable.getMessage());
}
});
}

人生的错位

很多年前都到过这样一段智慧祈祷语言,对我的人生产生了很大的影响:祈求上天赐给我力量去改变我能改变的事;赐给我耐心接受我不能改变的事;赐给我智慧来辩别它们。

我们许多人的人生是在一种错位状态:对自己不能改变的事运用过多的能量;对自己能改变的事,又看不到,或者不愿意去做。其原因是没有智慧来分辨它们。所以常常穷尽了一生的能量,去试图改变那种自己根本就改变不了的事,那种根本不在自己能力范围的事。

平静地接受自己不能改变的事,我们自己的心也会变得像明镜一样平静。改变自己能改变的事,在自己力所能及的地方,尽自己的力量让事情朝好的方向发展。这也使自己变得坚韧,培养独立的人格,增强自己的智慧。

其实,在这个世界上,很多事,一旦你接受了它们,它们就不存在了。有人站在事物的反面去争论,使得事物变得更明显。

许多年前,我也是喜欢看一些时髦文章,然后和人讨论,争论。后来发现,当时用尽自己的能量去 “据理力争”的事,过一段时间,那件事被人们忘得一干二净。人们又找到新的话题。即使那事物存在,自己的观点又奈它何得?我忽然想,这样浪费自己的能量,值得吗?

后来在佛经里读到的一句话,让我受用无穷:随缘不变,不变随缘。

人,最能改变的是自己。改变自己使自己变得更宽厚,更仁慈,更纯净,更有智慧。但是,这不是一件容易的事。我们都要终身挣扎去取得这些。

Class.isAssignableFrom与 instanceof 区别

isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。
通常调用格式是
Class1.isAssignableFrom (Class2)
调用者和参数都是 java.lang.Class 类型。

而 instanceof 是用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例。
格式是: oo instanceof TypeName
第一个参数是对象实例名,第二个参数是具体的类名或接口名
具体例子如下:
public class TestCase {
public static void main(String[] args) {
TestCase test = new TestCase();
test.testIsAssignedFrom1();
test.testIsAssignedFrom2();
test.testIsAssignedFrom3();
test.testInstanceOf1();
test.testInstanceOf2();
}

public void testIsAssignedFrom1() {  
    System.out.println(String.class.isAssignableFrom(Object.class));  
}  

public void testIsAssignedFrom2() {  
    System.out.println(Object.class.isAssignableFrom(Object.class));  
}  

public void testIsAssignedFrom3() {  
    System.out.println(Object.class.isAssignableFrom(String.class));  
}  

public void testInstanceOf1() {  
    String ss = "";  
    System.out.println(ss instanceof Object);  
}  

public void testInstanceOf2() {  
    Object o = new Object();  
    System.out.println(o instanceof Object);  
}  

}

打印结果:
false
true
true
true
true

一次重大错误选择的反思

人生有两种东西是无价的,“家人”与“经历”。
家人是我们的心灵的寄托,或喜或悲,家人的陪伴是温暖的,所有人都有可能随意的丢下你,唯有家人会永远在你身边。
经历是人生的根本,在不断的经历中摸索,抉择的对与错、得与失,只有经历才能体会更深。

在任何抉择面前,理清“核心---主要基准点是什么”,一切都围绕着这个核心去思考,分析利弊。尽量避免被一些旁枝末节、无关紧要的元素所左右。否则在重大抉择面前,往往会偏失而悔恨。

对于可能影响你五到十年甚至更久的人生抉择面前,切不可过多考虑小利(不能改变你目前人生现状的事物),往往会因小失大。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.