1. 调试和解决Bug的经验
1)遇到错误问题时候、如果是小众开源库 可以直接到issue中找到对应的问题。
2)如果没有,在StackOverflow上可以轻松找到。优先Google、少用Baidu。
3)普通的空指针异常定位到对象即可解决。
4)尽可能地让一个类、一个方法块只干一件事情,耦合太严重,可以拆分接口、类。否则会导致莫名奇妙的问题,并且难以看懂,降低效率和提升维护难度。
5)断点调试时候追踪代码问题是基本要求。
性能问题需要结合profiler 查看内存、CPU占用情况,并且结合 火焰图 FlameChart来查看可能的问题代码块。
2. 嵌套的RecyclerView滑动无响应的情况。
当滑动父RecyclerView的时候子RecyclerView可能没有响应,或者滑动卡顿。解决方案,刚开始考虑的是事件冲突的解决方案,外部RecyclerView全部拦截操作,或者内部拦截的方式设定dispatchTouchEvent。
由于它们是同方向的展示和滑动,而子RecyclerView需要展示的内容并不是非常多,因而自定义了一个新的LinearLayoutManager,禁止它的垂直滑动操作。因而不用重写两个RecyclerView并且效果良好。
public class CustomLinearLayoutManager extends LinearLayoutManager {
public CustomLinearLayoutManager(Context context) {
super(context);
}
@Override
public boolean canScrollVertically() {
return false;
}
}
3. 莫名的网络加载不成功问题
Failed to connect to api.ioneball.com/139.224.7.244:443
https、http请求问题。当改为http时成功访问
4. 垂直滑动的ViewPager一点小问题
重写Viewpager时候,把横向滑动的逻辑部分复用改成了能够纵向垂直的逻辑。
动态刷新数据时不能够成功让pageradapter数据增加,并且在滑动到pageradapter中 size临界大小的时候,报空指针异常。
查看自己变更的源码发现,问题出在没有DataSetObserver,它为null,那么viewpager和pagerAdapter更新数据的桥梁也就断了。
产生问题的原因是由于,新定义的viewpager和pagerAdapter不在一个包中,而关键的绑定二者的方法 setViewPagerObserver也就不能直接调用了,所以DataSetObserver为null。当时采用的是反射的方式调用关联observer。
if (mObserver == null) {
mObserver = new PagerObserver();
}
try {
Class<? extends PagerAdapter> aClass = mAdapter.getClass();
Method method = aClass.getMethod("setViewPagerObserver");
method.invoke(mAdapter, mObserver);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
断点调试发现总是走到了 NoSuchMethodException的部分。
所以重新查看了官方文档的API,发现了 registerDataSetObserver 方法。
将 Method method = aClass.getMethod("setViewPagerObserver"); 改为下面这句
Method method = aClass.getMethod("registerDataSetObserver", DataSetObserver.class);
即可成功调用了。
/**
* Register an observer to receive callbacks related to the adapter's data changing.
*
* @param observer The {@link android.database.DataSetObserver} which will receive callbacks.
*/
public void registerDataSetObserver(DataSetObserver observer) {
mObservable.registerObserver(observer);
}
/**
* Unregister an observer from callbacks related to the adapter's data changing.
*
* @param observer The {@link android.database.DataSetObserver} which will be unregistered.
*/
public void unregisterDataSetObserver(DataSetObserver observer) {
mObservable.unregisterObserver(observer);
}
void setViewPagerObserver(DataSetObserver observer) {
synchronized (this) {
mViewPagerObserver = observer;
}
}
源码中三者是写在一起的。
5. EventBus 无法更新UI?
断点发现能够成功传递数据。而界面UI却并不能够及时更新。
原因就是重新回到界面时,控件尚未被绑定就传递进了数据。数据就先于控件了。
6. Realm数据库报错情况
Each element of 'value' must be a valid managed object.
解决方式:
public class Product extends RealmObject {
private RealmList<RecipientData> mRecipients;
public void setRecipients(RealmList<RecipientData> mRecipientDatas) {
this.mRecipients = mRecipientDatas;
}
public void addRecipient(RecipientData recipientData){
if(mRecipients != null){
mRecipients.add(recipientData);
}
}
public void clearRecipients() {
mRecipients = new RealmList<>();
}
}
而不要在代码当中 new RealmList<>() 如下:
try(Realm realm = Realm.getDefaultInstance()) {
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
RealmProductModel managedProductModel = realm.copyToRealm(originalProductModel);
// managedProductModel.clearRecipients(); // calls mRecipients = new RealmList<>();
List<RecipientData> unmanagedRecipientDatas = realm.copyFromRealm(productModel.getRecipients());
for(RecipientData recipientData : unmanagedRecipientDatas) {
recipientData.setFloatingRecipient(true);
recipientData.setId(getNextKey(RecipientData.class));
}
// 不要这样操作
RealmList<RecipientData> newRealmList = new RealmList<>();
newRealmList.addAll(unmanagedRecipientDatas);
managedProductModel.setRecipients(newRealmList);
}
});
}
应当这样:
try(Realm realm = Realm.getDefaultInstance()) {
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
RealmProductModel managedProductModel = realm.copyToRealm(originalProductModel);
managedProductModel.clearRecipients(); // calls mRecipients = new RealmList<>();
List<RecipientData> unmanagedRecipientDatas = realm.copyFromRealm(originalProductModel.getRecipients());
for(RecipientData recipientData : unmanagedRecipientDatas) {
recipientData.setFloatingRecipient(true);
recipientData.setId(getNewKey(RecipientData.class));
managedProductModel.addRecipient(recipientData);
}
}
});
}