0、介绍
本篇整理自己在开发过程中遇到的各种坑,以便以后参考。
1、自定义Dialog样式时发现顶部出现一条蓝色横线
//部分手机dialog会出现蓝色横线,因此将它隐藏掉
Context context = getDialog().getContext();
int divierId = context.getResources().getIdentifier("android:id/titleDivider", null, null);
View divider = getDialog().findViewById(divierId);
if (divider != null) divider.setBackgroundColor(Color.TRANSPARENT);
在show之前将横线隐藏掉
2、 Permission Denial: starting Intent with revoked permission android.permission.CAMERA
崩溃原因:测试机版本>=M,代码中通过ACTION调取摄像机,如果Manifest文件中声明了android.permission.CAMERA权限则会崩溃。
解决方案:
1、如果项目中没有使用到相机权限则把CAMERA权限删掉。
2、启动该ACTION时先询问相机权限是否已动态声明。
3、getExternalFilesDir(null)可能返回空
getExternalFilesDir(null).getPath() 由于可能返回空报NullPointerException,因此使用时需要加一层trycatch保护
4、升级AS的ndk时出现"No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android"
崩溃原因:更新之后少了ndk-bundle下的toolchains少了文件
解决方案:
https://developer.android.com/ndk/downloads/?hl=zh-en
在这里下载稳定的ndk库,下载完之后跟Android/sdk/ndk-bundle/toolchains/下的文件比对,把少了的补充进去。
5、gradle dependency中exclude用法
一般在dependencies下的依赖格式:
groupName:moduleName:版本号
例如:
com.android.support:appcompat-v7:$SUPPORT_LIBRARY_VERSION
查看某个依赖它下面的依赖树,一般类似于:
+--- com.android.support:appcompat-v7:27.1.1
| +--- com.android.support:support-annotations:27.1.1
| +--- com.android.support:support-core-utils:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- android.arch.lifecycle:runtime:1.1.0
| | +--- android.arch.lifecycle:common:1.1.0
| | \--- android.arch.core:common:1.1.0
| +--- com.android.support:support-fragment:27.1.1
| | +--- com.android.support:support-compat:27.1.1 (*)
| | +--- com.android.support:support-core-ui:27.1.1
| | | +--- com.android.support:support-annotations:27.1.1
| | | +--- com.android.support:support-compat:27.1.1 (*)
| | | \--- com.android.support:support-core-utils:27.1.1 (*)
| | +--- com.android.support:support-core-utils:27.1.1 (*)
| | +--- com.android.support:support-annotations:27.1.1
| | +--- android.arch.lifecycle:livedata-core:1.1.0
| | | +--- android.arch.lifecycle:common:1.1.0
| | | +--- android.arch.core:common:1.1.0
| | | \--- android.arch.core:runtime:1.1.0
| | | \--- android.arch.core:common:1.1.0
| | \--- android.arch.lifecycle:viewmodel:1.1.0
| +--- com.android.support:support-vector-drawable:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1 (*)
| \--- com.android.support:animated-vector-drawable:27.1.1
| +--- com.android.support:support-vector-drawable:27.1.1 (*)
| \--- com.android.support:support-core-ui:27.1.1 (*)
+--- com.jakewharton:butterknife:8.8.1
| +--- com.jakewharton:butterknife-annotations:8.8.1
| | \--- com.android.support:support-annotations:25.3.0 -> 27.1.1
| +--- com.android.support:support-annotations:25.3.0 -> 27.1.1
| \--- com.android.support:support-compat:25.3.0 -> 27.1.1 (*)
exclude的格式为:
implementation ('com.jakewharton:butterknife:8.8.1') {
exclude group: 'com.android.support',module:'support-annotations'
}
规则很简单,移除该依赖下的groupName为"com.android.support",且moduleName为"support-annotations"的依赖
改完之后的依赖树
+--- com.android.support:appcompat-v7:27.1.1
| +--- com.android.support:support-annotations:27.1.1
| +--- com.android.support:support-core-utils:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- android.arch.lifecycle:runtime:1.1.0
| | +--- android.arch.lifecycle:common:1.1.0
| | \--- android.arch.core:common:1.1.0
| +--- com.android.support:support-fragment:27.1.1
| | +--- com.android.support:support-compat:27.1.1 (*)
| | +--- com.android.support:support-core-ui:27.1.1
| | | +--- com.android.support:support-annotations:27.1.1
| | | +--- com.android.support:support-compat:27.1.1 (*)
| | | \--- com.android.support:support-core-utils:27.1.1 (*)
| | +--- com.android.support:support-core-utils:27.1.1 (*)
| | +--- com.android.support:support-annotations:27.1.1
| | +--- android.arch.lifecycle:livedata-core:1.1.0
| | | +--- android.arch.lifecycle:common:1.1.0
| | | +--- android.arch.core:common:1.1.0
| | | \--- android.arch.core:runtime:1.1.0
| | | \--- android.arch.core:common:1.1.0
| | \--- android.arch.lifecycle:viewmodel:1.1.0
| +--- com.android.support:support-vector-drawable:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1 (*)
| \--- com.android.support:animated-vector-drawable:27.1.1
| +--- com.android.support:support-vector-drawable:27.1.1 (*)
| \--- com.android.support:support-core-ui:27.1.1 (*)
+--- com.jakewharton:butterknife:8.8.1
| +--- com.jakewharton:butterknife-annotations:8.8.1
| \--- com.android.support:support-compat:25.3.0 -> 27.1.1 (*)
同时还支持只指定moduleName或者只指定groupName的情况。
只指定moduleName:
implementation ('com.jakewharton:butterknife:8.8.1') {
exclude module:'support-annotations'
}
这之后的依赖树为:
+--- com.android.support:appcompat-v7:27.1.1
| +--- com.android.support:support-annotations:27.1.1
| +--- com.android.support:support-core-utils:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- android.arch.lifecycle:runtime:1.1.0
| | +--- android.arch.lifecycle:common:1.1.0
| | \--- android.arch.core:common:1.1.0
| +--- com.android.support:support-fragment:27.1.1
| | +--- com.android.support:support-compat:27.1.1 (*)
| | +--- com.android.support:support-core-ui:27.1.1
| | | +--- com.android.support:support-annotations:27.1.1
| | | +--- com.android.support:support-compat:27.1.1 (*)
| | | \--- com.android.support:support-core-utils:27.1.1 (*)
| | +--- com.android.support:support-core-utils:27.1.1 (*)
| | +--- com.android.support:support-annotations:27.1.1
| | +--- android.arch.lifecycle:livedata-core:1.1.0
| | | +--- android.arch.lifecycle:common:1.1.0
| | | +--- android.arch.core:common:1.1.0
| | | \--- android.arch.core:runtime:1.1.0
| | | \--- android.arch.core:common:1.1.0
| | \--- android.arch.lifecycle:viewmodel:1.1.0
| +--- com.android.support:support-vector-drawable:27.1.1
| | +--- com.android.support:support-annotations:27.1.1
| | \--- com.android.support:support-compat:27.1.1 (*)
| \--- com.android.support:animated-vector-drawable:27.1.1
| +--- com.android.support:support-vector-drawable:27.1.1 (*)
| \--- com.android.support:support-core-ui:27.1.1 (*)
+--- com.jakewharton:butterknife:8.8.1
| +--- com.jakewharton:butterknife-annotations:8.8.1
| \--- com.android.support:support-compat:25.3.0 -> 27.1.1 (*)
剩余的一种情况就不演示了。
注意:
1、exclude语法在官方包(就是support库这些)的依赖下不奏效,这个不知道什么原因。
6、DialogFragment给Dialog配置onDismissListener()不起作用。
案例:
dialogFragment.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
//TODO
}
});
dialogFragment.show(getFragmentManager(),"");
这种情况下dialog关闭时onDismiss不会调用。
原因:
查看DialogFragment的源码发现,DialogFragment里面也有给dialog设置监听器。
public void onActivityCreated(Bundle var1) {
super.onActivityCreated(var1);
......
this.mDialog.setCancelable(this.mCancelable);
this.mDialog.setOnCancelListener(this);
this.mDialog.setOnDismissListener(this);
if (var1 != null) {
Bundle var4 = var1.getBundle("android:savedDialogState");
if (var4 != null) {
this.mDialog.onRestoreInstanceState(var4);
}
}
}
}
因此如果我们按案例中的方案设置的监听器会被DialogFragment本身覆盖,自然调用不到。
解决方案
自定义DialogFragment,覆盖DialogFragment的onDismiss()方法,添加上自己的逻辑既可。
@Override
public void onDismiss(DialogInterface dialogInterface) {
super.onDismiss(dialogInterface);
if (onDissmissListener != null) onDissmissListener.onDismiss(dialogInterface);
}
7、GridView的item有默认点击背景
解决方案:
gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));// 去掉默认点击背景
8、gradle dependecy一直依赖最新版本的依赖
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
9、Android stroke边线框只画某一边
-
10、TextView当使用Spannable时不显示省略号的问题
重写TextView,反射修改其中的属性
public class FoldTextView extends AppCompatTextView {
public FoldTextView (Context context) {
super(context);
}
public FoldTextView (Context context, AttributeSet attrs) {
super(context, attrs);
}
public FoldTextView (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
StaticLayout layout = null;
Field field = null;
try {
Field staticField = DynamicLayout.class.getDeclaredField("sStaticLayout");
staticField.setAccessible(true);
layout = (StaticLayout) staticField.get(DynamicLayout.class);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (layout != null) {
try {
field = StaticLayout.class.getDeclaredField("mMaximumVisibleLineCount");
field.setAccessible(true);
field.setInt(layout,2);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
if (layout != null && field != null) {
try {
field.setInt(layout,Integer.MAX_VALUE);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
11、子module下的资源文件id不是静态常量
原因:
(1)该module编译后的代码中该资源被替换成值
(2)主工程下有同名资源id的话会被替换掉
(3)主工程会重新针对该资源生成一个id
(4)之后就会出现子module中该资源找不到的情况
子module资源id非静态常量可能出现的情况
(1)主工程有相同名称资源时会使用主工程的
(2)子module下由于资源id非静态常量,没办法使用switch-case
(3)子module下没法直接使用ButterKnife
12、当同个布局下出现两个同名id控件的情况
出现情况:Fragment包含ViewPager,ViewPager又包含Fragment,此时父Fragment和子Fragment拥有同id控件,父Fragment通过findViewById()找到的不一定是父Fragment下的控件,因为它会返回第一个找到的控件
13、Fragment中调用startActivityForResult
(1)getActivity().startActivityForResult(),只有父Aty的onActivityResult被调用,Fragment的不被调用
(2)startActivityForResult(),当前Fragment和父Activity的onActivityResult被调用
()getParentFragment().startAcitivtyForResult(),父Fragment和父Activity的onActivityResult被调用
14、latest.release指向非最新版本号
与第三方联调时候会发现当第三方第一时间更新了maven依赖时通过latest.release没有把最新版本的依赖拉下来,拉的是之前的版本。这个时候手动改版本号就可解决。
如果找得到原因的话,这里补充
15、Dialog初始化Context误区
因为最近有个需求是需要计时后弹出Dialog,此时如果用户的app在后台且计时到了需要弹窗,如果Activity被回收了,出现了crash
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@ce0817e is not valid; is your activity running?
原因:
Dialog可以传入Context初始化,但Dialog的展示需要依附Activity,换言之就是show()时候需要判断Activity是否存活
解决方案:
初始化时Context尽量传入为Activity
if(!activity.isFinishing()) dialog.show()