antd $confirm contentt怎么添加输入框并且在确认里面拿到输入的值?


目录介绍
1.1 java.lang.UnsatisfiedLinkError找不到so库异常
1.2 java.lang.IllegalStateException非法状态异常
1.3 android.content.res.Resources$NotFoundException
1.4 java.lang.IllegalArgumentException参数不匹配异常
1.5 IllegalStateException:Can't compress a recycled bitmap
1.6 java.lang.NullPointerException空指针异常
1.7 android.view.WindowManager$BadTokenException异常
1.8 java.lang.ClassCastException类转化异常
1.9 Toast运行在子线程问题,handler问题
2.1 java.lang.ClassNotFoundException类找不到异常
2.2 java.util.concurrent.TimeoutException连接超时崩溃
2.3 java.lang.NumberFormatException格式转化错误
2.4 java.lang.IllegalStateException: Fragment not attached to Activity
2.5 ArrayIndexOutOfBoundsException 角标越界异常
2.6 IllegalAccessException 方法中构造方法权限异常
2.7 android.view.WindowManager$BadTokenException,dialog弹窗异常
2.8 java.lang.NoClassDefFoundError 找不到类异常
2.9 Android出现:Your project path contains non-ASCII characters.
3.1 OnErrorNotImplementedException【 Can't create handler inside thread that has not called Looper.prepare()】
3.2 adb.exe,start-server' failed -- run manually if necessary
3.3 java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $
3.4 android.content.ActivityNotFoundException: No Activity found to handle Intent
3.5 Package manager has died导致崩溃
3.6 IllegalArgumentException View添加窗口错误
3.7 IllegalStateException: Not allowed to start service Intent异常崩溃
3.8 java.lang.IllegalStateException:Can not perform this action after onSaveInstanceState
3.9 在Fragment中通过getActivity找不到上下文,报null导致空指针异常
4.1 IllegalArgumentException导致崩溃【url地址传入非法参数,转义字符】
4.2 ClassNotFoundException: Didn't find class "" on path: /data/app/*错误
4.3 NoClassDefFoundError异常【该异常表示找不到类定义】
4.4 公司之前项目使用客服udesk,sdk更新后初始化导致崩溃问题
4.5 java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception
4.6 java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException
4.7 00768556 /vendor/lib/libllvm-glnext.so [armeabi-v8]无法加载so库导致崩溃
4.8 Only the original thread that created a view hierarchy can touch its views
4.9 NoSuchMethodException android.support.v4.app.Fragment$InstantiationException
好消息
博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近20万字],转载请注明出处,谢谢!
链接地址:https://github.com/yangchong2...
如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!
1.1 java.lang.UnsatisfiedLinkError
A.详细崩溃日志信息
# main(1)
java.lang.UnsatisfiedLinkError
dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.paidian.hwmc-1/base.apk", dex file "/data/app/com.paidian.hwmc-1/base.apk"],nativeLibraryDirectories=[/data/app/com.paidian.hwmc-1/lib/arm64, /data/app/com.paidian.hwmc-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libijkffmpeg.so"
B.查看崩溃类信息
这个异常类的大意是:如果Java虚拟机找不到声明为本机的方法的适当本机语言定义,则引发。
public class UnsatisfiedLinkError extends LinkageError {
private static final long serialVersionUID = -4019343241616879428L;
public UnsatisfiedLinkError() {
super();
}
public UnsatisfiedLinkError(String s) {
super(s);
}
}
C.项目中异常分析
根据实际项目可知,当准备播放视频时,找不到libijkffmpeg.so这个库,导致直接崩溃。
D.引发崩溃日志的流程分析
F.解决办法
ndk {
//根据需要 自行选择添加的对应cpu类型的.so库。
//abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'mips'
abiFilters 'armeabi-v7a'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
//这两个是必须要加的,其它的可供选择
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
//其他库文件
//compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
//compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
//compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
//compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
}
G.知识延申
Android 应用开发者应该对 UnsatisfiedLinkError 这种类型的错误比较熟悉了,这个问题一直困扰着广大的开发者,那么有没有想过有可能你什么都没做错,也会出现这个问题呢?
我们在 Android 应用开发测试过程中曾经碰到过这样的案例,apk 在某机型上安装完成之后运行即崩溃,报错 UnsatisfiedLinkError。
java.lang.UnsatisfiedLinkError: Couldn’t load mobsec from loader dalvik.system.PathClassLoader.....findLibrary returned null
首先怀疑是在 apk 中相应的 libsabi 目录下没有放置 libmobsec.so,然而检查发现这个 so 在所有的 libsabi 下都有放置过,继续排查;
然后的想法是放置的 so 不是对应 abi 的,比如由于粗心在 armeabi 目录下放置了 x86 指令集的 so,导致在 armeabi 指令集手机上加载出错,这个也被排除掉;
就在没有头绪的时候,想到 System.loadLibrary 函数加载 so 时,系统是从指定的路径下加载的,那么这个路径下 so 是否存在呢?
我们知道应用的私有 Native library 目录 /data/data/packagename/lib 是一个符号链接,链接到 /data/app-lib/<package name> 目录,System.loadLibrary 是到这个目录去尝试加载 so 的。
adb shell 到这个路径下,使用命令 ls 查看,果然这个 libmobsec.so 是不存在的。那么是什么原因导致的呢?
分析 Android 系统源码的实现,发现 /data/app-lib/<package name> 这个目录下的 so ,是在系统安装 apk 时从 apk 的 lib 目录下去抽取的。
1.2 java.lang.IllegalStateException非法状态异常
A.详细崩溃日志信息
onSaveInstanceState方法是在该Activity即将被销毁前调用,来保存Activity数据的,如果在保存玩状态后
再给它添加Fragment就会出错。
IllegalStateException: Can not perform this action after onSaveInstanceState:
B.查看崩溃类信息
在非法或不适当的时间调用方法的信号。换句话说,Java环境或Java应用程序没有处于请求操作的适当状态。
public class IllegalStateException extends RuntimeException {
public IllegalStateException() {
super();
}
public IllegalStateException(String s) {
super(s);
}
public IllegalStateException(String message, Throwable cause) {
super(message, cause);
}
public IllegalStateException(Throwable cause) {
super(cause);
}
static final long serialVersionUID = -1848914673093119416L;
}
C.项目中异常分析
分析
D.引发崩溃日志的流程分析
F.解决办法
解决办法就是把commit()方法替换成 commitAllowingStateLoss()
G.其他延申
错误类型大致为以下几种:
java.lang.IllegalStateException:Can't change tag of fragment d{e183845 #0 d{e183845}}: was d{e183845} now d{e183845 #0 d{e183845}}
java.lang.IllegalStateException:Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 37 path $.data
第一种:我在显示fragment的代码中使用了:fragment.show(getSupportFragmentManager,
fragment.toString());而这里是因为两次toString()结果不同,导致不同的tag指向的是同一个fragment。获取fragment的tag的正确方法应该是使用其提供的fragment.getTag()方法。
第二种:该异常是由于服务器错误返回的JSON字符串和服务器正常下时返回的JSON字符串结构不同,导致利用Gson解析的时候报了一个异常:本该去解析集合却强制去解析对象所致.解决办法:在使用Gson解析JSON时try cash一下,不报错按照正常逻辑继续解析,报异常则处理为请求失败逻辑即可.
1.3 android.content.res.Resources$NotFoundException
A.详细崩溃日志信息
Android资源不是可绘制的(颜色或路径)
Resource is not a Drawable (color or path): TypedValue{t=0x2/d=0x7f040151 a=2}
android.view.LayoutInflater.createView(LayoutInflater.java:620)
B.查看崩溃类信息
当找不到请求的资源时,资源API将引发此异常。
public static class NotFoundException extends RuntimeException {
public NotFoundException() {
}
public NotFoundException(String name) {
super(name);
}
public NotFoundException(String name, Exception cause) {
super(name, cause);
}
}
C.项目中异常分析
由于将图片资源拷贝到了drawable-land-xhdpi目录下,本来应该拷贝到drawable-xhdpi目录下。
D.引发崩溃日志的流程分析
F.解决办法
1.引用的资源ID 是否能匹配到R.java文件中定义的资源;
2.是否因为缓存等原因导致编译APK时未把资源文件打包进去,可以把APK反编译检查下;
3.是否使用了一个错误的类型来引用了某个资源或者配置资源时存在错误;
4.是否将Int等整型变量作为了参数传给了View.setText调用,这种情况下该整型变量将被认为是一个资源ID号去资源列表中查找对应的资源,导致找不到对应资源错误;解决方法是做类型转换View.setText(String.valueOf(Int id))。
1.4 java.lang.IllegalArgumentException参数不匹配异常
A.详细崩溃日志信息
B.查看崩溃类信息
参数不匹配异常,通常由于传递了不正确的参数导致。
public class IllegalArgumentException extends RuntimeException {
public IllegalArgumentException() {
super();
}
public IllegalArgumentException(String s) {
super(s);
}
public IllegalArgumentException(String message, Throwable cause) {
super(message, cause);
}
public IllegalArgumentException(Throwable cause) {
super(cause);
}
private static final long serialVersionUID = -5365630128856068164L;
}
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
G.常见的出现场景
Activity、Service状态异常;
非法URL;
UI线程操作。
Fragment中嵌套了子Fragment,Fragment被销毁,而内部Fragment未被销毁,所以导致再次加载时重复,在onDestroyView() 中将内部Fragment销毁即可
在请求网络的回调中使用了glide.into(view),view已经被销毁会导致该错误
1.5 IllegalStateException:Can't compress a recycled bitmap
A.详细崩溃日志信息
无法压缩回收位图
Can't compress a recycled bitmap
com.paidian.hwmc.utils.i.a(FileUtils.java:75)
B.查看崩溃类信息
如果位图已被回收,则希望抛出异常的方法将调用此值。知道了崩溃的具体位置,就该分析具体的原因呢!
public boolean compress(CompressFormat format, int quality, OutputStream stream) {
checkRecycled("Can't compress a recycled bitmap");
//省略代码
return result;
}
//如果位图已被回收,则希望抛出异常的方法将调用此值。
private void checkRecycled(String errorMessage) {
if (mRecycled) {
throw new IllegalStateException(errorMessage);
}
}
C.项目中异常分析
使用了已经被释放过内存的对象。对于Bitmap:Bitmap bitmap=一个bitmap对象。使用过程中调用bitmap.recycle(),之后再使用bitmap就会报错。
D.引发崩溃日志的流程分析
bitmap.recycle()解释如下所示,释放与此位图关联的本机对象,并清除对像素数据的引用。这将不会同步释放像素数据;它只允许在没有其他引用的情况下对其进行垃圾收集。位图被标记为“死”,这意味着如果调用getPixels()或setPixels(),它将抛出异常,而不会绘制任何内容。此操作不能反转,因此只有在确定没有进一步使用位图的情况下才应调用该操作。这是一个高级调用,通常不需要调用,因为当没有对此位图的引用时,普通GC进程将释放此内存。
Free the native object associated with this bitmap, and clear the reference to the pixel data
F.解决办法
第一种:在使用bitmap前增加判断,if (mBitmap.isRecycled()) return null;
1.6 java.lang.NullPointerException空指针异常
A.详细崩溃日志信息
Please call the AutoSizeConfig#init() first
com.paidian.hwmc.base.BaseApplication.initAutoSizeConfig(BaseApplication.java:386)
B.查看崩溃类信息
空指针异常,也是十分常见的一个异常
public class NullPointerException extends RuntimeException {
private static final long serialVersionUID = 5162710183389028792L;
public NullPointerException() {
super();
}
public NullPointerException(String s) {
super(s);
}
}
C.项目中异常分析
空指针发生场景较多,是指某一个对象报null,这个使用去使用它的话就i会报该异常。
D.引发崩溃日志的流程分析
导致出现空指针的原因: 必须满足两个条件才会发生空指针:引用变量指向了空,并且调用了这个引用的方法
空指针问题解决思路:
查看Log信息看第一行导致空指针发生的代码,直接双击打开报空指针的类
查看该行代码中有几处调用了方法,则有几个对象可能是空的,找出哪个对象是空的
查看这些对方在哪里赋值了
如果没赋值,则给她赋值,问题解决
如果有地方赋值了,则看这个方法有没有被调用(Ctrl + Shift + G)
如果没有调用(可能没调用或可能调用时机太晚),在使用她前先调用赋值,问题解决
如果有调用,则看是不是有其它地方又给她赋值为null了,如果没有设置为null,则要看赋值的变量和我们使用时的变量是否是同一个变量。
F.解决办法
1.7 android.view.WindowManager$BadTokenException异常,Toast报错Unable to add window
A.详细崩溃日志信息
报错日志,是不是有点眼熟呀?更多可以看我的开源项目:https://github.com/yangchong211
android.view.WindowManager$BadTokenException
Unable to add window -- token android.os.BinderProxy@7f652b2 is not valid; is your activity running?
B.查看崩溃类信息
查询报错日志是从哪里来的
C.项目中异常分析
D.引发崩溃日志的流程分析
这个异常发生在Toast显示的时候,原因是因为token失效。通常情况下,一般是不会出现这种异常。但是由于在某些情况下, Android进程某个UI线程的某个消息阻塞。导致 TN 的 show 方法 post 出来 0 (显示) 消息位于该消息之后,迟迟没有执行。这时候,NotificationManager 的超时检测结束,删除了 WMS 服务中的
token 记录。删除 token 发生在 Android 进程 show 方法之前。这就导致了上面的异常。
测试代码。模拟一下异常的发生场景,其实很容易,只需要这样做就可以出现上面这个问题
Toast.makeText(this,"潇湘剑雨-yc",Toast.LENGTH_SHORT).show();
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
F.解决办法
G.哪些情况会发生该问题?
UI 线程执行了一条非常耗时的操作,比如加载图片等等,就类似上面用 sleep 模拟情况
进程退后台或者息屏了,系统为了减少电量或者某种原因,分配给进程的cpu时间减少,导致进程内的指令并不能被及时执行,这样一样会导致进程看起来”卡顿”的现象
当TN抛出消息的时候,前面有大量的 UI 线程消息等待执行,而每个 UI 线程消息虽然并不卡顿,但是总和如果超过了 NotificationManager 的超时时间,还是会出现问题
1.8 java.lang.ClassCastException类转化异常
A.详细崩溃日志信息
android.widget.FrameLayout cannot be cast to android.widget.RelativeLayout
com.paidian.hwmc.goods.activity.GoodsDetailsActivity.initView(GoodsDetailsActivity.java:712)
B.查看崩溃类信息
抛出以指示代码试图将对象强制转换为它不是实例的子类。
public class ClassCastException extends RuntimeException {
private static final long serialVersionUID = -9223365651070458532L;
public ClassCastException() {
super();
}
public ClassCastException(String s) {
super(s);
}
}
C.项目中异常分析
该异常表示类型转换异常,通常是因为一个类对象转换为其他不兼容类对象抛出的异常,检查你要转换的类对象类型。
D.引发崩溃日志的流程分析
F.解决办法
一般在强制类型转换时出现,例如如果A向B转换,而A不是B的父类时,将产生java.lang.ClassCastException异常。一般建议做这时要使用instanceof做一下类型判断,再做转换。
该案例中,需要把FrameLayout更改成RelativeLayout就可以呢
1.9 Toast运行在子线程问题,handler问题
A.详细崩溃日志信息
先来看看问题代码,会出现什么问题呢?
new Thread(new Runnable() {
@Override
public void run() {
ToastUtils.showRoundRectToast("潇湘剑雨-杨充");
}
}).start();
报错日志如下所示:
然后找找报错日志从哪里来的
![image]()
子线程中吐司的正确做法,代码如下所示
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
ToastUtils.showRoundRectToast("潇湘剑雨-杨充");
Looper.loop();
}
}).start();
得出的结论
Toast也可以在子线程执行,不过需要手动提供Looper环境的。
Toast在调用show方法显示的时候,内部实现是通过Handler执行的,因此自然是不阻塞Binder线程,另外,如果addView的线程不是Loop线程,执行完就结束了,当然就没机会执行后续的请求,这个是由Hanlder的构造函数保证的。可以看看handler的构造函数,如果Looper==null就会报错,而Toast对象在实例化的时候,也会为自己实例化一个Hanlder,这就是为什么说“一定要在主线程”,其实准确的说应该是
“一定要在Looper非空的线程”。
Handler的构造函数如下所示:
2.1 java.lang.ClassNotFoundException类找不到异常
A.详细崩溃日志信息
Didn't find class "om.scwang.smartrefresh.layout.SmartRefreshLayout" on path: DexPathList[[zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/base.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_dependencies_apk.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_slice_0_apk.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_slice_1_apk.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_s
com.paidian.hwmc.goods.activity.GoodsDetailsActivity.onCreate(GoodsDetailsActivity.java:209)
B.查看崩溃类信息
当应用程序尝试使用字符串名称加载类时引发:但无法找到具有指定名称的类的定义。从1.4版开始,已对此异常进行了修改,以符合通用的异常链接机制。在构建时提供并通过{@link#getException()}方法访问的“在加载类时引发的可选异常”现在称为原因,并且可以通过{@link
Throwable#getCace()}方法以及前面提到的“遗留方法”进行访问。
public class ClassNotFoundException extends ReflectiveOperationException {
private static final long serialVersionUID = 9176873029745254542L;
private Throwable ex;
public ClassNotFoundException() {
super((Throwable)null);
// Disallow initCause
}
public ClassNotFoundException(String s) {
super(s, null);
//
Disallow initCause
}
public ClassNotFoundException(String s, Throwable ex) {
super(s, null);
//
Disallow initCause
this.ex = ex;
}
public Throwable getException() {
return ex;
}
public Throwable getCause() {
return ex;
}
}
C.项目中异常分析
该异常表示在路径下,找不到指定类,通常是因为构建路径问题导致的。
D.引发崩溃日志的流程分析
F.解决办法
G.其他延申
2.2 java.util.concurrent.TimeoutException连接超时崩溃
A.详细崩溃日志信息
java.util.concurrent.TimeoutException: android.view.ThreadedRenderer.finalize() timed out after 10 seconds
at android.view.ThreadedRenderer.nDeleteProxy(Native Method)
at android.view.ThreadedRenderer.finalize(ThreadedRenderer.java:423)
B.查看崩溃类信息
当阻塞操作超时引发的异常。指定超时的阻塞操作需要一种方法来指示已发生超时。对于许多此类操作,可以返回指示超时的值;如果不可能或不需要,则应声明并抛出{@code TimeoutException}。
public class TimeoutException extends Exception {
private static final long serialVersionUID = 1900926677490660714L;
public TimeoutException() {}
public TimeoutException(String message) {
super(message);
}
}
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
一般是系统在gc时,调用对象的finalize超时导致,解决办法:
1.检查分析finalize的实现为什么耗时较高,修复它;
2.检查日志查看GC是否过于频繁,导致超时,减少内容开销,防止内存泄露。
G.其他延申
2.3 java.lang.NumberFormatException格式转化错误
A.详细崩溃日志信息
Exception in thread "main" java.lang.NumberFormatException: For input string: "100 "
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:458)
at java.lang.Integer.parseInt(Integer.java:499)
B.查看崩溃类信息
引发,以指示应用程序试图将字符串转换为数字类型之一,但该字符串没有适当的格式。
public class NumberFormatException extends IllegalArgumentException {
static final long serialVersionUID = -2848938806368998894L;
public NumberFormatException () {
super();
}
public NumberFormatException (String s) {
super (s);
}
static NumberFormatException forInputString(String s) {
return new NumberFormatException("For input string: \"" + s + "\"");
}
}
C.项目中异常分析
错误关键字 java.lang.NumberFormatException 这句话明确告诉了我们是数字格式异常,接着后面有 For input string: "100 " 提示,这就告诉我们,当前想把 "100 " 转换成数字类型时出错了,这样就很确切了。
D.引发崩溃日志的流程分析
F.解决办法
解决办法很简单,改成 Integer.parseInt(str.trim()),注意将字符串转化成整数数据类型时,注意需要trim一下。
G.其他延申
2.4 java.lang.IllegalStateException: Fragment not attached to Activity
A.详细崩溃日志信息
java.lang.IllegalStateException: Fragment not attached to Activity
B.查看崩溃类信息
C.项目中异常分析
出现该异常,是因为Fragment的还没有Attach到Activity时,调用了如getResource()等,需要上下文Content的函数。
出现该异常,是因为Fragment还没有Attach到Activity时,调用了如getResource()等,需要上下文Context的函数。解决方法,就是等将调用的代码写在OnStart()中。
D.引发崩溃日志的流程分析
F.解决办法
将调用的代码运行在Fragment Attached的生命周期内。
第一种:在调用需要Context的函数之前,增加一个判断isAdded()
if(isAdded()){//isAdded方法是Android系统提供的,只有在Fragment被添加到所属的Activity后才返回true
activity.getResourses().getString(...);
}
第二种:如下所示
@Override
public void onAttach(Context context) {
super.onAttach(context);
activity = (MainActivity) context;
}
@Override
public void onDetach() {
super.onDetach();
if (activity != null) {
activity = null;
}
}
G.其他延申
发生场景:该错误经常发生在fragment的线程中执行了一个耗时操作,线程在执行完毕后会调用getResources来更新ui。如果在线程操作没有完成,就调用getActivity().recreate()重新加载activity或屏幕旋转,这时就会出现Fragment not attached to Activity的错误
2.5 ArrayIndexOutOfBoundsException 角标越界异常
A.详细崩溃日志信息
该异常表示数组越界
java.lang.ArrayIndexOutOfBoundsException: 0
at com.example.mytest.CityAdapter.setDataNotify(CityAdapter.java:183)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
B.查看崩溃类信息
引发,以指示已使用非法索引访问数组。索引不是负的,就是大于或等于数组的大小。
public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
private static final long serialVersionUID = -5116101128118950844L;
public ArrayIndexOutOfBoundsException() {
super();
}
public ArrayIndexOutOfBoundsException(int index) {
super("Array index out of range: " + index);
}
public ArrayIndexOutOfBoundsException(String s) {
super(s);
}
public ArrayIndexOutOfBoundsException(int sourceLength, int index) {
super("length=" + sourceLength + "; index=" + index);
}
public ArrayIndexOutOfBoundsException(int sourceLength, int offset,
int count) {
super("length=" + sourceLength + "; regionStart=" + offset
+ "; regionLength=" + count);
}
}
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
这种情况一般要在数组循环前做好length判断,index超出length上限和下限时都会报错。举例如下:一个数组int test[N],一共有N个元素分别是test[0]~test[N-1],如果调用test[N],将会报错。建议读取时,不要超过数组的长度(array.length)。
Android中一种常见情形就是上拉刷新中header也会作为listview的第0个位置,如果判断失误很容易造成越界。
G.其他延申
2.6 IllegalAccessException 方法中构造方法权限异常
A.详细崩溃日志信息
Unable to instantiate application com.pedaily.yc.meblurry.App: java.lang.IllegalAccessException
B.查看崩溃类信息
当应用程序试图反射地创建实例(数组除外)、设置或获取字段或调用方法时,将引发IllegalAccessException,但当前执行的方法无法访问指定的类、字段、方法或构造函数的定义。
public class IllegalAccessException extends ReflectiveOperationException {
private static final long serialVersionUID = 6616958222490762034L;
public IllegalAccessException() {
super();
}
public IllegalAccessException(String s) {
super(s);
}
}
C.项目中异常分析
错误提示是,构造方法的权限不对
D.引发崩溃日志的流程分析
F.解决办法
检查了整个Application,才发现,原来有一个无参数的构造方法,被设计成private。修改其为public即可。
G.其他延申
android BroadcastReceiver遇到java.lang.IllegalAccessException解决方法,错误原因主要是app中其他地方调用了默认的构造函数,必须增加默认构造函数且访问权限为public
2.7 android.view.WindowManager$BadTokenException,dialog弹窗异常
A.详细崩溃日志信息
Unable to add window -- token android.os.BinderProxy@9a57804 is not valid; is your activity running?
android.view.ViewRootImpl.setView(ViewRootImpl.java:907)
B.查看崩溃类信息
在WindowManager中可以找到这个异常类,主要发生在尝试添加视图时引发的
public static class BadTokenException extends RuntimeException {
public BadTokenException() {
}
public BadTokenException(String name) {
super(name);
}
}
C.项目中异常分析
该异常表示不能添加窗口,通常是所要依附的view已经不存在导致的。
D.引发崩溃日志的流程分析
F.解决办法
之前项目中有一个自定义弹窗,偶尔会报这个错。解决办法如下代码所示
主要逻辑是在弹窗show或者dismiss的时候,都增加了逻辑判断,判断宿主activity存在。
/**
* 展示加载窗
* @param context
上下文
* @param isCancel
是否可以取消
*/
public static void show(Context context,
boolean isCancel) {
if(context == null){
return;
}
if (context instanceof Activity) {
if (((Activity) context).isFinishing()) {
return;
}
}
if (loadDialog != null && loadDialog.isShowing()) {
return;
}
loadDialog = new LoadLayoutDialog(context, isCancel);
loadDialog.show();
}
/**
* 销毁加载窗
* @param context
上下文
*/
public static void dismiss(Context context) {
if(context == null){
return;
}
try {
if (context instanceof Activity) {
if (((Activity) context).isFinishing()) {
loadDialog = null;
return;
}
}
if (loadDialog != null && loadDialog.isShowing()) {
Context loadContext = loadDialog.getContext();
if (loadContext instanceof Activity) {
if (((Activity) loadContext).isFinishing()) {
loadDialog = null;
return;
}
}
loadDialog.dismiss();
loadDialog = null;
}
} catch (Exception e) {
e.printStackTrace();
loadDialog = null;
}
}
G.其他延申
H.其他建议
1.不要在非UI线程中使用对话框创建,显示和取消对话框;
2.尽量少用单独线程,出发是真正的耗时操作采用线程,线程也不要直接用Java式的匿名线程,除非是那种单纯的操作,操作完成不需要做其他事情的。
3.如果是在fragment中发起异步网络的回调中进行dialog的操作,那么在操作之前,需要判断 isAdd( ),避免fragment被回收了但是还要求dialog去dismiss
4.在Activity onDestroy中对Dialog提前进行关闭
2.8 java.lang.NoClassDefFoundError 找不到类异常
A.详细崩溃日志信息
B.查看崩溃类信息
如果Java虚拟机或ClassLoader实例试图加载类的定义(作为普通方法调用的一部分或使用新的表达式创建新实例的一部分),则抛出该类的定义。编译当前执行的类时存在搜索类定义,但无法再找到该定义。
public class NoClassDefFoundError extends LinkageError {
private static final long serialVersionUID = 9095859863287012458L;
public NoClassDefFoundError() {
super();
}
public NoClassDefFoundError(String s) {
super(s);
}
private NoClassDefFoundError(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
}
C.项目中异常分析
问题的主要原因:方法数超65536限制。由于实际开发当中的需求不断变更,开源框架越来越多,大多都用第三方SDK,导致方法数很容易超出65536限制。出现错误Java.lang.NoClassDefFoundError
D.引发崩溃日志的流程分析
这个错误是Android应用的方法总数限制造成的。android平台的Java虚拟机Dalvik在执行DEX格式的Java应用程序时,使用原生类型short来索引DEX文件中的方法。这意味着单个DEX文件可被引用的方法总数被限制为65536。通常APK包含一个classes.dex文件,因此Android应用的方法总数不能超过这个数量,这包括Android框架、类库和你自己开发的代码。而Android
5.0和更高版本使用名为ART的运行时,它原生支持从APK文件加载多个DEX文件。在应用安装时,它会执行预编译,扫描classes(..N).dex文件然后将其编译成单个.oat文件用于执行. 通熟的讲,就是分包。
F.解决办法
64k解决办法
G.其他延申
2.9 Android出现:Your project path contains non-ASCII characters.
A.详细崩溃日志信息
B.查看崩溃类信息
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
很好解决啦,就是你的工程项目路径或者项目名称包含了中文,修改相关的名称就好
G.其他延申
3.1 OnErrorNotImplementedException【 Can't create handler inside thread that has not called Looper.prepare()】
A.详细崩溃日志信息
Can't create handler inside thread that has not called Looper.prepare()
B.查看崩溃类信息
C.项目中异常分析
D.引发崩溃日志的流程分析
这是因为Handler对象与其调用者在同一线程中,如果在Handler中设置了延时操作,则调用线程也会堵塞。每个Handler对象都会绑定一个Looper对象,每个Looper对象对应一个消息队列(MessageQueue)。如果在创建Handler时不指定与其绑定的Looper对象,系统默认会将当前线程的Looper绑定到该Handler上。
在主线程中,可以直接使用new Handler()创建Handler对象,其将自动与主线程的Looper对象绑定;在非主线程中直接这样创建Handler则会报错,因为Android系统默认情况下非主线程中没有开启Looper,而Handler对象必须绑定Looper对象。
如果在主线程中创建handler时,系统会自动创建Looper,但是在子线程中创建handler时,是不会自动创建Looper的,此时如果不手动创建Looper,系统就会崩溃
F.解决办法
不要在子线程中做UI操作,比如更改界面,吐司等等……
方法1:需先在该线程中手动开启Looper(Looper.prepare()-->Looper.loop()),然后将其绑定到Handler对象上;
final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //执行耗时操作
    try {
      Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
      Thread.sleep(2000);
      Log.e("bm", "执行完耗时操作了~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
    Looper.prepare();
    new Handler().post(runnable);//在子线程中直接去new 一个handler
    Looper.loop();    //这种情况下,Runnable对象是运行在子线程中的,可以进行联网操作,但是不能更新UI
  }
}.start();
方法2:通过Looper.getMainLooper(),获得主线程的Looper,将其绑定到此Handler对象上。
final Runnable runnable = new Runnable() {
  @Override
  public void run() {
    //执行耗时操作
    try {
      Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
      Thread.sleep(2000);
      Log.e("bm", "执行完耗时操作了~");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
  }
};
new Thread() {
  public void run() {
  
//在子线程中直接去new 一个handler
    new Handler(Looper.getMainLooper()).post(runnable);
    //这种情况下,Runnable对象是运行在主线程中的,不可以进行联网操作,但是可以更新UI
  }
}.start();
G.其他延申
3.2 platform-toolsadb.exe,start-server' failed -- run manually if necessary
A.详细崩溃日志信息
B.查看崩溃类信息
C.项目中异常分析
adb启动失败,端口被占用
D.引发崩溃日志的流程分析
F.解决办法
百度google大家多说的是任务管理器 kill掉adb 或者重启adb server,但我任务管理器就没有adb ,猜测是某个程序占用了adb端口。于是按此思路查找。
5037为adb默认端口 查看该端口情况如下:
netstat -aon|findstr "5037"
TCP 127.0.0.1:5037 0.0.0.0:0 LISTENING 6540
发现6540占用了 5037端口,继续查看6540的task,发现是wandoujia .如下所示
tasklist|findstr "6540"
wandoujia_daemon.exe 6540 Console 1 4,276 K
接下来问题就好解决了,在任务管理器kill掉wandoujia_daemon.exe ,运行android程序,ok .
1.关闭xx荚进程
2.adb kill-server
3.adb start-server
G.其他延申
3.3 java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $
*/
public static boolean isJson(String value) {
try {
new JSONObject(value);
} catch (JSONException e) {
return false;
}
return true;
}
/**
* 判断是否是json结构
*/
public static boolean isGoodJson(String json) {
try {
new JsonParser().parse(json);
return true;
} catch (JsonParseException e) {
System.out.println("bad json: " + json);
return false;
}
}
```
G.其他延申,补充说明
解决办法:后台输出稳定的Gson格式。此方法工程量太大
真正的问题是我的数据结构有问题
例如下面Json字符串:
{"code":1,"info":"success","results":{"id":"1","name":"hehe"}}
results对应的应该是一个实体类,如果这个时候想把他解析为String或者List就会出现异常
如果参考使用GsonForm处理后的数据模型,几乎不会出现问题;加入result后面的内容可能在请求时会因为某些原因会存在格式上的变化,这个时候就有出现该异常的风险。Gson中,关键字后面出现""引起来的内容将会被只认为是STRING,“{}”只被认为是类,“[]”只被认为是List,这个几乎是强制性的。
就是说如果你的实体预计是获取String的变量,但是关键字后面对应的却出现了“{”或“[”,那么这个转换将被认为是错误的,抛出异常。
3.4 android.content.ActivityNotFoundException: No Activity found to handle Intent
A.详细崩溃日志信息
android.content.ActivityNotFoundException: No Activity found to handle Intent
B.查看崩溃类信息
当调用{@link Context#startActivity}或其变体之一失败时,会引发此异常,因为无法找到执行给定意图的活动。
public class ActivityNotFoundException extends RuntimeException
{
public ActivityNotFoundException()
{
}
public ActivityNotFoundException(String name)
{
super(name);
}
};
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
第一种办法:做一个try catch
Intent intent = new Intent(Intent.ACTION_SENDTO,url);
try {
context.startActivity(intent);
} catch(ActivityNotFoundException exception) {
Toast.makeText(this, "no activity", Toast.LENGTH_SHORT).show();
}
第二种办法:判断是否有应用宝客户端
//避免安装了应用宝的用户点击其他外部链接走此方法导致崩溃
//判断是否用应用宝客户端
if(AppUtils.isPkgInstalled(AdDetailActivity.this,"com.tencent.android.qqdownloader")){
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent);
}
3.5 Package manager has died导致崩溃
A.详细崩溃日志信息
出错代码位置
public static String softVersionName(Context context) {
PackageInfo info = null;
try {
info = context.getPackageManager().getPackageInfo( context.getPackageName(), 0);
//在这里
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return info.versionName;
}
B.查看崩溃类信息
C.项目中异常分析
D.引发崩溃日志的流程分析
原因分析(Binder造成)
如果一个进程中使用的Binder内容超过了1M,就会crash.
如果Binder的使用超出了一个进程的限制就会抛出TransactionTooLargeException这个异常。
如果是其他原因造成Binder crash的话就会抛出RuntimeException。
F.解决办法
public static String softVersionName(Context context) {
PackageInfo info = null;
try {//增加同步块
synchronized (context) {
info =context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
}
return info.versionName;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
G.其他延申
private void test() {
//这个Demo就是同时创建两个线程来进行Binder调用.
for (int i = 0; i < 2; i++) {
new Thread() {
@Override
public void run() {
int count = 0;
List<PackageInfo> list = getPackageManager().getInstalledPackages(0);
for (PackageInfo info : list) {
if(count >=1000){
break;
}
try {
PackageInfo pi = getPackageManager().getPackageInfo(info.packageName, PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e) {
}
}
}
}.start();
}
}
}
错误打印日志
解决方式:其实只要避免多个线程同时来调用Binder就可以了,毕竟一个线程用了会释放,所以理论上是很难发生的。
synchronized(MainActivity.class){
PackageInfo pi = getPackageManager() .getPackageInfo(info.packageName, PackageManager.GET_ACTIVITIES);
}
3.6 IllegalArgumentException View添加窗口错误
A.详细崩溃日志信息
View=com.android.internal.policy.impl.PhoneWindow$DecorView{22a4fb16 V.E..... R.....ID 0,0-1080,1020} not attached to window manager
com.flyco.dialog.widget.base.BaseDialog.superDismiss(BaseDialog.java)
B.查看崩溃类信息
C.项目中异常分析
该异常表示view没有添加到窗口管理器,通常是我们dismiss对话框的时候,activity已经不存在了,建议不要在非UI线程操作对话框。
D.引发崩溃日志的流程分析
常发生这类Exception的情形都是,有一个费时的线程操作,需要显示一个Dialog,在任务开始的时候显示一个对话框,然后当任务完成了在Dismiss对话框,如果在此期间如果Activity因为某种原因被杀掉且又重新启动了,那么当dialog调用dismiss的时候WindowManager检查发现Dialog所属的Activity已经不存在,所以会报错。要避免此类Exception,就要正确的使用对话框,也要正确的使用线程
F.解决办法
可以参考崩溃bug日志总结1中的1.7
G.其他延申,建议
不要在非UI线程中使用对话框创建,显示和取消对话框;
尽量少用单独线程,出发是真正的耗时操作采用线程,线程也不要直接用Java式的匿名线程,除非是那种单纯的操作,操作完成不需要做其他事情的。
如果是在fragment中发起异步网络的回调中进行dialog的操作,那么在操作之前,需要判断 isAdd( ),避免fragment被回收了但是还要求dialog去dismiss
在Activity onDestroy中对Dialog提前进行关闭
3.7 IllegalStateException: Not allowed to start service Intent异常崩溃
A.详细崩溃日志信息
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { act=initApplication cmp=com.paidian.hwmc/.service.InitializeService }: app is in background uid UidRecord{a37d28d u0a386 TRNB bg:+5m30s482ms idle procs:3 seq(0,0,0)}
B.查看崩溃类信息
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
G.其他延申
3.8 java.lang.IllegalStateException:Can not perform this action after onSaveInstanceState
A.详细崩溃日志信息
B.查看崩溃类信息
C.项目中异常分析
通过下面的源码分析,我们可以知道,出现以上崩溃日志的原因,是因为我们在按下页面返回键的时候,当前Activity以及在执行销毁操作(也就是说我们以前在其他地方调用了finish方法)。
D.引发崩溃日志的流程分析
问题所在是Activity#onBackPressed()方法。查看源代码:点击onBackPressed方法中的super
在FragmentActivity中
@Override
public void onBackPressed() {
if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
super.onBackPressed();
}
}
接着再次点击super,在Activity中
public void onBackPressed() {
if (mActionBar != null && mActionBar.collapseActionView()) {
return;
}
if (!mFragments.getFragmentManager().popBackStackImmediate()) {
finishAfterTransition();
}
}
public void finishAfterTransition() {
if (!mActivityTransitionState.startExitBackTransition(this)) {
finish();
}
}
我们看到onBackPressed()方法执行了两个操作,第一个是获取当前的FragmentManager,并且执行退栈操作,第二个是在退栈完成之后,执行finish方法。继续查看源码,关键是FragmentManager实现类的popBackStackImmediate方法
@Override
public boolean popBackStackImmediate() {
checkStateLoss();
executePendingTransactions();
return popBackStackState(mHost.getHandler(), null, -1, 0);
}
我们看到,在执行退栈动作之前,这里还有一步检查操作
private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
从这里,我们终于找到了崩溃日志上的异常文案:Can not perform this action after onSaveInstanceState
F.解决办法
方案1,在调用super.onBackPressed的时候,我们需要判断当前Activity是否正在执行销毁操作。
if (!isFinishing()) {
super.onBackPressed();
}
方案2,通过上面的源码分析,我们也知道了,super.onBackPressed最后也是调用finish()方法,因此我们可以重写onBackPressed,直接调用finish方法。
G.其他延申
3.9 在Fragment中通过getActivity找不到上下文,报null导致空指针异常
A.详细崩溃日志信息
B.查看崩溃类信息
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
在Fragment中直接调用
private MActivity mActivity;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = (MActivity) activity;
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
G.其他延申
源码解读:在FragmentActivity中
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
……
}
如果从最近使用的应用里面点击我们的应用,系统会恢复之前被回收的Activity,这个时候FragmentActivity在oncreate里面也会做Fragment的恢复
@SuppressWarnings("deprecation")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
mFragments.restoreLoaderNonConfig(nc.loaders);
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
……
}
if (mPendingFragmentActivityResults == null) {
mPendingFragmentActivityResults = new SparseArrayCompat<>();
mNextCandidateRequestIndex = 0;
}
mFragments.dispatchCreate();
}
假设我们的页面叫MyActivity(继承自FragmentActivity),其中用到的Fragment叫MyFragment。出现上面这种情况时,app发生的变化如下:
1、在前面提到的几种情况下系统回收了MyActivity
2、通过onSaveInstanceState保存MyFragment的状态
3、用户再次点击进入app
4、由于MyActivity被回收,系统会重启MyActivity,根据之前保存的MyFragment的状态恢复fragment
5、MyActivity的代码逻辑中,会再次创建新的MyFragment
6、页面出现混乱,覆盖了两层的fragment。假如恢复的MyFragment使用到了getActivity()方法,会报空指针异常
对于上面的问题,可以考虑下面这两种解决办法:
1、不保存fragment的状态:在MyActivity中重写onSaveInstanceState方法,将super.onSaveInstanceState(outState);注释掉,让其不再保存Fragment的状态,达到fragment随MyActivity一起销毁的目的。
2、重建时清除已经保存的fragment的状态:在恢复Fragment之前把Bundle里面的fragment状态数据给清除。方法如下:
if(savedInstanceState!= null){
String FRAGMENTS_TAG =
"Android:support:fragments";
savedInstanceState.remove(FRAGMENTS_TAG);
}
4.1 IllegalArgumentException导致崩溃【url地址传入非法参数,转义字符】
A.详细崩溃日志信息
B.查看崩溃类信息
C.项目中异常分析
只有很少一部分传入非法参数导致崩溃,不能直接用常规方法。需要过滤
D.引发崩溃日志的流程分析
F.解决办法
Java调用 URLDecoder.decode(str,"UTF-8");抛出以上的异常,其主要原因是%在URL中是特殊字符,需要特殊转义一下
public static String replacer(String data) {
try {
//使用%25替换字符串中的%号
data = data.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
data = URLDecoder.decode(data, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
4.2 ClassNotFoundException: Didn't find class "" on path: /data/app/*错误
A.详细崩溃日志信息
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{*****Activity}: java.lang.ClassNotFoundException: Didn't find class "*****Activity" on path: /data/app/*******.apk
B.查看崩溃类信息
当应用程序尝试使用字符串名称加载类时引发:但无法找到具有指定名称的类的定义。从1.4版开始,已对此异常进行了修改,以符合通用的异常链接机制。在构建时提供并通过{@link#getException()}方法访问的“在加载类时引发的可选异常”现在称为原因,并且可以通过{@link
Throwable#getCace()}方法以及前面提到的“遗留方法”进行访问。
public class ClassNotFoundException extends ReflectiveOperationException {
private static final long serialVersionUID = 9176873029745254542L;
private Throwable ex;
public ClassNotFoundException() {
super((Throwable)null);
// Disallow initCause
}
public ClassNotFoundException(String s) {
super(s, null);
//
Disallow initCause
}
public ClassNotFoundException(String s, Throwable ex) {
super(s, null);
//
Disallow initCause
this.ex = ex;
}
public Throwable getException() {
return ex;
}
public Throwable getCause() {
return ex;
}
}
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
1。Manifest文件中注册的Activity的名称,有没有写错,包名有没有搞错,有些网友,可能只写一个类名,前面用点号代替,但是这个类不在默认的包内,所以报这个错,那么只要写上类的全名,即可。
2.你的使用的class,是一个外部的JAR包,当在工程中编译使用时,发布成APK并没有包含JAR文件,所以APK在执行的时候就找不到JAR文件,会报错。有些android,需要一些第三方的包,直接将其引入,在以前是可以的,但是在最新的adt中不行,必须在程序中新建一个libs文件夹,将第三方的jar文件copy到libs文件夹中,才行,很多人因为这样才报错,特别是以前的项目,默认并没有这个libs文件夹,但是新版本的adt,默认就建了libs这个文件夹。
3。有一点也很重要,在Java Build Path面板下的Order and Export中,一定要把你引入的jar文件,勾上,否则,跟没引用一样,切记。
4.3 NoClassDefFoundError异常【该异常表示找不到类定义】
4.4 公司之前项目使用客服udesk,sdk更新后初始化导致崩溃问题
出错原因:初始化udesk客服sdk时,需要传入token,name等信息。token是作为客户的唯一标识,而客服第三方sdk是以token命名创建sqlite数据库,造成数据库名称过长……
报错信息:
Could not open database, (OS error - 36:File name too long)
{"code":"4444","message":"未知错误","exception":"Data too long for column 'sdk_token' at row 1"}
日志错误截图
解决办法
第一种解决办法:客户端裁剪token前10位[或者15位也行,就是不要长度过长]字符串作为客户唯一标识,经过测试可以解决问题,但是需要发版,并且无法改正之前版本的问题。
第二种解决办法:第三方平台解决,因为之前使用没有问题,后来出现了该问题。可能是他们改代码引起该问题!已经跟第三方发过信息,周一看……
4.5 java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception
A.详细崩溃日志信息
Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
Caused by: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
B.查看崩溃类信息
public class ExecutionException extends Exception {
protected ExecutionException() {
throw new RuntimeException("Stub!");
}
protected ExecutionException(String message) {
throw new RuntimeException("Stub!");
}
public ExecutionException(String message, Throwable cause) {
throw new RuntimeException("Stub!");
}
public ExecutionException(Throwable cause) {
throw new RuntimeException("Stub!");
}
}
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
在项目的中,gradle.properties文件中添加一行代码就行,即gradle.properties(Project properties)
android.enableAapt2=false
G.其他延申
gradle.properties 里面配置的东西,在gradle 文件里面可以直接引用
在项目根目录的gradle.properties文件配置:
# 应用版本名称
VERSION_NAME=1.0.0
# 应用版本号
VERSION_CODE=100
# 支持库版本
SUPPORT_LIBRARY=24.2.1
# MIN_SDK_VERSION
ANDROID_BUILD_MIN_SDK_VERSION=14
# TARGET_SDK_VERSION
ANDROID_BUILD_TARGET_SDK_VERSION=24
# BUILD_SDK_VERSION
ANDROID_BUILD_SDK_VERSION=24
# BUILD_TOOLS_VERSION
ANDROID_BUILD_TOOLS_VERSION=24.0.3
这时候配置app和lib的build.gradle可以这样写:
android {
compileSdkVersion project.ANDROID_BUILD_SDK_VERSION as int
buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
defaultConfig {
applicationId project.APPLICATION_ID // lib项目不需要配置这一项
versionCode project.VERSION_CODE as int
versionName project.VERSION_NAME
minSdkVersion project.ANDROID_BUILD_MIN_SDK_VERSION as int
targetSdkVersion project.ANDROID_BUILD_TARGET_SDK_VERSION as int
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
//这里注意是双引号
compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY}"
compile "com.android.support:design:${SUPPORT_LIBRARY}"
compile "com.android.support:recyclerview-v7:${SUPPORT_LIBRARY}"
compile "com.android.support:support-annotations:${SUPPORT_LIBRARY}"
compile "com.android.support:cardview-v7:${SUPPORT_LIBRARY}"
compile "com.android.support:support-v4:${SUPPORT_LIBRARY}"
}
4.6 java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException
A.详细崩溃日志信息
也就是执行异常,进程异常。
Caused by: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: Error while executing process /Users/duanzheng/WorkSpace/AndroidSdk/build-tools/27.0.3/aapt with arguments {package -f --no-crunch -I /Users/duanzheng/WorkSpace/AndroidSdk/platforms/android-27/android.jar -M /Users/duanzheng/.jenkins/workspace/android_hwmc_project/UdeskSDKUI/build/intermediates/manifests/aapt/release/AndroidManifest.xml -S /Users/duanzheng/.jenkins/workspace/android_hwmc_project/UdeskSDKUI/build/intermediates/res/merged/release --non-constant-id -0 apk --no-version-vectors}
Caused by: org.gradle.process.internal.ExecException: Process 'command '/Users/duanzheng/WorkSpace/AndroidSdk/build-tools/27.0.3/aapt'' finished with non-zero exit value 1
//注意这里看重点:aapt'' finished with non-zero exit value 1
B.查看崩溃类信息
C.项目中异常分析
D.引发崩溃日志的流程分析
F.解决办法
网上搜索第一种方法:初步猜测可能由同步下来不需要的build文件造成,clean一下项目看是否能解决。
H.aapt是啥
AAPT是Android资源打包工具
https://www.jianshu.com/p/8d6...
4.7 00768556 /vendor/lib/libllvm-glnext.so [armeabi-v8]无法加载so库导致崩溃
4.8 Only the original thread that created a view hierarchy can touch its views
4.9 NoSuchMethodException android.support.v4.app.Fragment$InstantiationException
详细日志错误
vity.baojia.ChoiceResultPsActivity}: android.support.v4.app.Fragment$InstantiationException:
Unable to instantiate fragment com.cheoo.app.fragment.choiceresultps.QuotationDaQuanFragment:
could not find Fragment constructor
可能导致的出现该bug的原因分析
问题主要跟Activity的数据恢复有关,其可能产生的Exception:android.support.v4.app.Fragment$InstantiationException
每个Fragment必须要有一个无参构造方法,这样该Fragment在Activity恢复状态的时候才可以被实例化。
强烈建议,Fragment的子类不要有其他含参构造方法,因为这些构造方法在Fragment重新实例化时不会被调用。取而代之的方式是,通过setArguments(Bundle)设置参数,然后通过getArguments获得参数。如果的Fragment没有无参构造方法,app在恢复Activity时(例如旋转设备),会出现crash。
问题代码如下所示,解决办法就是添加一个无参构造方法即可。
public static BusinessHotCarFragment newInstance(Map<String,String> map) {
BusinessHotCarFragment fragment = new BusinessHotCarFragment(map);
return fragment;
}
public BusinessHotCarFragment(Map<String,String> map) {
this.pMap =map;
}
//解决问题办法,添加一个无参构造方法
public BusinessHotCarFragment(){}
深入分析为何Fragment需要无参构造函数才可以实例化
既然报的找不到构造方法的错误,先来看一下Fragment的构造函数:
谷歌翻译一下可知。构造函数上有一段注释:默认构造器。每一个Fragment必须有一个无参的构造函数,以便当Activity恢复状态时fragment可以实例化。强烈建议fragment的子类不要有其他的有参构造函数,因为当fragment重新实例化时不会调用这些有参构造函数;如果要传值应该使用setArguments方法,在需要获取这些值时调用getArguments方法。
/**
* Default constructor.
<strong>Every</strong> fragment must have an
* empty constructor, so it can be instantiated when restoring its
* activity's state.
It is strongly recommended that subclasses do not
* have other constructors with parameters, since these constructors
* will not be called when the fragment is re-instantiated; instead,
* arguments can be supplied by the caller with {@link #setArguments}
* and later retrieved by the Fragment with {@link #getArguments}.
*
* <p>Applications should generally not implement a constructor. Prefer
* {@link #onAttach(Context)} instead. It is the first place application code can run where
* the fragment is ready to be used - the point where the fragment is actually associated with
* its context. Some applications may also want to implement {@link #onInflate} to retrieve
* attributes from a layout resource, although note this happens when the fragment is attached.
*/
public Fragment() {
}
这个异常是从哪里来的?
这一段注释明确的告诉我们使用有参构造函数会出问题,建议使用无参构造函数,但是并没有告诉我们具体是哪里的问题。我们在Fragment源码中搜索could not find Fragment constructor这个异常,发现是在instantiate方法中抛出的。
看上面的代码我们可以知道,Fragment的实例化是通过调用类对象的getConstructor()方法获取构造器对象并调用其newInstance()方法创建对象的。此时还会将args参数设置给Fragment。
public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) {
try {
Class<?> clazz = sClassMap.get(fname);
if (clazz == null) {
// Class not found in the cache, see if it's real, and try to add it
clazz = context.getClassLoader().loadClass(fname);
sClassMap.put(fname, clazz);
}
Fragment f = (Fragment) clazz.getConstructor().newInstance();
if (args != null) {
args.setClassLoader(f.getClass().getClassLoader());
f.setArguments(args);
}
return f;
} catch (ClassNotFoundException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (java.lang.InstantiationException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (IllegalAccessException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": make sure class name exists, is public, and has an"
+ " empty constructor that is public", e);
} catch (NoSuchMethodException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": could not find Fragment constructor", e);
} catch (InvocationTargetException e) {
throw new InstantiationException("Unable to instantiate fragment " + fname
+ ": calling Fragment constructor caused an exception", e);
}
}
这个异常是哪里触发的呢?
找到了具体报错的地方,但是这个方法是在哪里调用触发的呢?在Fragment没有找到调用的地方,由于Fragment是由FragmentManager管理的,在该类发现是在restoreAllState方法中调用的
这方法名意为恢复所有的状态,而其中注释为创建激活Fragment的列表,并将他们从保存的状态中实例化。这个方法应该是Fragment重新实例化时调用的方法。该方法在Fragment的restoreChildFragmentState被调用。
void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
// Build the full list of active fragments, instantiating them from
// their saved state.
mActive = new SparseArray<>(fms.mActive.length);
for (int i=0; i<fms.mActive.length; i++) {
FragmentState fs = fms.mActive[i];
if (fs != null) {
FragmentManagerNonConfig childNonConfig = null;
if (childNonConfigs != null && i < childNonConfigs.size()) {
childNonConfig = childNonConfigs.get(i);
}
ViewModelStore viewModelStore = null;
if (viewModelStores != null && i < viewModelStores.size()) {
viewModelStore = viewModelStores.get(i);
}
Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig,
viewModelStore);
if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.put(f.mIndex, f);
// Now that the fragment is instantiated (or came from being
// retained above), clear mInstance in case we end up re-restoring
// from this FragmentState again.
fs.mInstance = null;
}
}
...
}
然后看一下在Fragment的restoreChildFragmentState方法源码。
restoreChildFragmentState方法又在Fragment的onCreate方法中调用,这里将保存的savedInstanceState状态又传递给了restoreChildFragmentState以完成Fragment的重新实例化。
void restoreChildFragmentState(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(
FragmentActivity.FRAGMENTS_TAG);
if (p != null) {
if (mChildFragmentManager == null) {
instantiateChildFragmentManager();
}
mChildFragmentManager.restoreAllState(p, mChildNonConfig);
mChildNonConfig = null;
mChildFragmentManager.dispatchCreate();
}
}
}
接着看看Fragment中的onCreate方法
@CallSuper
public void onCreate(@Nullable Bundle savedInstanceState) {
mCalled = true;
restoreChildFragmentState(savedInstanceState);
if (mChildFragmentManager != null
&& !mChildFragmentManager.isStateAtLeast(Fragment.CREATED)) {
mChildFragmentManager.dispatchCreate();
}
}
得出结论
经过以上的分析,我们就知道了为什么这个错误出在了Fragment的有参构造函数上。因为当Fragment因为某种原因重新创建时,会调用到onCreate方法传入之前保存的状态,在instantiate方法中通过反射无参构造函数创建一个Fragment,并且为Arguments初始化为原来保存的值,而此时如果没有无参构造函数就会抛出异常,造成程序崩溃。
其他介绍
01.关于博客汇总链接
1.技术博客汇总
2.开源项目汇总
3.生活博客汇总
4.喜马拉雅音频汇总
5.其他汇总
02.关于我的博客
github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
简书:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜马拉雅听书:http://www.ximalaya.com/zhubo...
开源中国:https://my.oschina.net/zbj161...
泡在网上的日子:http://www.jcodecraeer.com/me...
邮箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault头条:https://segmentfault.com/u/xi...
掘金:https://juejin.im/user/593943...
博客开源到GitHub上了,更多可以看:https://github.com/yangchong2...

我要回帖

更多关于 antd form 的文章

 

随机推荐