【个人复习向】Android学习过程 以及 问题集合

 

这篇博文记录的是本人的Android学习过程,从Android基础开始,到实际遇到的问题;

橘色表示某一范围内的知识点总结;绿色表示分散的小知识点。

 


 

一,Activity 生命周期

Activity是与用户交互的接口,一个activity对应一个窗口。Android系统中是通过Activity栈的方式来管理Activity的,而Activity自身则是通过生命周期的方法来管理的自己的创建与销毁。

1. Activity的四种状态

Active/Running:

Activity处于活动状态,此时Activity处于栈顶,是可见状态,可与用户进行交互。

Paused:

当Activity失去焦点时,或被一个新的非全屏的Activity,或被一个透明的Activity放置在栈顶时,Activity就转化为Paused状态。但我们需要明白,此时Activity只是失去了与用户交互的能力,其所有的状态信息及其成员变量都还存在,只有在系统内存紧张的情况下,才有可能被系统回收掉。

Stopped:

当一个Activity被另一个Activity完全覆盖时(失去焦点并且上层存在不透明的、非Dialog样式的Activity),被覆盖的Activity就会进入Stopped状态,此时它不再可见,但是跟Paused状态一样保持着其所有状态信息及其成员变量,该Activity的数据会在RAM中暂时保留,一旦系统需要内存,这种处于Stopped状态的Activity占用的RAM空间会优先被清理并重新利用。所以,在Activity处于Stopped状态时,必须要保存该Activity的UI状态,否则一旦RAM空间被重新利用,UI状态和数据就完全丢失。

Killed:

当Activity被系统回收掉时,Activity就处于Killed状态。不占用RAM空间。

2. Activity的生命周期

典型的生命周期:创建,运行,停止,销毁

onCreate

创建,它是生命周期第一个调用的方法,我们在创建Activity时一般都需要重写该方法,然后在该方法中做一些初始化的操作。不能在这个阶段写太多耗时的东西。

onStart

运行,此方法被回调时表示Activity正在启动,此时Activity已处于可见状态,只是还没有在前台显示,因此无法与用户进行交互。可以简单理解为Activity已显示而我们无法看见罢了。

onResume

运行,当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的Active/Running形态)。

onPause

此方法被回调时则表示Activity正在停止(Paused形态),一般情况下onStop方法会紧接着被回调。在onPause方法中我们可以做一些数据存储或者动画停止或者资源回收的操作,但是不能太耗时,因为这可能会影响到新的Activity的显示——onPause方法执行完成后,新Activity的onResume方法才会被执行。

onStop

一般在onPause方法执行完成直接执行,表示Activity即将停止或者完全被覆盖(Stopped形态),此时Activity不可见,仅在后台运行。同样地,在onStop方法可以做一些资源释放的操作(不能太耗时)。

onRestart

表示Activity正在重新启动,当Activity由不可见变为可见状态时,该方法被回调。这种情况一般是用户打开了一个新的Activity时,当前的Activity就会被暂停(onPause和onStop被执行了),接着又回到当前Activity页面时,onRestart方法就会被回调。

onDestroy

此时Activity正在被销毁,也是生命周期最后一个执行的方法,一般我们可以在此方法中做一些回收工作和最终的资源释放。

引用及扩展阅读:

https://blog.csdn.net/qq_35559358/article/details/79715222

https://blog.csdn.net/qingxuan521721/article/details/78737080

 

二,MVP架构 (Presenter)

只知道MVC,MVP是MVC的改良。主要不清楚presenter的作用。

View:主要负责界面的显示及跟数据无关的逻辑,比如设置控件的点击事件等

Presenter:主要负责View与Model的交互

Model:数据部分

任何需要更新或者操作数据的,都间接通过Presenter对象去操作数据

Presenter层持有View层对象的引用,除此之外不持有其他的UI控件等的引用,Model层会把想要更新View的操作委托Presenter去操作,而Presenter层会把更新View操作交给View层对象去操作。

 

三,了解 RxJava

a library for composing asynchronous and event-based programs using observable sequences for the Java VM

本质是实现异步操作的库,利用了观察者模式。

观察者模式面向的需求是:A 对象(观察者)对 B 对象(被观察者)的某种变化高度敏感,需要在 B 变化的一瞬间做出反应。程序的观察者模式,采用注册(Register)或者称为订阅(Subscribe)的方式,告诉被观察者:我需要你的某某状态,你要在它变化的时候通知我。类似OnClickListener

