Android开发中遇到的问题

1、自定义View ,wrap_content 不处理时和父布局大小一样(占满父布局)。可以查看View的getDefaultSize方法。

2、NestedScrollView 嵌套 竖向的RecyclerView 时,item会被全部创建出来。具体可看 measureChildWithMargins方法,传给RecyclerView的是UNSPECIFIED。

3、RxJava : repeatWhen() 和 retryWhen() 区别就在于什么样的终止事件会触发重订阅:当.repeat()接收到.onCompleted()事件后触发重订阅 ; 当.retry()接收到.onError()事件后触发重订阅;

 被返回的Observable<?>所要发送的事件决定了重订阅是否会发生。
 如果发送的是onCompleted或者onError事件,将不会触发重订阅。
 相对的,如果它发送onNext事件,则触发重订阅(不管onNext实际上是什么事件)。
 这就是为什么使用了通配符作为泛型类型:这仅仅是个通知(next, error或者completed),一个很重要的通知而已。

4、PopUpWindow 中有EditText 时,且 EditText 没有设置inputType , 使用原生输入法输入错误单词,按空格键,提示单词错误时,移动光标到错误的单词中,会导致闪退:

     android.view.WindowManager$BadTokenException: Unable to add window -- token android.view.ViewRootImpl$W@503232 is not valid; is your activity running?
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:769)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
        at android.widget.PopupWindow.invokePopup(PopupWindow.java:1429)
        at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1203)
        at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1170)
        at android.widget.Editor$PinnedPopupWindow.updatePosition(Editor.java:3186)
        at android.widget.Editor$PinnedPopupWindow.show(Editor.java:3142)
        at android.widget.Editor$SuggestionsPopupWindow.show(Editor.java:3587)
        at android.widget.Editor.replace(Editor.java:381)
        at android.widget.Editor$3.run(Editor.java:2223)

解决办法是给EditText设置inputType为 textNoSuggestions 。该问题在Android 8上出现。Android 10/11没有出现。

5、如果NestedScrollView里面没有RecyclerView, setOnTouchListener会被调用,setOnScrollChangeListener(NestedScrollView的OnScrollChangeListener)不会被调用;

如果NestedScrollView里面有RecyclerView, setOnScrollChangeListener(NestedScrollView的OnScrollChangeListener)会被调用,setOnTouchListener却不会被调用; 不管NestedScrollView里面有没有RecyclerView,setOnScrollChangeListener(View.OnScrollChangeListener)都会被调用。

6、Android8.0上:

设置了android:windowIsTranslucent 为 true 后,不能设置android:screenOrientation ,否则会报错

java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation。

Activity使用共享元素启动:

val options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, view, "sharedName")
ActivityCompat.startActivity(activity, intent, options.toBundle())

启动后如果 setRequestedOrientation 改变Activity的方向,会报错:

java.lang.IllegalStateException: Only fullscreen activities can request orientation

解决方法是给这个Activity设置android:windowIsTranslucent 为 true。这样setRequestedOrientation就不会报错了。

7、ViewPager中使用PhotoView,多只手指左右滑动和缩放图片一起操作时,可出现下面异常:

Fatal Exception: java.lang.IllegalArgumentException:pointerIndex out of range

解决办法是使用 ViewPager2 代替 ViewPager 即可。

8、BottomNavigationView或Viewpager 有些情况选中不了对应item,比如页面刚打开时或者页面不在栈顶(后台),延时执行选中方法方可。

9、静态内部类,在被调用时才会被加载(静态内部类实现单例是懒加载)。

10、fastjson解析Kotlin Data类可能会出现问题:

data类要有默认构造方法,不然报错;
如果data类包含list,这个list的元素会被解析为JsonObject,而不是指定的类型;

11、继承Dialog自定义弹框,要设置弹框没有黑边,通过style样式指定windowBackground为透明和windowIsTranslucent为true是没有效果的,必须通过下面方法实现:

attributes.format = PixelFormat.TRANSPARENT
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))

12、Kotlin中的data class不能被继承。若data class类继承一个类,使用Gson解析json为该data class,父类的属性不会被解析。

13、Fragment中观察LiveData:

页面操作相关的在onCreate中观察,owner参数使用this,与Fragment的生命周期对应。如果在onCreateView或onViewCreated里面观察,导致每次页面创建时都会回调一次。
在ViewPager中,切换页面时Fragment会重新创建View。页面显示的数据要在onViewCreated中观察,并且owner参数使用getViewLifecycleOwner,与view的生命周期对应。

14、webView,处理h5调用 window.go(-1)返回上一页,当页面为跟页面时,这时需要关闭 Actiivty。

