這些年,我爬過的 Android 坑 | 持續更新

總結目錄

  • 視圖篇java

    • 如何理解非主線程能夠更新UI
    • dialogFragment 全屏時左右留空的解決方案
    • dialogFragment 全屏時狀態欄出現黑色佈局的解決方案
    • dialogFragment 全屏時狀態欄出現黑色佈局的解決方案
    • recyclerview 調用 notifyItemRemoved 方法移除某個 Item 以後 由於引用 position 引發 crash 的緣由
    • recyclerview 局部刷新Item時會由於默認動畫致使閃爍的解決方案
    • recyclerview 中的 item 出現莫名的偏移滾動
    • recyclerview 內容超過一屏時, findFistCompletelyVisibleItemPosition 會返回 -1 的緣由
    • textview 中富文本點擊事件攔截了長按事件的解決方案
    • 如何禁止 ViewPager 的滑動
    • 如何仿蘑菇街/馬蜂窩 Viewpager 裝載圖片以後切換時動態變動高度
    • 如何控制 appbarLayout 隨時定位到某個位置
    • 如何禁止 appbarLayout 滾動
    • edittext 未能響應 onClickListener 事件的解決方案
    • 使用 listview 或gridview 的處理 item 的 state_selected 事件是無效的解決方案
    • 解決5.0以上Button自帶陰影效果的方案
    • 針對 onSingleTapUp 和 onSIngleTapConfirmed 的使用區別
    • 如何使用layer-list畫三角形
    • 關於屬性動畫中旋轉 View 時部分機型出現 View 閃爍的解決方案
    • 關於 ConstraintLayout 的代碼佈局下的注意事項
    • TextView 在 6.0 版本下設置單行尾部縮略的坑
  • 服務篇linux

    • 後臺手動清理應用以後,service中啓動的notifications並無消失的解決方案
  • 線程篇android

    • 建議新起線程不要隨便調用網絡請求,通常的newThread沒有looper 隊列,參考handlerThread
  • 網絡篇git

    • Retorfit get 請求參數出現錯誤的解決方案
  • 數據篇github

    • 如何優雅處理 sqlite 多線程讀寫問題
    • 如何理解 Intent 傳遞數據出現 TransactionTooLargeException 的問題
  • 機型系統適配篇sql

    • 如何解決 NatigationBar 被 PopupWindow 遮擋的問題
    • 如何解決MIUI系統後臺沒法 toast 的問題
    • 如何解決關閉通知欄權限沒法彈出 toast 的問題
    • 如何適配 vivo 等雙面屏幕
    • 如何解決華爲設備產生太多 broadcast 致使crash的問題
    • 各類通知欄的適配方案
    • 解決針對魅族推送內容限制的問題
    • 解決從系統安裝起安裝應用後啓動,Home 隱藏後 Launcher 重複啓動的問題
    • 針對有launcher作爲Activity的應用,在徹底沒有啓動下收到第三方推送(小米,華爲,魅族)/分享拉起的注意事項
    • 針對 App 多場景拉起場景下的場景判斷分析
    • 9.0 android 支持明文鏈接(Http
  • 編譯構建篇數據庫

    • travis-ci 高版本androidO編譯遇到 license 沒經過編譯失敗的解決方案
    • Dalvik 支持的 android 版本下進行分包執行會有一些限制
    • Dalvik 分包構建每個 dex 文件時可能出現 java.lang.NoClassDefFoundError
    • Java 8 methods of java.lang.Long and java.lang.Character are not desugared by D8
    • databinding 中 findBinding vs getBinding 的場景區別
    • 版本構建出現 Gradle sync failed: Cannot choose between the following configurations of project
    • gradle 配置本地離線包
    • 解決kvm/jvm 編譯時 -classpath 遇到的分割及空格的問題
    • databinding NoSuchMethodError with buildTool 3.4.0
  • 版本控制篇後端

    • git 修改 commit 記錄
    • 解決git ignore 文件不生效的問題
  • 其餘安全

    • ExoPlayer在接聽電話以後會致使原來設置的 Source 中靜音狀態消失了致使可能返回 app 續播的時候視頻忽然有聲音
    • AndroidStudio 提示 Please select Android SDK
    • 關於 Java 中字符與字節的編碼關係認識
    • 關於 emoji 編碼的長度計算問題

<<視圖篇>>

  • 如何理解非主線程能夠更新UI

谷歌在 viewRootImpl 中檢查更新ui的線程服務器

void checkThread() {  
    if (mThread != Thread.currentThread()) {  
        throw new CalledFromWrongThreadException(  
                "Only the original thread that created a view hierarchy can touch its views.");  
    }  
}

在執行onCreate的時候這個判斷並無執行到

  • dialogFragment 全屏時左右留空的解決方案

在 fragment#onResume 中從新調整 window 佈局

<item name="android:windowIsFloating">true</item>

此時 window 爲 wrap_content,若是出現左右空白,則考慮使用上個問題的方案。

  • recyclerview 調用 notifyItemRemoved 方法移除某個 Item 以後由於引用 position 引發 crash 的緣由notifyItemRemoved方法並不會移除列表的數據源的數據項致使數據源中的數據與列表Item數目不一致,須要同步刷新數據源。
  • recyclerview 局部刷新Item時會由於默認動畫致使閃爍的解決方案

由於recyclerview存在ItemAnimator,且在刪除/更新/插入Item時會觸發,可設置不支持該動畫便可。

((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
  • recyclerview 中的 item 出現莫名的偏移滾動

這個問題通過定位存在於 viewholder 中的某個 view 可能提早獲取到焦點。 同時在。alibaba-vlayout 庫中也發現有人反饋改問題。 issues-255 解決的方法是在 Recyclerview中外層父佈局中添加 android:descendantFocusability="blocksDescendants" 用於父佈局覆蓋 Recyclerview 優先搶佔焦點。

  • recyclerview 內容超過一屏時,findFistCompletelyVisibleItemPosition 會返回 -1 的緣由

緣由是在 findOneVisibleChild 計算出來的 start 和 end 已經超過了 reclclerview 的 start 和 end.通過研究源碼獲得如下。

findFirstCompletelyVisibleItemPosition -> -1
findLastCompletelyVisibleItemPosition -> -1
findFirstVisibleItemPosition -> 正常
findLast

textview 中富文本點擊事件攔截了長按事件的解決方案

這個問題常見於消息列表中,某條消息使用了ClickableSpan用於處理富媒體的點擊事件,同時這個消息又須要支持長按複製。因爲LinkMovementMethod方法在onTouchEvent一直返回true,能夠經過自定義View.onTouchListener來替換setMovenmentMethod達到效果。
 

public class ClickMovementMethod implements View.OnTouchListener {
private LongClickCallback longClickCallback;
 
public static ClickMovementMethod newInstance() {
    return new ClickMovementMethod();
}
 
@Override
public boolean onTouch(final View v, MotionEvent event) {
    if (longClickCallback == null) {
        longClickCallback = new LongClickCallback(v);
    }
 
    TextView widget = (TextView) v;
    // MovementMethod設爲空,防止消費長按事件
    widget.setMovementMethod(null);
    CharSequence text = widget.getText();
    Spannable spannable = Spannable.Factory.getInstance().newSpannable(text);
    int action = event.getAction();
    if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        x -= widget.getTotalPaddingLeft();
        y -= widget.getTotalPaddingTop();
        x += widget.getScrollX();
        y += widget.getScrollY();
        Layout layout = widget.getLayout();
        int line = layout.getLineForVertical(y);
        int off = layout.getOffsetForHorizontal(line, x);
        ClickableSpan[] link = spannable.getSpans(off, off, ClickableSpan.class);
        if (link.length != 0) {
            if (action == MotionEvent.ACTION_DOWN) {
                v.postDelayed(longClickCallback, ViewConfiguration.getLongPressTimeout());
            } else {
                v.removeCallbacks(longClickCallback);
                link[0].onClick(widget);
            }
            return true;
        }
    } else if (action == MotionEvent.ACTION_CANCEL) {
        v.removeCallbacks(longClickCallback);
    }
 
    return false;
}
 
private static class LongClickCallback implements Runnable {
    private View view;
 
    LongClickCallback(View view) {
        this.view = view;
    }
 
    @Override
    public void run() {
        // 找到可以消費長按事件的View
        View v = view;
        boolean consumed = v.performLongClick();
        while (!consumed) {
            v = (View) v.getParent();
            if (v == null) {
                break;
            }
            consumed = v.performLongClick();
        }
    }
}
}
 
textView.setOnTouchListener(ClickMovementMethod.newInstance());
  • 如何仿蘑菇街/馬蜂窩 Viewpager 裝載圖片以後切換時動態變動高度

imageViewPager 爲普通的 Viewpager 對象

imageListInfo爲存放圖片信息的list,imageShowHeight爲業務須要顯示高度,經過切換時動態計算調整

imageViewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                imageViewPager.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                //根據viewpager的高度,拉伸顯示圖片的寬度調整高度。
                ViewGroup.LayoutParams layoutParams = imageViewPager.getLayoutParams();
                layoutParams.height = imageListInfo.imageShowHeight[0];
                imageViewPager.setLayoutParams(layoutParams);
            }
        });
        imageViewPager.setAdapter(imagePagerAdapter);
        imageViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (position == imageListInfo.getImageListSize() - 1) {
                    return;
                }
                int height = (int) (imageListInfo.imageShowHeight[position] * (1 - positionOffset) + imageListInfo.imageShowHeight[position + 1] * positionOffset);
                ViewGroup.LayoutParams params = imageViewPager.getLayoutParams();
                params.height = height;
                imageViewPager.setLayoutParams(params);
            }
 
            @Override
            public void onPageSelected(int position) {
                if (!clickListBySelf) {
                    toSelectIndex(imageListInfo.selected, position);
                }
            }
 
            @Override
            public void onPageScrollStateChanged(int state) {
 
            }
        });
