android开发问题合集

这篇博客汇总了Android开发中的一些常见问题,包括ViewPager的滑动效果、TabLayout的padding处理、SeekBar的边距问题、禁止软键盘自动弹出、JavaX类导入问题等,并给出了相应的解决方法。还涉及到了Gradle配置、Retrofit上传参数格式、WebView截图、RecyclerView滑动冲突等问题,以及在Dialog中使用Glide和ScrollView嵌套布局时需要注意的事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. ViewPager中如果有页面要显示超出界面的部分,就是clipChildren = false,这时候设置了滑动效果,即 mViewPager.setPageTransformer(false, new ScaleTransformer(), ViewCompat.LAYER_TYPE_NONE);第三个参数要关掉硬件加速,要不然,滑动时,clipChildren = false会失效。

2. TabLayout 会有默认的padding,通过app:tabPaddingEnd=“0dp”, app:tabPaddingStart="0dp"能去掉左右的padding,但是上下还是没有办法解决,虽然有提供属性app:tabPaddingTop=“0dp”,app:tabPaddingBottom=“0dp”,但是设置无效。如果自定义tab样式,需要设置tabMinWidth = 0

3. android seekbar 增加边距paddingstart 不要用paddingleft,要不然没效果。多个seekbar在同一个ViewGroup时,如果拖动某一个,其他的seekbar会响应setPressed(),会出现其他seekbar滑片被点击了的效果,也就是滑动一个,其他几个滑片都出现了放大的效果,是因为ViewGroup做了事件分发,看代码

ViewGroup


    @Override
    protected void dispatchSetPressed(boolean pressed) {
        final View[] children = mChildren;
        final int count = mChildrenCount;
        for (int i = 0; i < count; i++) {
            final View child = children[i];
            // Children that are clickable on their own should not
            // show a pressed state when their parent view does.
            // Clearing a pressed state always propagates.
            if (!pressed || (!child.isClickable() && !child.isLongClickable())) {
                child.setPressed(pressed);
            }
        }
    }

如果要去掉,只要设置 android:clickable="true"即可。就不会分发给子View了。

4. 禁止软键盘自动弹出,EditText父布局中添加android:focusable="true"和android:focusableInTouchMode=“true”

5. JavaX中的类无法导包的问题,比如:AbstractProcessor,需要新建一个Java library模块,然后在这个模块里面实现注解器,android工程没法引用javax中的类,只有Java library这个模块才能引用。

6. Android studio 开启编译期debug,在实现自定义注解时,生成Java文件,需要开启debug调试程序运行是否正确,,说一下怎么开启编译时debug:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后将配置命令行添加到gradle.properties里面
在这里插入图片描述
然后开启debug,就可以在注解器里面打断点了,编译时,就可以调试了。

6. ScrollView里面嵌套recyclerview会导致焦点在recyclerview上,会自动定位到recyclerview的位置,为了不滚动界面需要在布局顶层里面找一个view来获取焦点,添加

 android:focusable="true"
 android:focusableInTouchMode="true"

7. 新建一个Android项目时,把com.android.tools.build:gradle:3.0.0的版本改低了,改成3.0以下,重新编译会报finished with non-zero exit value 1 错误,告诉你某个属性找不到。finished with non-zero exit value 1这个错误经常会出现,记录下,遇到再补充。

8. fastjson解析私有属性时,需要设置set,get方法,不然没法解析,Gson就没这个问题

9. retrofit使用时发现@Filed与@Body上传的参数格式不一样,这其实是application/x-www-from-urlencoded与 application/json的区别,@Filed是以键值对的格式上传数据,key1=value1&key2=value2,而@Body是以json格式上传的{“key”: “value”},两者不一样,要看服务端怎么解析数据的。

10CoordinatorLayout里面的recyclerview再嵌套recyclerview会出现滑动冲突,需要在最里面的recyclerview设置setNestedScrollingEnabled(false)

11 dialog 显示的时候会出现间距没法填满布局,设置 getWindow().setBackgroundDrawable(null);

12 CoordinatorLayout 滑动导致JNI DETECTED ERROR IN APPLICATION: can’t call void android.view.View.setElevation(float) on null obj崩溃

<android.support.design.widget.AppBarLayout
        。。。。
        android:stateListAnimator="@null"
       。。。
>

13 做一个webview截图的功能的时候遇到一个问题,为了能够截取完整的内容,在外面套了个linearlayout和nestscrollview,LinearLayout是webview的父容器,然后H5内容里面有动态图表,导致在调用linearlayout的draw(cavans)的方法去绘图的时候,这些动态图表绘制不出来,webview里面的其他内容没有问题,就动态图表有问题,然后查了下,说是硬件加速的问题,然后我把webview硬件加速关了,果然好了。然而。。。在Android 10上不管用,鼓捣了半天也没找到解决办法,但是知道肯定跟硬件加速有关系,就在代码里面尝试去关闭硬件加速,发现一个奇葩的现象,要在webview的pagefinish()方法里面加才有作用。。。完全不知道为什么,webview的绘制没有去了解过,这里记下,待查。

