1. 程式人生 > >記錄自己開發中踩過的一些坑

記錄自己開發中踩過的一些坑

如題,進以此來記錄日常開發中遇到的一些坑,近期抽空整理一下並長期更新~~
排名不分先後,隨踩隨記~

1.部分手機App喚起第三方支付(微信/支付寶)不成功

以支付寶為例,環境為華為Mate7 EMUI4.0(Android6.0)系統,體驗發現程式碼流程正常,支付寶卻未啟動正常的支付介面,其他手機正常,想到Android6.0新的許可權管理方案,於是檢視許可權管理髮現支付寶的許可權中 關聯啟動 一項未被授予,手動開啟這項許可權後正常。
本以為加上提示或者跳轉告訴使用者去開啟支付寶的關聯啟動項就OK了,但是測試同學說美團App在同樣的環境下不需要手動開啟那項許可權依然可以正常喚起支付寶寶,這TM就很尷尬了。最後通過檢視支付寶官方最新整合文件並提問支付寶技術支援得到一個半肯定的回答,因為我們使用的支付寶SDK版本太老了,影響正常使用。專案中支付寶SDK中還是用的AliPay喚起的支付寶,這至少也是2年前的SDK版本了,不知道為什麼一直沒有更新,可能是抱著不出問題就不換的原則。通過demo測試確實和支付寶SDK版本有關, 經過替換最新版的支付寶SDK後驗證一切正常。

2.H5互動相關

//java.lang.Throwable: A WebView method was called on thread ‘JavaBridge’. All WebView methods must be called on the same thread
1.與H5互動的互動中標註@JavascriptInterface的函式可被javaScript呼叫 但並不在Android主執行緒呼叫
所以此函式中不可進行UI操作或對WebView的操作
2.與H5互動的互動中標註@JavascriptInterface的函式命名為getUserId()與API衝突 在部分手機中出現許可權報錯(華為Mate10by8.0),不可用getUserId命名與H5互動的函式

3.//專案正式簽名打包時報錯mulit define錯誤

一般為依賴庫重複引用衝突導致 以retrofit為例,retrofit會捆綁依賴okhttp
當其它lib中也有okhttp時會衝突(阿里雲檔案上傳SDK需依賴okhttp),刪掉lib中的okttp即可
可通過命令列檢視app所有依賴庫的lib樹結構,具體命令百度

4//QQ分享成功後提示分享取消

1同時注意這裡的APPid需要替換成你程式碼裡配置的APPid
PlatformConfig.setQQZone(“100424468”, “c7394704798a158208a74ab60104f0ba”);
這兩處的APPid應該是一致的,同時注意不要刪掉tencent字首!!!!
2注意實現onActivityresult方法
mShareAPI.onActivityResult(requestCode, resultCode, data);

5.//相機拍照機相簿選擇的開發相關

呼叫系統相機拍照獲取圖片分2種情況,如果啟動相機時指定了Uri,則相機拍照結果會儲存在該Uri下,並且onActivityResult中
的data返回為null 。如果啟動相機時未指定Uri,則onActivityResult中data會返回照片縮略的Bitmap物件=data.getParcelableExtra(“data”)

6.RecyclerView常見問題解決方案,RecyclerView巢狀自動滾動,RecyclerView 高度設定wrap_content 無作用等問題。轉自https://www.cnblogs.com/xgjblog/p/8260061.html

1,ScrollView或者RecyclerView1 巢狀RecyclerView2 進入頁面自動跳轉到recyclerView2上面頁面會自動滾動
貌似是RecyclerView 自動獲得了焦點
兩種解決辦法
一,recyclerview去除焦點
recyclerview.setFocusableInTouchMode(false);
recyclerview.requestFocus();
二,在程式碼裡面 讓處於ScrollView或者RecyclerView1 頂端的某個控制元件獲得焦點即可
比如頂部的一個textview
tv_goodsName.setFocusableInTouchMode(true);
tv_goodsName.requestFocus();

2,RecyclerView 高度設定wrap_content 無作用,RecyclerView 高度適中鋪滿全屏的bug
解決方案:
這是RecyclerView相容包的bug,23.2.0後官方已經修復了。
所以直接在gradle裡設定用23.2.0及以上的RecyclerView:
compile ‘com.android.support:recyclerview-v7:23.2.0’
或者全部升級
api ‘com.android.support:appcompat-v7:25.3.0’
api ‘com.android.support:support-v13:25.3.0’
api ‘com.android.support:design:25.3.0’

3,RecyclerView 條目佈局寬度設定match_parent無效果的問題解決
//這裡為了解決recycleview不能撐滿全屏的問題,這裡layoutManager不管你佈局裡是否設定,都不準確,所以需要在程式碼裡
//重新設定MATCH_PARENT
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()) {
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
};
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
xrecyclerview.setLayoutManager(layoutManager);

7.Can not perform this action after onSaveInstanceState異常處理

1.多數場景為在Activity中處理Fragment事務操作,如

        FragmentTransaction ft=getSupportFragmentManager().beginTransaction();
        ....
        ft.commit();  //改為呼叫commitAllowingStateLoss()函式即可

2.少數場景為某些任務呼叫了當前Activity的finish()函式,當用戶手動按下回退鍵執行onBackPress()時也會丟擲這種異常,解決方法:

if (!isFinishing()) {  //需要重寫onBackPress()函式避免重複退棧操作
    super.onBackPressed();
}

3.原因分析,因為activity在銷燬前會呼叫onSaveInstanceState()儲存資料。然檢視原始碼FragmentManager中有一個checkStateLoss()函式如下,這個函式在Fragment退棧和commit()操作時都會被呼叫來檢查狀態,原始碼如下:

    //BackStackState類中原始碼
    public int commit() {   //場景1中的ft.commit()呼叫實際最終由BackStackState的commit函式處理
        return commitInternal(false);
    }
    public int commitAllowingStateLoss() {
        return commitInternal(true);
    }

    int commitInternal(boolean allowStateLoss) { //最終都進到該函式中交由FragmentManager物件執行enqueueAction函式
        ....
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

    //FragmentManager類中原始碼
    public void enqueueAction(Runnable action, boolean allowStateLoss) {
        if (!allowStateLoss) {  //可以看到普通的commit操作時allowStateLoss為false,才會執行checkStateLoss()函式,
        //如果此時activity已經被銷燬或者說onSaveInstanceState已經執行,那麼在checkStateLoss()中就會丟擲異常
            checkStateLoss();
        }
        ...
    }

     //FragmentManager類中原始碼checkStateLoss()
    private void checkStateLoss() {
        if (mStateSaved) {  //mStateSaved在onSaveInstanceState之後會被置為true
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        ...
    }

場景2中原因類似,同樣是因為onBackPress()函式中先執行FragmentManager的退棧操作popBackStackImmediate()函式,popBackStackImmediate()函式的第一步就是呼叫checkStateLoss()檢查狀態,可自行閱讀。