如何控制 appbarLayout 隨時定位到某個位置
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
    @Override
    public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
        return false;
    }
});
  • edittext 未能響應 onClickListener 事件的解決方案

Edittext監聽未獲取焦點的Edittext的點擊事件,第一次點擊觸發OnFocusChangeListener,在獲取焦點的狀況下才能響應onClickListener

  • 使用 listview 或gridview 的處理 item 的 state_selected 事件是無效的解決方案

在xml佈局中對listview或gridview設置Android:choiceMode="singleChoice",並使用state_activated狀態來代替state_selected狀態。(2016.12.10)

  • 解決5.0以上Button自帶陰影效果的方案

在xml定義的Button中,添加如下樣式定義 

  • 針對 onSingleTapUp 和 onSIngleTapConfirmed 的使用區別

前者在按下並擡起時發生,後者有一個附加條件時Android會確保點擊以後在短期內沒有再次點擊纔會觸發。經常使用於若是須要監聽單擊和雙擊事件。

  • 如何使用layer-list畫三角形
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
//左
<item>
    <rotate
        android:fromDegrees="45"
        android:pivotX="85%"
        android:pivotY="135%">
        <shape android:shape="rectangle">
            <size
                android:width="16dp"
                android:height="16dp" />
            <solid android:color="#7d72ff" />
        </shape>
    </rotate>
 
