Android开发问题和经验总结(不断更新中)
Android开发问题和经验总结(不断更新中)
安卓常见问题,Bug等以及解答,欢迎大家更新和指正!!!
View 问题
TextView
singleLine过时了,使用lines代替。maxLines=“1”不能限制文本只显示一行
EditText
Java代码中调用了setFilters,会覆盖布局中maxLength属性,除非同时设置了LengthFilter
RecyclerView
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position...
RecyclerView绑定的 List 对象在更新数据之前进行了 clear,而这时紧接着迅速上滑 RecyclerView,就会造成崩溃,属于RecyclerView内部异常。
RecyclerView在多层嵌套的内容中,即使设置了wrap_content或者match_parent,但是数据项还是只显示1行,Item高度也不是wrap_content
使用可以让RecyclerView显示全的控件进行包裹,推荐使用NestedScrollView。(本人在项目中遇到这个问题,Recyclerview外层是多层LinearLayout, CardView等布局,还要在外层加上下拉刷新的功能。网上多种解决方案都试过,也没有采用inflate(layoutId, null, false)加载Item的方法,因为封装过Adapter再改代价很大。最后的解决方案是:在RecyclerView外层布局包裹NestedScrollView,禁用RecyclerView滑动,使用NestedScrollView的滑动即可[本人使用的下拉刷新是SmartRefreshLayout,内部使用NestedScrollView可以正常滑动,问题解决])
ScrollView嵌套RecyclerView的显示不全,滑动卡顿,夺取了焦点导致页面启动时RecyclerView上方布局没显示问题
有问题的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--页面启动时,TextView未显示,焦点被RecyclerView获取-->
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/_200dp"
android:gravity="center"
android:text="Header"
android:textColor="@color/aero"
android:textSize="@dimen/_50sp"/>
<!--没有android:nestedScrollingEnabled="false"时,滑动冲突,-->
<!--有这个属性时,ScrollView无法滑动,整个ScrollView只能滑动一点-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
滑动卡顿问题:
recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);
或者
android:nestedScrollingEnabled="false"
RecyclerView夺取焦点问题:外层布局需要增加属性
android:focusable="true"
android:focusableInTouchMode="true"
显示不全的问题:使用NestedScrollView代替ScrollView
//没有问题的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--页面启动时,TextView未显示,焦点被RecyclerView获取-->
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/_200dp"
android:gravity="center"
android:text="Header"
android:textColor="@color/aero"
android:textSize="@dimen/_50sp"/>
<!--没有android:nestedScrollingEnabled="false"时,滑动冲突,-->
<!--有这个属性时,ScrollView无法滑动,整个ScrollView只能滑动一点-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
DiffUtil.Callback RecyclerView动态更新/增减数据需要实现的类
部分(partial)绑定vs完整(full)绑定
payloads 参数 是一个从(notifyItemChanged(int, Object)或notifyItemRangeChanged(int, int, Object))里得到的合并list。
如果payloads list 不为空,那么当前绑定了旧数据的ViewHolder 和Adapter, 可以使用 payload的数据进行一次 高效的部分更新。
如果payload 是空的,Adapter必须进行一次完整绑定(调用两参方法)。
需要实现的方法:DiffUtil.Callback:public Object getChangePayload(int oldItemPosition, int newItemPosition), RecyclerView.Adapter:public void onBindViewHolder(VH holder, int position, List<Object> payloads)
ScrollView
滚动到顶部或者底部 :
scrollView.fullScroll(ScrollView.FOCUS_DOWN);滚动到底部
scrollView.fullScroll(ScrollView.FOCUS_UP);滚动到顶部
滚动到顶部的三种方式:
ScrollView.scrollTo(``0``,``0``);``//直接置顶,瞬间回到顶部,没有滚动过程,其中Y值可以设置为大于0的值,使Scrollview停在指定位置。
ScrollView.fullScroll(View.FOCUS_UP);``//类似于手动拖回顶部,有滚动过程
ScrollView.smoothScrollTo(``0``, ``0``);``//类似于手动拖回顶部,有滚动过程,其中Y值可以设置为大于0的值,使Scrollview停在指定位置。
ViewPager
Item切换重建(主要是和Fragment搭配使用时,切换到第三个页面,第一个页面销毁)
通过setOffscreenPageLimit防止频繁销毁(setOffscreenPageLimit注释:设置当前page左右两侧应该被保持的page数量,超过这个限制,page会被销毁重建(只是销毁视图),onDestroy-onCreateView,但不会执行onDestroy。尽量维持这个值小,特别是有复杂布局的时候,因为如果这个值很大,就会占用很多内存,如果只有3-4页的话,可以全部保持active,可以保持page切换的顺滑
Activity等系统组件
Activity切换时,短暂白屏问题,主要是启动singleTask或者singleInstance标志的Activity,同时关闭当前Activity,大概率出现这个问题
Activity theme加上 **<item name="android:windowDisablePreview">true</item> ** 即可。
这个标志应该也可以 <item name="android:windowIsTranslucent">true</item> ,然后onCreate应该需要去掉这个标志。