14 Glide加载图片的时候报了错You cannot start a load for a destroyed activity
我在一个dialog里面加载了一张图片,奇怪的是我做了activity是否销毁的判断,但是还是崩了,我们都知道dialog的context必须是一个activity,所以在Glide加载之前我加了isDestory()的判断,不管用。调试的时候发现从dialog类getcontext()得到的对象不是我们传入的activity而是一个ContextThemeWrapper,原来在dialog构造器里面并不是直接使用activity而是包了一层,所以直接getcontext得到的就不是传入的activity。


    Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
        if (createContextThemeWrapper) {
            if (themeResId == ResourceId.ID_NULL) {
                final TypedValue outValue = new TypedValue();
                context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
                themeResId = outValue.resourceId;
            }
            mContext = new ContextThemeWrapper(context, themeResId);
        } else {
            mContext = context;
        }
......}

而我在加载图片之前只做了context是否是activity的判断,如果不是activity就直接加载了,没有判断是否是ContextWrapper的判断,而Glide在加载之前却做了一层判断,如下

    public RequestManager get(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("You cannot start a load on a null Context");
        } else if (Util.isOnMainThread() && !(context instanceof Application)) {
            if (context instanceof FragmentActivity) {
                return get((FragmentActivity) context);
            } else if (context instanceof Activity) {
                return get((Activity) context);
            } else if (context instanceof ContextWrapper) {
                return get(((ContextWrapper) context).getBaseContext());
            }
        }

        return getApplicationManager(context);
    }

如果context是一个Wrapper就会递归去找wrapper真正代理的对象,对于dialog的context来说,其代理的就是activity,所以glide最后还是会拿activity去加载,如果这个时候activity销毁了,就会出问题。所以在判断是否能加载图片之前要多加一层判断


    public static boolean isLoadEnable(Context context) {
        if (context == null) {
            return false;
        } else if (context instanceof Application) {
            return true;
        } else if(context instanceof Activity){
            Activity activity = (Activity)context;
            return isLoadEnable(activity);
        } else if(context instanceof ContextWrapper){
            return isLoadEnable(((ContextWrapper)context).getBaseContext());
        }else {
            return false;
        }
    }

    public static boolean isLoadEnable(Activity activity) {
        if (activity == null) {
            return false;
        } else {
            boolean destroyed = Build.VERSION.SDK_INT >= 17 && activity.isDestroyed();
            return !destroyed && !activity.isFinishing();
        }
    }

15 ScrollView里面嵌套ConstrainLayout会导致anr,不只是子布局不行,就连子布局里面存在ConstrainLayout也不行,也就是说scrollview的子布局和间接子布局都不能有ConstrainLayout。奇怪的是在一些手机上表现的特别明显,有些手机上感觉没什么影响,网上也有人遇到过这种情况https://stackoverflow.com/questions/53046700/constraintlayout-crash-with-stackoverflowerror

16 今天遇到一个kotlin很有意思的问题,看代码


    fun testLet(str: String?,str2:String?) {
        str?.let {
            Log.d("testLet", "非空")
         
        } ?: let {
            Log.d("testLet", "空")

        }
    }

我一直以为kotlin的?.let与?:let是一个if else的关系,翻译成Java就是

	if(str!=null){
	        Log.d("testLet", "非空")
	}else{
	       Log.d("testLet", "空")
	}           

事实上通过反编译也确实是这样的


  public final void testLet(@Nullable String str, @Nullable String str2) {

      if (str != null) {
         Log.d("testLet", "非空");
      } else {
         MainActivity it = (MainActivity)this;
         Log.d("testLet", "空");
      }

   }

我一直以为?.let的判断的前置条件是str是否为空,只会走上面let的其中一个作用域,直到今天我写了个这样的代码(逻辑类似)

    fun testLet(str: String?,str2:String?) {
        str?.let {
            Log.d("testLet", "非空")
            str2//并不是想返回str2,可能这里是一个表达式,而这个表达式的值是空
        } ?: let {
            Log.d("testLet", "空")
        }
    }

testLet("test",null)

然而这个输出却是

testLet: 非空
testLet: 空

居然都输出了,原来let的最后一行是返回值还能作用于后面的?:let空判断。反编译一下

 public final void testLet(@Nullable String str, @Nullable String str2) {

      if (str != null) {

         Log.d("testLet", "非空");
         if (str2 != null) {
            return;
         }
      }
      MainActivity it = (MainActivity)this;
      Log.d("testLet", "空");
   }

所以?.let与?:let作为空判断不是互斥关系的还要看let的返回值,平时还是要注意点,否则,这些小细节还是不容易排查。

17:groovy插件与Android模块不兼容,只能放到Java 模块中。
18Recyclerview 高度 WRAP_CONTENT导致卡顿
19 Textview 频繁设置settext导致卡顿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值