</item>
 
//右
<item>
    <rotate
        android:fromDegrees="45"
        android:pivotX="15%"
        android:pivotY="-35%">
        <shape android:shape="rectangle">
            <size
                android:width="16dp"
                android:height="16dp" />
            <solid android:color="#7d72ff" />
        </shape>
    </rotate>
 
</item>
 
//上/正
<item>
    <rotate
        android:fromDegrees="45"
        android:pivotX="-40%"
        android:pivotY="80%">
        <shape android:shape="rectangle">
            <size
                android:width="16dp"
                android:height="16dp"/>
            <solid android:color="#7d72ff"/>
        </shape>
    </rotate>
</item>
 
//下
<item>
    <rotate
        android:fromDegrees="45"
        android:pivotX="135%"
        android:pivotY="15%">
        <shape android:shape="rectangle">
            <size
                android:width="16dp"
                android:height="16dp"/>
            <solid android:color="#7d72ff"/>
        </shape>
    </rotate>
</item>
  • 關於屬性動畫中旋轉 View 時部分機型出現 View 閃爍的解決方案

在大神 app 信息流快捷評論模塊中,在交付快捷評論動畫的時候發現,使用屬性動畫實現的抖動效果在部分機型上出現閃爍。而咱們的實現抖動效果是經過 View.ROTATION 來實現的。通過研究,部分機型由於硬件加速的緣由致使的。爲動畫 view 進行如下設置