一种解决方法是让h5调用app提供的接口关闭页面;
另一种方法是打开h5时,先打开一个本地页面,本地页面加载完成后(onPageFinished),在加载h5。然后同样也在onPageFinished判断加载地址是否为本地页面,再根据是否加载过h5,判断是否需要关闭activity。这种方式时无侵入的,对h5友好。注意:要在onPageFinished处理,不能在onPageStarted里面处理,因为在android7.0上不生效。

15、使用liveData保存接口返回的数据时,第一次接口请求成功,liveData有数据,如果第二次接口请求失败,liveData数据变没了,但是界面还会显示旧的数据。所以最好保存一个数据的副本,和界面显示的数据保持一致。

16、使用Html.fromHtml显示文字时,在string.xml中定义字符资源,要使用:<![CDATA[...]]>包裹,不然没有效果。

<![CDATA[Return <font color="#E60039">%s</font> to your wallet after the order is received]]>

17、kotlin 要让 lambda 能return调用lambda的方法,lambda需要使用inline,不然只能return到lambda(局部返回);

crossinline 的作用是让被标记的lambda表达式不允许非局部返回。

18、js调用APP注入的方法线程不是主线程,在JavaBridge线程。

19、eventBus如果register了,但是没有定义事件接受方法,会报错:

org.greenrobot.eventbus.EventBusException: Subscriber class * and its super classes have no public methods with the @Subscribe annotation

20、sw最小宽度适配是按下匹配的,如果手机是sw为392,资源定义的是sw400,不会匹配到sw400,只会向下找小于sw392的,找不到就使用默认的。

一般以sw360为基础,算出其他尺寸的sw,公式为dp = sw360中的dp * 目标sw / 360

21、android:fontFamily=“sans-serif-medium” 对应Roboto-Medium字体

android:fontFamily="sans-serif"           // roboto regular  
android:fontFamily="sans-serif-light"     // roboto light  
android:fontFamily="sans-serif-condensed" // roboto condensed  
android:fontFamily="sans-serif-thin"      // roboto thin (android 4.2)  
android:fontFamily="sans-serif-medium"    // roboto medium (android 5.0)

22、观察liveData时,如果liveData里面有值,会立马收到回调。而不是等到有新值时才收到回调。

23、 下载的apk,如果放在getCacheDir里面,在Android7.0以下安装时,因为文件是私有,导致系统安装失败,提示解析包出现问题。放在getExternalCacheDir里面不会出现该问题。

24、beginTransaction.commitNow()是同步提交,commit()是异步提交。使用BottomNavigationView切换Fragment,或者实现类似功能是,最好使用commitNow(),如果使用commit(),在快速切换时可能会出现页面重叠,一个fragment被添加多次。

executePendingTransactions()会将所有pending在队列中还有你新提交的transactions都执行了, 而commitNow()将只会执行你当前要提交的transaction. 
所以commitNow()避免你会不小心执行了那些你可能并不想执行的transactions.
不能对要加在back stack中的transaction使用commitNow(), 即addToBackStack()和commitNow()不能同时使用

25、查看签名文件信息:keytool -list -v -keystore .\app.jks

26、点九图不能放着drawable文件下,必须放在drawable-xxhdpi(或者mipmap-xxhpi)等有分辨率的文件下,不然点九图没有效果。

27、RecyclerView里面的itemView使用ConstraintLayout的话,onCreateViewHolder里面inflate布局时,要把parent参数传进去,不然ConstraintLayout的宽度不会撑满。

28、Kotlin foreach中使用return跳出循环需要添加标签才能跳出

29、Application的onCreate方法只在app冷启动的时候才执行。温启动不会执行。

30、popupwindow如果再activity销毁时忘记了关闭,虽不影响app,但会出现windowLeaked异常,在log会打印。

31、如果没有在 manifest 文件中声明 Camera 权限,使用 ACTION_IMAGE_CAPTURE 不需要对 Camera 权限做运行时权限处理,代码正常运行。如果manifest声明了就必须要做权限处理。

32、LiveData的观察回调里面不要使用onBackPressed关闭页面,如果网络很慢,app放到后台后,网络请求完成,再回到前台,在Android8和9的机器上会出现该异常:

Caused by: java.lang.IllegalStateException: FragmentManager is already executing transactions
如果使用onBackPressed(),假如你的Activity有添加管理fragment回退的话,调用该方法是不会退出Activity的.直到Fragment回退栈清空,才会退出Activity。
如果使用finish(),那么就会直接退出Activity。

猜你喜欢

转载自blog.csdn.net/ganduwei/article/details/111151497