最近的一些基础笔记

● Jenkins构建后shell脚本,删除旧的输出文件,把新的apk、mapping拷贝到自定义的输出目录;debug模式下不拷贝mapping

# delete old apk (before 1 min) in sub folders
test $? -eq 0 && find ${WORKSPACE}/app/build/outputs/apk -mindepth 1 -maxdepth 3 -type f -mmin +2 -exec rm -f {} \;

# move mapping.txt to archive dir
archive_dir=${WORKSPACE}/app/build/outputs/archive
test -d ${archive_dir} && rm -rf "${archive_dir}"

mkdir -p ${archive_dir}
build_dir=$(echo ${ENVIRONMENT} | tr '[:upper:]' '[:lower:]')  # to lower case
cp ${WORKSPACE}/app/build/outputs/apk/${build_dir}/*.apk ${archive_dir}

debugMode="debug"
if [ ${build_dir} != ${debugMode} ]
then
   cp ${WORKSPACE}/app/build/outputs/mapping/${build_dir}/mapping.txt ${archive_dir}
fi

● Aidl中oneway这个关键字,可以用关键字oneway来标明远程调用的行为属性,使用了该关键字,那么远程调用将仅仅是调用所需的数据传输过来并立即返回,

而不会等待结果的返回,也即是说不会阻塞远程线程的运行。AIDL接口将最终将获得一个从Binder线程池中产生的调用(和普通的远程调用类似)。
如果关键字oneway在本地调用中被使用,将不会对函数调用有任何影响。

● Linux用户空间/内核空间简述

1)Linux Kernel是操作系统的核心,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。
2)对于Kernel这么一个高安全级别的东西,显然是不容许其它的应用程序随便调用或访问的,所以需要对Kernel提供一定的保护机制,这个保护机制用来告诉那些应用程序,你只可以访问某些许可的资源,不许可的资源是拒绝被访问的,于是就把Kernel和上层的应用程序抽像的隔离开,分别称之为Kernel Space和User Space

● 后台任务的新实现WorkManager

 implementation "android.arch.work:work-runtime:1.0.0-alpha01" 

https://blog.csdn.net/xiangzhihong8/article/details/80389742

● 查看项目中库的依赖结构(有的第三方库跟项目依赖相同的第三方库,且第三方库锁依赖的版本有bug时,需要分析依赖结构)

gradle dependencies

●关于SharedPreference进程间共享的问题


根据官方文档可知,SharedPreferences的MODE_MULTI_PROCESS模式对部分版本的系统不可靠。

●清除dns缓存命令:ipconfig /flushdns

●Jenkins,构建时删除旧的apk文件shell脚本:
# delete old apk (before 1 min) in sub folders
test $? -eq 0 && find ${WORKSPACE}/app/build/outputs/apk -mindepth 1 -maxdepth 3 -type f -mmin +1 -exec rm -f {} \;

●ScrollView不能撑满全屏的问题

android:fillViewport="true"
●java.lang.ref.FinalizerReference引发的内存泄漏
这和GC的机制有关:
实现了object的finalize()的类在创建时会新建一个FinalizerReference,这个对象是强引用类型,封装了override  finalize()的对象,下面直接叫原对象。原对象没有被其他对象引用时(FinalizeReference除外),执行GC不会马上被清除掉,而是放入一个静态链表中(ReferenceQueue),有一个守护线程专门去维护这个链表,如何维护呢?就是轮到该线程执行时就弹出里面的对象,执行它们的finalize(),对应的FinalizerReference对象在下次执行GC时就会被清理掉。
一个堆的FinalizerReference会组成一条双向链表,垃圾回收器应该会持有链表头(链表头在FinalizerReference中为一个静态成员)。
为什么会泄漏:
直接原因就是守护线程优先级比较低,运行的时间比较少。如果较短时间内创建较多的原对象,就会因为守护线程来不及弹出原对象而使FinalizerReference和原对象都得不到回收。无论怎样调用GC都没有用的,因为只要原对象没有被守护线程弹出执行其finalize()方法,FinalizerReference对象就不会被GC回收。
知道这些机制后,应该注意以下几点:
1.  紧缺资源不要依赖finalize()来释放。
2.  尽量不要重载finalize()。
3.  如果必须重载finalize(),一定要记得调用super.finalize,也建议把类实现成单例模式(减少FinalizerReference占用)。
http://blog.csdn.net/gwgking2012/article/details/41278949
http://www.oschina.net/question/12_19310
http://it.deepinmind.com/gc/2014/05/13/debugging-to-understand-finalizer.html

javassist的特点、常用api,写的很明了

● gradle与maven版本对应关系(版本不匹配时,可能会出现一些api找不到的错误)


美团GC优化

1fragmentManager.popBackStack();最终执行的是FragmentTranaction.commit();如果执行时应用在后台,触发了onSaveInstanceState(),然后触发popBackStack(),则闪退。

 因为不是commitIgnoreState...

2使用sp作为字体大小单位,会随着系统的字体大小改变dp作为单位则不会.

3android.os.BadParcelableException: ClassNotFoundException when unmarshalling:

putExtra时存入了null导致的。

Android有两种不同的classloadersframework classloaderapk classloader,其中framework classloader知道怎么加载android classesapk classloader知道怎么加载你的代码,即可以知道你自定义的类,apk classloader继承自framework classloader,所以也知道怎么加载android classes。在应用刚启动时,默认class loaderapk classloader,但在系统内存不足应用被系统回收会再次启动,这个默认class loader会变为framework classloader了,所以对于自己的类会报ClassNotFoundException

如果是在要传递的JavaBean中有其中一个Field继承自Parcelable,那么有很简单的处理方法,只要把类似rect = in.readParcelable(null);改为config = in.readParcelable(Rect.class.getClassLoader());

但是我们这里是直接传递一个List,那要怎么办呢?

其实很简单,只需要在Client端读取Bundle中的数据之前加上如下一行代码:

bundle.setClassLoader(getClass().getClassLoader());这样就会使用apk classloader加载。

4Context有个createPackageContext方法,可以创建另外一个包的上下文,这个实例不同于它本身的Context实例,但是功能是一样的。

这个方法有两个参数:
1)packageName  包名,要得到Context的包名
2)flags  标志位,有CONTEXT_INCLUDE_CODECONTEXT_IGNORE_SECURITY两个选项。CONTEXT_INCLUDE_CODE的意思是包括代码,也就是说可以执行这个包里面的代码。CONTEXT_IGNORE_SECURITY的意思是忽略安全警告,如果不加这个标志的话,有些功能是用不了的,会出现安全警告。

限制:1)共享应用之间都需要配置相同的android:sharedUserId

<manifestandroid:sharedUserId="io.silvrr.installment"...

2)两个应用要有相同的签名

5merge、和rebase的区别 

  merge是用来合并2个不同分支的,合并后会生成一个新的commit

  Rebase是把当前修改内容复制一份到另一分支上,使两个分支一致,不会生成新的commit

6、关于onActivityResultonResume调用顺序问题

  系统会先调用onActivityResult再调用onResume,具体调用代码可以看ActivityThread4096

deliverResults(r, res.results);
if (resumed) {
    r.activity.performResume();
    r.activity.mTemporaryPause =false;
}

7、Activity OnCreate中 EventBus#register(Object)报错java.lang.NoClassDefFoundError: android/os/PersistableBundle

 //Starting with EventBus 2.2 we enforced methods to be public (might change with annotations again)

Method[] methods = clazz.getDeclaredMethods();

Method[] methods = clazz.getMethods();

bug修复方式,onCreate重写

protected voidonCreate(Bundle savedInstanceState) {}

不要重写

public voidonCreate(Bundle savedInstanceState, PersistableBundle persistentState) {}

原因:onCreate中EventBus注册时,会用反射去读取一些方法,但是PersistableBundleAPI21才提供的,在低于4.4的系统找不到这个类,导致闪退

8、假设Handler绑定子线程,只有在sendMessage之后,handleMessage里才是在该handler绑定线程

9startActivityForResult启动singleTask模式的activity,无回调的问题。

<p>Note that this method should only be used with Intent protocols
* that are defined to return a result.  In other protocols (such as
* {
@linkIntent#ACTION_MAIN} or {@linkIntent#ACTION_VIEW}), you may
* not get the result when you expect.  For example, if the activity you
* are launching uses the singleTask launch mode,it will not run in your
* task and thus you will immediately receive a cancel result.

根据这一段源码的注释,可以知道启动的singleTask模式的Activity与其他模式activity运行不在一个task中,数据不交互,所以启动时会直接触发RESULT_CANCEL

从柯元旦的《Android 内核剖析》的第十章“Ams内部原理“10.1.3中有这样的一段话:请注意:SINGLE_TASK标识以及SINGLE_INSTANCE两个标识必须在r.result==0的条件中,即这两个标识只能用在startActivity()的方法中,而不能使用在startActivityForResult方法中。因为从Task的角度看,Android认为不同Task之间的Activity是不能传递数据的,所以不能使用NEW_TASK标识,但还是要调用forResult方法。

官方文档:singleInstancesingleTask"”相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。 该 Activity 始终是其任务唯一仅有的成员。

10、@JavascriptInterface 4.4以下版本,这种h5与原生交互存在bug4.4以上通过注解获取方法,h5只能拿到带有注解的方法进行操作。而4.4以下,是通过方法名获取,h5能拿到该类中所有方法,不够安全。

11、android studio中导入svg矢量图插件   http://www.cnblogs.com/tokyow/p/6293743.html

12、关于ScrollView嵌套RecyclerView,item不显示的问题:ScrollView中加上 android:fillViewport="true" 属性。

13、向现有项目中添加C/C++代码:https://developer.android.google.cn/studio/projects/add-native-code.html?hl=zh-cn#link-gradle

14、关于Parcelable,实现parcelable的对象,取出的值会存在部分字段数据丢失的问题,原因是write、read字段的顺序要一致。

15、关于序列化

16、关于多进程读写同一个文件的问题,同时读没问题,同时写入一个文件可能会死锁

//==========================2017/12/26=============================

17、从ActivityFragment中传数据,不能用setBean,还是得用fragment.setArgument(Bundle),否则在一些机型上会存在兼容性问题

18Git常用命令

新分支的情况:git fetch origin --prune   

删除远程分支:git push origin --delete <branchName>

删除taggit push origin --delete tag <tagname>

推送一个空分支到远程分支,其实就相当于删除远程分支:git push origin :<branchName>

推送一个空tag到远程taggit tag -d <tagname>

git push origin :refs/tags/<tagname>

取消合并:git reset release/2.2.2

     git revert -m release/2.2.2

取消cimmit: git reset --hard commit_id 

19、Google Play Console 发布版本

1)上传apk

Release management --> App releases --> MANAGE PRODUCTION --> EDIT RELEASE

-->BROWSE FILES -->view...  ...

2)上传mapping.txt   Android vitals -> Deobfuscation files ->Review ->选择推送比例->roll out

 

20关于mipmap和drawable既不是把所有图标都放置在mipmap下,也不是说mipmap只能够放Launcher图标。如果图标有固定的尺寸,不需要更改,那么drawable更加适合。如果需要变大变小变大变小的,有动画的,放在mipmap中能有更高的质量。固定尺寸drawable合适、动画图片mipmap去锯齿流畅

21不同的语言对数量的语法规定有不同的规则。
例如一棵树是one tree, 两颗树是two trees。
为了解决后缀的问题,Android引入了plurals 这种资源,其xml定义类似于:

<!--定义到资源文件即可 --><plurals name="subtitle_plural">

    <!--在使用时,可以根据数量来选择不同的字符串-->

    <!--还有zero、few等其它选项-->

    <item quantity="one">%s crime</item>

    <item quantity="other">%s crimes</item></plurals>

int crimeCount = crimeLab.getCrimes().size();

String subtitle = getResources().getQuantityString(R.plurals.subtitle_plural, crimeCount, crimeCount);//第一参数为resId,第二个参数为数量,第三个为替换占位符的字符

不过plurals的使用,受到系统当前语言(本地化)的限制。

22、Linux常用命令

rm -rf /var/log/httpd/access
将会删除/var/log/httpd/access目录以及其下所有文件、文件夹

rm -f /var/log/httpd/access.log
将会强制删除/var/log/httpd/access.log这个文件

使用这个rm -rf的时候一定要格外小心,linux没有回收站的

 

23、一个TimerbugTimer使用System.currentTimeMillis()计算时间。当修改系统时间后计时就会出现问题。很可能会无限循环导致死机。另外Timer多任务时,某个任务崩溃其他也停止。所以使用Timer定时的请修改,不推荐使用。

可以使用ScheduledExecutorService这个内部用的是System.nanoTime,系统时间修改不会影响定时。



● 查看项目中库的依赖结构(有的第三方库跟项目依赖相同的第三方库,且第三方库锁依赖的版本有bug时,需要分析依赖结构)

gradle dependencies

猜你喜欢

转载自blog.csdn.net/u010577768/article/details/77600212
今日推荐