view.setLayerType(View.LAYER_TYPE_HARDWARE,null);
  • 關於 ConstraintLayout 的代碼佈局下的注意事項

不一樣於其餘 ViewGroup 控制子 View 的排版,ConstraintLayout 須要構建 ConstraintSet 對象來粘合。 在手動添加子 View 的場景下,能夠經過 ConstraintSet#clone(ConstraintLayout constraintLayout) 來克隆當前已有 ConstraintLayout 的排版信息,而後最後調用 ConstraintSet#applyTo(ConstraintLayout constraintLayout) 確認最終的排版信息。
TextView 在 6.0 版本下設置單行尾部縮略的坑

  • 在大神信息流中,有一些卡片信息須要設置單行縮略。在 MTL 兼容測試過程當中發現有一些機型顯示異常,通過概括及校驗,這部分機型的版本都是 < 6.0。 經過在 stackoverflow 也找到了相同的問題場景 text ellipsize behavior in android version < 6.0 . 針對這部分版本的手機,咱們須要在設置單行的時候把 android:maxLines="1" 改爲 android:singleLine="true"。即便 IDE 提示該 API 已通過期了!

<<服務篇>>

  • 後臺手動清理應用以後,service中啓動的notifications並無消失的解決方案

從 How to remove all notifications when an android app (activity or service) is killed? 的諸多討論中學習到, Service#onTaskRemoved 是咱們的App被清理以後Service的回調。嘗試過一下方法並不能達到清除的效果。

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);
    NotificationManager nManager = ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE));
    nManager.cancelAll();
}

在線上應用中,因爲咱們的通知相似於將軍令這種有定時更新的功能,須要完全乾掉全部serivce承載的功能,下面方法可行

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);
    stopSelf();
    stopForeground(true);
}

<<線程篇>>

  • 建議新起線程不要隨便調用網絡請求,通常的newThread沒有looper隊列,參考handlerThread

<<網絡篇>>

  • Retorfit get 請求參數出現錯誤的解決方案
@GET( BASE_URL + "index/login" )
Observable< LoginResult > requestLogin( @QueryMap(encoded = true) Map< String, String > params );
 
final Map< String, String > paramsMap = new ParamsProvider.Builder().
        append( "username", account ).
        append( "password",URLEncoded(password) ).
  • 好比登錄,encode = true 表示未對特殊字符進行url編碼,默認是false。

<<數據篇>>

  • 如何優雅處理 sqlite 多線程讀寫問題

    • 一個helper實例對應一個 db connectton,這個鏈接能提供讀鏈接和寫鏈接,若是隻是調用 read-only,則默認也會有寫鏈接。
    • 一個helper實例能夠在多個線程中使用,java層會使用鎖機制保證線程同步,哪怕有100個線程,對數據度的調用也會被序列化
    • 若是嘗試從不一樣 connection 同時對數據庫進行寫操做,則有一個會失敗。並不會按照第一個寫完再輪到第二個寫,有一些sqlite版本甚至不會有錯誤提示。

通常而言,若是要在多線程環境下使用數據庫,則確保多個線程中使用的是同一個SQLiteDataBase對象,該對象對應一個db文件。

特殊狀況,若是多個 SQLiteDataBase 打開同一個 db 文件,同時使用不一樣線程同時寫(insert,update,exexSQL)會致使在 SQLiteStatement.native_execute 方法時可能致使異常。這個異常來自本地方法裏面,僅僅在Java對有對 SQLiteDataBase 進行同步鎖保護。可是多線程讀(query)返回的事 SQLiteCursor保存查詢條件並無馬上執行查詢,僅僅在須要時加載部分數據,能夠多線程不一樣 SQLiteDataBase 進行讀。