RxJava 的观察者模式有部分不同,有四个基本概念

Observable (可观察者,即被观察者);Observer (观察者);subscribe (订阅);事件

RxJava的事件回调方法有:

onNext() 普通事件

onCompleted() 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。

onError() 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。

线程切换:基本是依靠ObserveOn和SubscribeOn这两个操作符来完成

引用及扩展阅读:

http://gank.io/post/560e15be2dca930e00da1083#toc_1

 

四,了解Room数据库

google自己的数据库框架Room。

涉及到的概念:

Entity:具体的bean实体(一个对象类称之为一个javabean,不知道为甚),会与数据库表column进行映射

Dao:数据库访问对象,实现具体的增删改查。

RoomDatabase:提供直接访问底层数据库实现,我们应该从里面拿到具体的Dao,进行数据库操作。

引用及扩展阅读:

https://www.jianshu.com/p/72c8efc3ad87

DAO层操作这个超级全:https://blog.csdn.net/u011897062/article/details/82107709#%E4%BF%A1%E6%81%AF%E6%9F%A5%E8%AF%A2

 

五,四大组件

Activity:展现为一个可视化的用户界面。这些activity一起工作,共同组成了一个应用程序,但每个activity都是相对独立的。每个activity都 是Activity(android.app.Activity)的子类。展示activity窗体的可视化内容区域是一些具有层次关系(非常像数据结构中的树)的视图,而视图则是由类View的子类表示的。通过调用Activity.setContentView()方法来设置展现activity的窗体的视图。

Service:Android系统的服务(不是一个线程,是主程序的一部分),与Activity不同,它是不能与用户交互的,不能自己启动的,须要调用Context.startService()来启动,执行后台,假设我们退出应用时,Service进程并没有结束,它仍然在后台行。比如,service可能在用户处理其他事情的时候播放背景音乐,或者从网络上获取数据,或者执行一些运算,并把运算结构提供给activity展示给用户。每一个service都扩展自类Serivce。与activity以及其他组件一样,service相同执行在应用程序进程的主线程中。所以它们不能堵塞其他组件或用户界面,通常须要为这些service派生一个线程执行耗时的任务。

Broadcase receiver:用于异步接收广播Intent。

正常广播 Normal broadcasts(用 Context.sendBroadcast()发送) 是全然异步的。没有定义的顺序。

有序广播 Ordered broadcasts(用 Context.sendOrderedBroadcast()发送)每一个receiver执行后能够传播到下一个receiver,也能够全然中止传播--不传播给其它receiver。

专注于接收广播通知信息,并做出相应处理。广播接收器没实用户界面。然而,它们能够启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知能够用非常多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。

Content provider:用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其它应用訪问,其它应用能够通过ContentProvider对指定应用中的数据进行操作。ContentProvider分为系统的和自己定义的,系统的也就是比如联系人,图片等数据。

以上是四大组件,下面说一下也很重要的intent组件:

intent:一个保存着消息内容的Intent对象。对于activity和服务来说,它指明了请求的操作名称以及作为操作对象的数据的URI和其他一些信息。比方说,它能够承载对一个activity 的请求,让它为用户显示一张图片,或者让用户编辑一些文本。而对于广播接收器而言,Intent对象指明了声明的行为。比方,它能够对全部感兴趣的对象声 明照相button被按下。对于每种组件来说,激活的方法是不同的。此处不赘述,需要阅读,下面有链接~

Application:当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建。

引用与扩展阅读:https://www.cnblogs.com/hrhguanli/p/3961599.html

 

六,Android 布局

时间有限,我是边上手边学的,所以这部分只记录了我觉得难一点的地方。

 

Android 圆角、圆形 ImageView 实现

https://blog.csdn.net/jakezhang1990/article/details/79425879

用glide也是很好的选择

如果图片长宽不定,很有可能出现上下两条线或者左右两条线的情况,设置android:scaleType="centerCrop" 很有用,参考如下:

https://www.cnblogs.com/nimorl/p/8081542.html

 

ConstraintLayout

https://blog.csdn.net/etwge/article/details/80433580

 

 

 

 

 

 

 

七,View 绘图

1. onMeasure:

作用:

