1. 調(diào)試和解決Bug的經(jīng)驗
1)遇到錯誤問題時候、如果是小眾開源庫 可以直接到issue中找到對應的問題。
2)如果沒有,在StackOverflow上可以輕松找到。優(yōu)先Google、少用Baidu。
3)普通的空指針異常定位到對象即可解決。
4)盡可能地讓一個類、一個方法塊只干一件事情,耦合太嚴重,可以拆分接口、類。否則會導致莫名奇妙的問題,并且難以看懂,降低效率和提升維護難度。
5)斷點調(diào)試時候追蹤代碼問題是基本要求。
性能問題需要結(jié)合profiler 查看內(nèi)存、CPU占用情況,并且結(jié)合 火焰圖 FlameChart來查看可能的問題代碼塊。
2. 嵌套的RecyclerView滑動無響應的情況。
當滑動父RecyclerView的時候子RecyclerView可能沒有響應,或者滑動卡頓。解決方案,剛開始考慮的是事件沖突的解決方案,外部RecyclerView全部攔截操作,或者內(nèi)部攔截的方式設(shè)定dispatchTouchEvent。
由于它們是同方向的展示和滑動,而子RecyclerView需要展示的內(nèi)容并不是非常多,因而自定義了一個新的LinearLayoutManager,禁止它的垂直滑動操作。因而不用重寫兩個RecyclerView并且效果良好。
public class CustomLinearLayoutManager extends LinearLayoutManager {
public CustomLinearLayoutManager(Context context) {
super(context);
}
@Override
public boolean canScrollVertically() {
return false;
}
}
3. 莫名的網(wǎng)絡加載不成功問題
Failed to connect to api.ioneball.com/139.224.7.244:443
https、http請求問題。當改為http時成功訪問
4. 垂直滑動的ViewPager一點小問題
重寫Viewpager時候,把橫向滑動的邏輯部分復用改成了能夠縱向垂直的邏輯。
動態(tài)刷新數(shù)據(jù)時不能夠成功讓pageradapter數(shù)據(jù)增加,并且在滑動到pageradapter中 size臨界大小的時候,報空指針異常。
查看自己變更的源碼發(fā)現(xiàn),問題出在沒有DataSetObserver,它為null,那么viewpager和pagerAdapter更新數(shù)據(jù)的橋梁也就斷了。
產(chǎn)生問題的原因是由于,新定義的viewpager和pagerAdapter不在一個包中,而關(guān)鍵的綁定二者的方法 setViewPagerObserver也就不能直接調(diào)用了,所以DataSetObserver為null。當時采用的是反射的方式調(diào)用關(guān)聯(lián)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();
}
斷點調(diào)試發(fā)現(xiàn)總是走到了 NoSuchMethodException的部分。
所以重新查看了官方文檔的API,發(fā)現(xiàn)了 registerDataSetObserver 方法。
將 Method method = aClass.getMethod("setViewPagerObserver"); 改為下面這句
Method method = aClass.getMethod("registerDataSetObserver", DataSetObserver.class);
即可成功調(diào)用了。
/**
* 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?
斷點發(fā)現(xiàn)能夠成功傳遞數(shù)據(jù)。而界面UI卻并不能夠及時更新。
原因就是重新回到界面時,控件尚未被綁定就傳遞進了數(shù)據(jù)。數(shù)據(jù)就先于控件了。
6. Realm數(shù)據(jù)庫報錯情況
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);
}
}
});
}