若是要處理上述問題,可使用 「一個線程寫,多個線程同時讀,每一個線程都用各自SQLiteOpenHelper。」

在android 3.0版本以上 打開 enableWriteAheadLogging。當打開時,它容許一個寫線程與多個讀線程同時在一個SQLiteDatabase上起做用。實現原理是寫操做實際上是在一個單獨的文件,不是原數據庫文件。因此寫在執行時,不會影響讀操做,讀操做讀的是原數據文件,是寫操做開始以前的內容。在寫操做執行成功後,會把修改合併會原數據庫文件。此時讀操做才能讀到修改後的內容。可是這樣將花費更多的內存。

  • 如何理解 Intent 傳遞數據出現 TransactionTooLargeException的問題

Intent 傳輸數據的機制中,用到了 Binder。Intent 中的數據,會做爲 Parcel 被存儲在 Binder 的事務緩衝區(Binder transaction buffer)中的對象進行傳輸.而這個 Binder 事務緩衝區具備一個有限的固定大小,當前爲 1MB。你可別覺得傳遞 1MB 如下的數據就安全了,這裏的 1MB 空間並非當前操做獨享的,而是由當前進程所共享。也就是說 Intent 在 Activity 間傳輸數據,自己也不適合傳遞太大的數據.

參考阿里 《Android 開發者手冊》 對於Activity間數據通信數據較大,避免使用Intent+Parcelable的方式,能夠考慮使用EventBus等代替方案,避免 TransactionTooLargeException。EventBus使用黏性事件來解決,可是針對Activity重建又能拿到Intent而EventBus則不能夠,因此須要根據業務來調整。

<<機型系統適配篇>>

  • 如何解決 NatigationBar 被 PopupWindow 遮擋的問題
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
  • 如何解決MIUI系統後臺沒法 toast 的問題

參考 github.com/zhitaocai/T… 項目,可是在小米3或者小米Note(4.4.4)手機上

mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);

mContext 須要使用 ApplicationContext 才能生效。

  • 如何解決關閉通知欄權限沒法彈出 toast 的問題

因爲谷歌把 Toast 設置爲系統消息權限,能夠參考 Android關閉通知消息權限沒法彈出Toast的解決方案 維護本身的消息隊列.

  • 如何適配 vivo 等雙面屏幕

在 AndroidManifest.xml 中聲明一下 meta-data

<meta-data
android:name="andriod.max_aspect" android:value="ratio_float"/>
  • 或者使用 android:maxAspectRatio="ratio_float"(API LEVEL 26) ratio_float 通常爲屏幕分辨率高寬比。 其餘好比凹槽區域,圓角切割等問題能夠參考市面上最新的vivo機型對應的 vivo開放平臺 文檔。
  • 如何解決華爲設備產生太多 broadcast 致使crash的問題

因爲部分華爲中,若是app註冊超過500個BroadcastReceiver就會拋出 「 Register too many Broadcast Receivers 」 異常。經過分析發現其內部有一個白名單,本身能夠經過建立一個新的app,使用微信包名進行測試,發現並無這個限制。經過反射 LoadedApk 類拿到 mReceiverResource 中的 mWhiteList 對象添加咱們的包名就能夠了。 能夠參考 github.com/llew2011/Hu… 這個項目。

  • 各類通知欄的適配方案

參考 網易考拉實現的適配方法

  • 解決針對魅族推送內容限制的問題

今天收到魅族渠道的警報稱「推送內容可能過長」。IM功能針對離線設備走設備商的推送,魅族推送限制了title標題1-32字符,content內容1-100字符。若是頻繁推送超過限制的通知,魅族推送服務器可能不會下發推送到魅族設備。故服務端限制發送到魅族服務器的消息標題和內容長度解決。

  • 解決從系統安裝起安裝應用後啓動,Home 隱藏後 Launcher 重複啓動的問題

判斷啓動頁面是不是根節點(推薦)

if(!isTaskRoot()){
    finish();
    return 
}

或者判斷Activity是否多了 FLAG_ACTIVITY_BROUGHT_TO_FRONT ,這個tag是該場景緻使的

if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
        finish();
        return;
}