(1)一般情况重写onMeasure()方法作用是为了自定义View尺寸的规则,如果你的自定义View的尺寸是根据父控件行为一致,就不需要重写onMeasure()方法
(2)如果不重写onMeasure方法,那么自定义view的尺寸默认就和父控件一样大小,当然也可以在布局文件里面写死宽高,而重写该方法可以根据自己的需求设置自定义view大小

使用:

onMeasure有两个参数 ( int widthMeasureSpec, int heightMeasureSpec),该参数表示控件可获得的空间以及关于这个空间描述的元数据。widthMeasureSpec和heightMeasureSpec这两个值通常情况下都是由父视图经过计算后传递给子视图的,说明父视图会在一定程度上决定子视图的大小。

specMode一共有三种类型,如下所示:
1. EXACTLY
表示父视图希望子视图的大小应该是由specSize的值来决定的,系统默认会按照这个规则来设置子视图的大小,简单的说(当设置width或height为match_parent时,模式为EXACTLY,因为子view会占据剩余容器的空间,所以它大小是确定的)
2. AT_MOST
表示子视图最多只能是specSize中指定的大小。(当设置为wrap_content时,模式为AT_MOST, 表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸)
3. UNSPECIFIED
表示开发人员可以将视图按照自己的意愿设置成任意的大小,没有任何限制。这种情况比较少见,不太会用到。

PorterDuffColorFilter 

保持原来图片的形状,而切换图片的颜色

 

ViewOutlineProvider

实现图像矩形圆角效果

class RoundViewOutlineProvider extends ViewOutlineProvider {
        private float radius = 100f;
        private int diameter = 200;

        public RoundViewOutlineProvider(float radius) {
            this.radius = radius;
            this.diameter = (int) radius * 2;
        }

        @Override
        public void getOutline(View view, Outline outline) {
            int left = (view.getWidth() - diameter) / 2;
            int top = (view.getHeight() - diameter) / 2;
            int right = view.getWidth() - left;
            int bottom = view.getHeight() - top;
            outline.setRoundRect(left, top, right, bottom, radius);
        }
    }

 

 

 

 八,Android 动画

https://www.jianshu.com/p/609b6d88798d

Android 中的动画可以分为以下几类: 逐帧动画 补间动画 属性动画。

1. 逐帧动画的原理就是让一系列的静态图片依次播放,利用人眼“视觉暂留”的原理,实现动画。逐帧动画通常是采用 XML 资源进行定义的,需要在 <animation-list .../> 标签下使用 <item .../> 子元素标签定义动画的全部帧,并指定各帧的持续时间。

2. 补间动画就是指开发者指定动画的开始、动画的结束的"关键帧",而动画变化的"中间帧"由系统计算,并补齐。补间动画有四种:淡入淡出: alpha,位移:translate, 缩放:scale,旋转: rotate

3. 属性动画可以看作是增强版的补间动画,与补间动画的不同之处体现在:

属性动画可以看作是增强版的补间动画,与补间动画的不同之处体现在:补间动画只能定义两个关键帧在透明、旋转、位移和倾斜这四个属性的变换,但是属性动画可以定义任何属性的变化。补间动画只能对 UI 组件执行动画,但属性动画可以对任何对象执行动画。

与补间动画类似的是,属性动画也需要定义几个方面的属性:

  • 动画持续时间。默认为 300ms,可以通过 android:duration 属性指定。
  • 动画插值方式。通过 android:interploator 指定。
  • 动画重复次数。通过 android:repeatCount 指定。
  • 重复行为。通过 android:repeatMode 指定。
  • 动画集。在属性资源文件中通过 <set .../> 来组合。
  • 帧刷新率。指定多长时间播放一帧。默认为 10 ms。

 

主要学习属性动画:

参考引用:https://github.com/OCNYang/Android-Animation-Set/tree/master/property-animation

属性动画实现原理就是修改控件的属性值实现的动画。

类:我们平时使用属性动画的重点就在于 AnimatorSet、ObjectAnimator、TimeAnimator、ValueAnimator。