針對有launcher作爲Activity的應用,在徹底沒有啓動下收到第三方推送(小米,華爲,魅族)/分享拉起的注意事項

因爲咱們的應用LauncherActivity用於分發不一樣場景的入口,A邏輯進入特殊場景頁面A,B邏輯進入主頁面B。

  • onCreate中優先攔截 intent 判斷拉起參數,若是有拉起參數則直接進入主頁面B,intent交付給主頁面B處理
  • 部分場景下,好比第三方消息推送,華爲和小米拉起閃屏或 launcher intent沒法區分,針對該作法是,限定進入閃屏/launcher的邏輯,剩餘場景統一進入主頁面B
if (後端控制是否須要進入特殊場景頁面) {
    boolean goToA = false;
        if (getIntent() != null) {
    String action = getIntent().getAction();
    Set category = getIntent().getCategories();
        if (TextUtils.equals(action, "android.intent.action.MAIN")) {
            if (category != null && category.contains("android.intent.category.LAUNCHER"))             {
        Intent intent = new Intent(this, 頁面A.class);
        intent.setData(getIntent().getData());
        startActivity(intent);
        goToA = true;
        }
    }
}
    if (! goToA) {
        goToMainActivity();
    }
} else {
    goToMainActivity();
}
  • 針對 App 多場景拉起場景下的場景判斷分析

可參考我另外一篇文章 對線上項目拉起應用場景的思考總結

  • 9.0 android 支持明文鏈接(Http)

Android 9(API級別28)開始,默認狀況下禁用明文支持

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        ...
        android:usesCleartextTraffic="true"
        ...>
        ...
    </application>
</manifest>

<<編譯構建篇>>

  • travis-ci 高版本androidO編譯遇到 license 沒經過編譯失敗的解決方案

參考 CI 討論區 添加 dist: precise 及 before_install 項中新增 sdkmanager指令。具體可參考個人 開源項目配置

  • Dalvik 支持的 android 版本下進行分包執行會有一些限制

    • 冷啓動時須要安裝dex文件,若是dex文件太大則可能致使處理時間太長致使 ANR
    • 即便使用 multiDex 方案在低於 4.0 系統上可能會出現 Dalvik linearAlloc 的bug,這是由於該方案須要申請一個很大的內存,運行時可能的致使程序崩潰。這個限制在 4.0 上雖然有所改善了,可是仍是可能在低於 5.0 的機器上觸發。
  • Dalvik 分包構建每個 dex 文件時可能出現 java.lang.NoClassDefFoundError

這個問題的緣由是構建工具繪製行比較複雜決策來肯定主 dex 文件中須要的類以便應用可以正常的啓動。若是啓動期間須要的任何類在主 dex 中未能找到,則會拋出上述異常。全部必需要 multiDexKeepFile 或 multiDexKeepProguard 屬性中聲明他們,手動將這些類指定爲主 dex 文件中的必需項。

建立 multidex-new.txt文件,寫入如下新增的類

com/example/Main2.class
com/example/Main3.class

建立 meltidex-new.pro,寫入如下 keep 住的類

-keep class com.example.Main2
-keep class com.example.Main3

而後在gradle multiDexKeepFile屬性 和 multiDexKeepProguard屬性聲明上述文件

android {
buildTypes {
    release {
        multiDexKeepFile file 'multidex-new.txt'
        multiDexKeepProguard 'multidex-new.pro'
        ...
    }
}
}
  • Java 8 methods of java.lang.Long and java.lang.Character are not desugared by D8

這個問題出如今使用 Kotlin 編譯時,從 Kotlin1.3.30 版本開始 ndroid.compileOptions中的Java版本推斷出JVM目標,若是同時設置了sourceCompatibility和targetCompatibility,則選擇「1.8」到那個或更高. 能夠經過指定 JavaVersion 1.6 來解決這個問題。

sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
  • Issue 中表示,AGP(Android Gradle Plugin)3.4 已解決脫糖問題,可嘗試升級解決。
  • databinding 中 findBinding vs getBinding 的場景區別

不一樣之處在於,findBinding將遍歷父節點,而若是使用getBinding時當view不是跟節點會返回null。

  • 版本構建出現 Gradle sync failed: Cannot choose between the following configurations of project

參考 issues 的回答

If you're using Android plugin for Gradle 3.0.0 or higher, the plugin automatically matches each variant of your app with corresponding variants of its local library module dependencies for you. That is, you should no longer target specific variants of local module dependencies, show as below
dependencies {
// Adds the 'debug' varaint of the library to the debug varaint of the app
debugCompile project(path: ':my-library-module', configuration: 'debug')
 
// Adds the 'release' varaint of the library to the release varaint of the app
releaseCompile project(path: ':my-library-module', configuration: 'release')
}
  • gradle 配置本地離線包

    1. 離線下載 gradle 離線包保存在 url 中
    2. 修改 gradle/wrapper/gradle-wrapper.properties 調整 distributionUrl 目錄指向 url
    3. 修改 build.gradle classpath 版本映射 gradle 版本
  • 解決kvm/jvm 編譯時 -classpath 遇到的分割及空格的問題

linux/mac OS 上使用 「:」 分割多個classpath路徑,window使用 「;」 分割。

若是linux/mac OS 路徑存在空格,暫時避免,使用多種方式嘗試未果=。=。

  • databinding NoSuchMethodError with buildTool 3.4.0

項目從 gradle 3.1 升級到 3.4.0 並使用了 androidx 以後,發現編譯失敗了。來項目就是使用 databinding,編譯出現了

java.lang.NoSuchMethodError: No direct method <init>
(Landroidx/databinding/DataBindingComponent;Landroid/view/View;I)V in 
class Landroidx/databinding/ViewDataBinding; or its super classes
(declaration of 'androidx.databinding.ViewDataBinding'

緣由咱們使用的 aar 庫中使用了舊版本 gradle 編譯,新版本主端 gradle 升級了,致使舊的 ViewDataBinding 構造器簽名匹配不上新版 androidx.databinding.ViewDataBinding 的簽名。

//舊版本
protected ViewDataBinding(DataBindingComponent bindingComponent, View root, int localFieldCount)
//新版本
protected ViewDataBinding(Object bindingComponent, View root, int localFieldCount)
  • 幸運的是,3.4.1已經修復了。更改 3.4.0 -> 3.4.1 就能夠了。

<<版本控制篇>>

  • git 修改 commit 記錄
git reset --soft HEAD^
 
撤銷當前的commit,若是隻是修改提示,則使用
git commit --amend
  • 解決git ignore 文件不生效的問題
git rm -r --cached .
git add .
git commit -m 'update .gitignore'

<<其餘>>

  • ExoPlayer在接聽電話以後會致使原來設置的 Source 中靜音狀態消失了致使可能返回 app 續播的時候視頻忽然有聲音

緣由是多媒體焦點被通話搶奪以後播放音量被充值,解決方法可參考 github.com/google/ExoP…

  • AndroidStudio 提示 Please select Android SDK

解決手段: File->Project Structure中修改Build tools version

  • 關於 Java 中字符與字節的編碼關係認識
unicode編碼下1箇中文字符或英文字符都佔2個字節;
GBK編碼下測試:
「java測試」.length() 返回 6,「GBK測試」.getBytes().length() 返回 8
總結:1箇中文字符佔2個字節  1個英文字符佔1個字節
utf-8編碼下測試:
「java測試」.length() 返回 6,「GBK測試」.getBytes().length() 返回 10
總結:1箇中文字符佔3個字節  1個英文字符佔1個字節
utf-16編碼下測試:
「java測試」.length() 返回 6,「GBK測試」.getBytes().length() 返回 14
總結:1箇中文字符佔3個字節  1個英文字符佔2個字節
utf-32編碼下測試:
「java測試」.length() 返回 6,「GBK測試」.getBytes().length() 返回 24
總結:1箇中文字符或英文字符都佔4個字節
<h4 id="9-4"> 關於 emoji 編碼的長度計算問題 </h4>

重點熟悉下 Unicode 編碼標識的 emoji 下針對多平面 emoji 的拆分邏輯。可參考這篇文章

相關文章
相關標籤/搜索