属性:Android 属性动画提供了以下属性:

  • Duration:动画的持续时间;
  • TimeInterpolation:定义动画变化速率的接口,所有插值器都必须实现此接口,如线性、非线性插值器;
  • TypeEvaluator:用于定义属性值计算方式的接口,有 int、float、color 类型,根据属性的起始、结束值和插值一起计算出当前时间的属性值;
  • Animation sets:动画集合,即可以同时对一个对象应用多个动画,这些动画可以同时播放也可以对不同动画设置不同的延迟;
  • Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为 10ms,最终刷新时间还受系统进程调度与硬件的影响;
  • Repeat Country and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以让此动画一直重复,或播放完时向反向播放;

 

贝塞尔曲线:

1、moveTo:不会进行绘制,只用于移动移动画笔。

2、quadTo :用于绘制圆滑曲线,即贝塞尔曲线。

 mPath.quadTo(x1, y1, x2, y2) (x1,y1) 为控制点,(x2,y2)为结束点。同样地,我们还是得需要moveTo来协助控制。

mPath.moveTo(100, 500);
mPath.quadTo(300, 100, 600, 500);
canvas.drawPath(mPath, mPaint);

效果如图:

3、cubicTo:同样是用来实现贝塞尔曲线的。

mPath.cubicTo(x1, y1, x2, y2, x3, y3) (x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点。多了一个控制点而已。

mPath.moveTo(100, 500);
mPath.cubicTo(100, 500, 300, 100, 600, 500);

结果和上图一样。

如果我们不加 moveTo 呢?则以(0,0)为起点,(100,500)和(300,100)为控制点绘制贝塞尔曲线:

Android Animation运行原理

https://www.jianshu.com/p/fcd9c7e9937e

想要做更酷炫的效果,一般就需要涉及Animation的原理,Android使用一个3*3的矩阵处理平移、缩放、旋转等动画效果,假如我们想要实现一个平移(a,b)之后旋转(c,d)的动画,那用Matrix的实现代码就是这样的:

 

 

    Matrix matrix = new Matrix();
    matrix.setTranslate(a, b);
    matrix.postScale(c, d);

Animation的applyTransformation()方法是空实现,具体实现它的是Animation的四个子类,而该方法正是真正的处理动画变化的过程。applyTransformation()方法就是动画具体的实现,系统会以一个比较高的频率来调用这个方法,一般情况下60FPS,是一个非常流畅的画面了,也就是16ms。我们可以覆写这个方法,快速的制作自己的动画。

https://www.cnblogs.com/kross/p/4087780.html

 

Android运行时的动画卡顿问题:

我的项目中,页面不仅在播放动画,还在播放gif(承载动画的view本身是一个gif),以及还在播放视频,效果是有很明显的卡顿和gif掉帧的。

问题出在内存泄漏,主线程任务过多,以及启用GC频繁。

我查了资料过后,使用了以下硬件加速,结果是没效果。

经过查看GC启用频率,确实启用的非常频繁,想要减少GC,就要尽可能少的创建临时变量,由于我使用的是属性动画,创建一个AnimatorSet和多个ObjectAnimation,确实很多,可以尝试这样改改,看有没有效果:

可以按照下面这个博文的思路改代码:

https://blog.csdn.net/rentee/article/details/52251829

====================改完代码的分割线==========================

优化过后,发现内存占用不仅没少反多了,emmmmm(没有多很多)

反思了一下,我个人浅薄认为,虽然减少了很多ObjectAnimation对象的创建,但是产生了许多PropertyValuesHolder 对象 以及 Keyframe 对象,而且我的动效比较复杂,经常穿插多个view的动画,最终它们需要在一个set里面,那么还是不可避免的需要创建ObjectAnimation。 所以改完代码过后,临时变量反而更多了,这些是我的猜测,但是确实在我的实验中,这么写不起优化作用。

这时候看到了另一个帖子:

https://blog.csdn.net/qiujuer/article/details/42531485

 

 

九,反射

https://blog.csdn.net/lwl20140904/article/details/80163880

为什么用:

1. private类

2. 需要拿到系统级的类

 

获取Class对象的三种方式
1 Object ——> getClass();
2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
3 通过Class类的静态方法:forName(String  className)(常用)

常用第三种方法

譬如说做SDK的时候,想要引用某个包的时候,可以用这种方式,找得到就用,找不到就不用。

GSON内部也是用反射找到输出类型的类,并返回对象。

 

单例实现的效果是用来做内存级别的操作,实现缓存

 

 

缓存

内存缓存 红位数 loser cache

内存缓存的意义是更快的用数据,可以用各种算法。

 

 

十,WebView

WebView是android中一个非常重要的控件,它的作用是用来展示一个web页面。它使用的内核是webkit引擎,4.4版本之后,直接使用Chrome作为内置网页浏览器。

https://www.jianshu.com/p/3e0136c9e748

 

 

 

 

原子操作

"原子操作(atomic operation)是不需要synchronized"

原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。

如果把一个事务可看作是一个程序,它要么完整的被执行,要么完全不执行(回滚)。这种特性就叫原子性。

 

常用的XML解析方法

sax:基于事件驱动,逐条解析,适用于只处理xml数据,不易编码,而且很难同时访问同一个文档中的多处不同数据

dom:Dom解析是将xml文件全部载入到内存,组装成一颗dom树,然后通过节点以及节点之间的关系来解析xml文件,与平台无关,java提供的一种基础的解析XML文件的API,理解较简单,但是由于整个文档都需要载入内存,不适用于文档较大时。

JDOM:简化与XML的交互并且比使用DOM实现更快,仅使用具体类而不使用接口因此简化了API,并且易于使用

DOM4j:JDOM的一种智能分支,功能较强大,建议熟练使用

 

 

内部类和静态内部类

内部类会持有外部类的对象,打印构造函数是可以看到的,JVM在编译阶段会加进去。

1. 对象创建的方式不同
静态内部类创建对象的时候,独立于外部类及其对象,就好像它是一个独立的类,可以和外部类一样使用。
内部类创建对象的时候,不能独立于外部类,必须要先创建外部类的对象,然后再用这个对象来new出内部类的对象。

2. 内部类不可以有非常量的静态成员

原因很简单,静态成员可以不依赖于对象使用,如果内部类有静态成员的话,就相当于外部类对象直接调用内部类的静态成员,一个是对象,一个是类,不伦不类的。

所以,要给内部类的定义静态成员,必须要使用静态内部类。

 

非静态内部类是在外部类对象产生的时候才会初始化,所以在没有产生对象时,内部类本身还没有被初始化,这个时候声明一个静态成员,静态成员必须在类加载的时候被加载,所以不能被声明。

 

匿名内部类

https://blog.csdn.net/hellocsz/article/details/81974251

Listener就是用了匿名内部类。

如果想要在之后remove匿名内部类里面的东西,就不要这么写了,拿不到句柄无法remove。

 

 

接口和抽象方法

https://blog.csdn.net/frankfan123/article/details/79628034

 

 

设计模式——模板方法模式

https://www.cnblogs.com/chenpi/p/5217430.html

baseActivity 就是用到了这个。

 

 

setContentView 作用与用法

作用:给当前activity设置一个layout布局

安卓里的用户界面放在res.layout下,为xml文件,系统自动生成R类,R.layout自动获取res.layout文件夹中的xml文件,再用该语句调用。之后就可以看到页面啦。

setContentView(R.layout.main);

 

findViewById 作用与用法

作用:获取layout中的某个组件,以便于操作该组件,常见于view,button。

findViewById(R.id.xml文件中对应的idName)

 

Map<Integer, String> 和 set<Integer> 

set集合:元素不允许重复,无序,允许null但最多有一个。

HashMap:无序(Tree有序),遍历Map过程中,不能用map.put和map.remove,会引发 并发修改异常,可以通过迭代器的remove(),从迭代器指向的 collection 中移除当前迭代元素来达到删除访问中的元素的目的。

Map不能用=赋值,用map.put(key,newVal)

// map初始化,以及set初始化和赋值
Map<Integer, String> map = new HashMap<>();
map.put(1, "hihihihihihi"); Set
<Integer> set = map.keySet(); //获取map全部key

Java 遍历Map时 删除元素:https://www.cnblogs.com/wxmdevelop/p/5549548.html

 

final 的用法

final如果修饰类,该类不能被继承;

final如果修饰变量,该变量不能被修改,不能再重新赋值,即变为常量;

final如果修饰方法,该方法不能被重写;

只有被final修饰的局部变量可以用在内联方法里。

使用final的目的大概有以下两条:

1、Java中内部类调用外部类局部变量时要final。

2、当我们写的代码行已经很多的时候,自己可能就忘了之前的意图,把button改了,结果就是:没有按照我们的意愿运行,然后报错。而final修饰后,是不允许修改的,就避免了这样的错误。

引用:

https://www.jianshu.com/p/fd7ce9e3eecb

 

GSON

GSON是Google提供的用来在Java对象和JSON数据之间进行映射的Java类库。可以将一个Json字符转成一个Java对象,或者将一个Java转化为Json字符串。

 

Handler的作用与用法

Handler是Android SDK来处理异步消息的核心类。子线程与主线程通过Handler来进行通信。子线程可以通过Handler来通知主线程进行UI更新。

 

个推,以及什么透传消息

文档里面有一句写了:消息推送以个推的透传消息实现。不知道这个透传是什么

透传,即透明传输(pass-through),指的是在通讯中不管传输的业务内容如何,只负责将传输的内容由源地址传输到目的地址,而不对业务数据内容做任何改变。

百科的意思大概就是东西是什么就传什么,那为什么要这样做呢?

透传消息,就是消息体格式及内容,对于传递的通道来说是不去过问的,通道只负责消息的传递,对消息不做任何处理,当客户端接收到透传消息后,由客户端自己来决定如何处理消息。正是因为透传消息可以自定义消息体,也可以自定义消息的展示方式及后续动作处理,所以弥补了通知栏消息的一些不足之处(通知栏消息是直接展示出来,相关的动作客户端无法捕获到)。

透传消息是必须打开应用才能收到,通知是杀死应用也能收到。

看完还是有点不懂,以及如何实现呢

引用和扩展阅读:https://blog.csdn.net/u011136197/article/details/78921988

 

 pollFirst

 java.util.LinkedList.pollFirst() 方法检索并移除此列表的第一个元素,或者如果此列表为空,则返回null。

 

LinkedList

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。

LinkedList<X> x= new LinkedList<>();

LinkedList.clear()  用于从链接列表中删除所有元素。使用clear()方法只会清除列表中的所有元素,而不会删除列表。换句话说,我们可以说clear()方法仅用于清空现有的LinkedList。

扩展阅读:https://www.cnblogs.com/skywang12345/p/3308807.html

 

adb pull does not exist

一定要记得先adb remount一下,不然没有读写权限,就找不到设备报does not exist的错误😭

 

实现list分成20个为一组

int userNum = list().size(); //
for ( int i = 0; i<=userNum/20; i++ ){
      List<String> whiteList = new ArrayList<>();
      for (int j = 0;j<20;j++){
           whiteList.add(list().get(i*20+j));
           if ( list().size() == i*20+j+1 ) break;
      }
      //功能代码区
}

 

 java.lang.ExceptionInInitializerError

我在一次调用类函数的时候出现了Rxjava错误:UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with.

用RxJavaPlugins.setErrorHandler(Throwable::printStackTrace); 抓下来,提示java.lang.ExceptionInInitializerError,于是去找解决办法。

当在静态初始化块中出现了异常的时候,JVM会抛出 java.lang.ExceptionInInitializerError异常。具体来说是这个类加载失败了,我的这个后面还跟着RuntimeException,指向类的构造函数。

 

extends

在Java中,通过关键字extends继承一个已有的类,被继承的类称为父类(超类,基类),新的类称为子类(派生类)。

 

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo

java.lang.ClassNotFoundException: Didn't find class "***" on path: DexPathList[[zip file

出现这个bug的原因有很多,百度一下你可以看到;我试过了网上能找到的所有方法都不行……找了前辈帮忙才解决,说一说我这里报错的原因:类名的命名规范采用大驼峰命名法,一定要严格遵守!我一开始全部小写,改成开头大写就可了。

关于命名规范扩展阅读:https://blog.csdn.net/wenzhi20102321/article/details/61650405

 

给Thread传递参数

https://www.cnblogs.com/larrylawrence/p/3517897.html

这个文给了我很好的想法,用另外一个有参函数setTar()传递参数。或者可以用回调

 

延迟执行

如果可以用handler delay写,尽量不要起线程写Thread.sleep。

 

a method on a null object reference

某方法在一个空指针引用里,有两种情况:1. 实例对象没有实例化 2. 调用的方法返回了NULL给实例,然后实例又去做操作。我检查后发现确实是实例对象没有实例化。

 

资源复用

新建对象会占用cpu,对象的保留会占用内存,销毁也会占用资源,特别是画图这类的动作。所以尽量减少动作发生,一个解决办法是建立回收机制/等待区,把不用的对象放在等待区,用的时候再引用它们。下面举个栗子:


Android自定义属性时TypedArray的使用方法

https://blog.csdn.net/qq_36523667/article/details/79289821

 

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

不能在子线程中更新ui

 

RxJava轮询器:interval

https://www.jianshu.com/p/03958daf4b82

 

getInstance()

https://www.cnblogs.com/roadone/p/7977544.html 使用getInstance()方法的原因及作用

总的来说:这是单例模式,一般用于比较大,复杂的对象,只初始化一次,应该还有一个private的构造函数,使得不能用new来实例化对象,只能调用getInstance方法来得到对象,而getInstance保证了每次调用都返回相同的对象。

getInstance往往是static的。

 

Android实现两个循环动画之间互相中断执行,clearAnimation()会导致的bug

中断动画用的clearAnimation(),如果此时动画已经开始执行了,就不能阻止它完成,并且会执行onAnimationEnd;如果在这个阶段,再一次执行这个动画,并且作用在同一个view上,会导致之前clear掉的动画又出现,并且此时两个动画在一个view上,互相牵制,这就是这个错误的表现,跟踪会发现是这个view上有两个动画。
这种情况会出现我们想要在两个动画之间相互切换,A动画在循环的过程中被中断,执行B动画,而A动画并不会立刻中断,还是会去执行onAnimationEnd,而在这个阶段B动画被中断,执行A动画,之前那个动画也会被执行。

 

Warning: Static member accessed via instance reference

Warning:
Static member accessed via instance reference 通过引用实例来访问静态成员
Shows references to static methods and fields via class instance rather than a class itself. 通过类的实例来显示静态方法和变量的引用,而不是通过类本身

现有一个类Test,有静态方法methods和静态属性fields。
对于静态变量或方法,推荐使用的方式是Test.fields,而不是new Test().fields。
当然,使用this.fields也是不行的!因为this也指向一个实例对象。
如果出现以上告警,那一定是对于java不推荐的方式使用了静态元素。

 

504错误

504错误是(网关超时) (Gateway timeout)  服务器作为网关或代理,但是没有及时从上游服务器收到请求。

这个问题完全是由后端电脑之间 IP 通讯缓慢而产生。

 

Shallow Size、Retained Size、Heap Size 和 Allocated

https://blog.csdn.net/strange_monkey/article/details/81746232

Shallow size就是对象本身占用内存的大小,不包含其引用的对象。

Retained Size 就是该对象被 Gc 之后所能回收内存的总和。

Retained Size = 对象本身的Shallow Size + 对象能直接或间接访问到的对象的Shallow Size

Heap Size:堆的大小,当资源增加,当前堆的空间不够时,系统会增加堆的大小,若超过上限(如64M,阈值视平台而定)则会被杀掉 。

Allocated:堆中已分配的大小,即 App 应用实际占用的内存大小,资源回收后,此项数据会变小。

建议:若单一操作反复进行,堆大小一直增加,则有内存泄露的隐患,可采用MAT进一步查看。

 

 

session

public key  发送给服务端,服务端再生成一个···

 

请求框架:

retrofit+okhttp

下载:downloadManager 支持断点续传……

 

getSimpleName名字会比getName更短。

 

Java反射机制:反射到名字变化多的地方,被混淆的东西,就会报错,要注意。

模块化的时候会用到;调用SDK的时候;调用第三方库;调用系统 ……  的 private成员

注解

混淆

 

model.bin

部署模型https://www.jianshu.com/p/43da2553a2fb

 

 

播放器部分:

mediaplayer:

mediaplayer采用recycleview,有复用机制。但是传入新数据的时候,就会new新的,但是之前的view

 

还可以用exoplayer

 

 

final 和effectively final

针对于jdk1.8,对于一个变量,如果没有给它加final修饰,而且没有对它的二次赋值,那么这个变量就是effectively final(有效的不会变的),如果加了final那肯定是不会变了哈。就是这个意思。

在使用内部类的时候,一个外部变量不能直接被用,但如果它是final或者effectively final就可以被内部类使用了。

 

 

 

 

 

 

posted @ 2019-06-12 12:06  粥粥Sophie  阅读(416)  评论(0编辑  收藏  举报