日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Weekly Notes Issue #220

發(fā)布時間:2024/4/17 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Weekly Notes Issue #220 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Android Weekly Issue #220

August 28th, 2016
Android Weekly Issue #220

ARTICLES & TUTORIALS

Manage dependencies versions with gradle extra properties

依賴管理的小Tip: 把依賴的版本號作為變量管理.
改造之后, build.gradle文件變成這樣:

apply plugin: 'com.android.application' android {... } ...ext {supportLibraryVersion = '23.4.0'playServicesVersion = '9.2.1' }dependencies {// support librariescompile "com.android.support:appcompat-v7:$supportLibraryVersion"compile "com.android.support:design:$supportLibraryVersion"compile "com.android.support:percent:$supportLibraryVersion"compile "com.android.support:cardview-v7:$supportLibraryVersion"compile "com.android.support:gridlayout-v7:$supportLibraryVersion"//play servicescompile "com.google.android.gms:play-services-location:$playServicesVersion"compile "com.google.android.gms:play-services-gcm:$playServicesVersion"// other dependencies... }

定義了版本號變量, 原來hardcode時的單引號變成了雙引號, 然后用$符號取變量值.

上面這個是app module里面使用的例子, 如果你的應(yīng)用有多個module怎么辦呢?
當然一種辦法是每個module里定義一組版本號變量, 更方便的辦法是在項目工程總目錄的build.gradle文件里定義變量.
可以在工程的build文件里寫

ext {// sdk and toolsminSdkVersion = 14targetSdkVersion = 23compileSdkVersion = 23buildToolsVersion = '23.0.2'// dependencies versionssupportLibraryVersion = '23.4.0'playServicesVersion = '9.2.1' }

也可以這樣定義:

project.ext.supportLibVersion = '24.0.0'

使用的時候可以這樣取值: $rootProject.supportLibraryVersion.
也可以省略前面的rootProject, 直接取$supportLibraryVersion

Android CI with Docker

作者講了他怎么用Docker搭建CI.

  • 環(huán)境:
    首先, CI需要Android環(huán)境(JDK 7&8, Android SDK, Gradle, Release keychain, google-services.json, etc).
    裝了這些環(huán)境之后, 需要保證他們在每一個CI實例上都是同步更新的.
    用了Docker之后, 更新環(huán)境的步驟變?yōu)?
    更新你的Dockerfile -> Push到版本管理系統(tǒng) -> CI會build新的image, 然后push到docker registry.

  • Build:
    docker run -v ./app:/opt/app docker-ci-android:latest gradle assembleRelease

  • Test:
    有兩種測試, 一種是單元測試, 只需要JVM; 另一種是UI或者功能測試, 需要Android.
    emulator會有一些問題: why
    所以你可能想要在更真實的機器上測試: STF提供了服務(wù), 你只需要用這個stf-client.

  • Deploy:
    部署用一些gradle的task就可以完成.
    fabric
    gradle-play-publisher

  • 后面還提到了一些擴展和問題.

    Bottom Sheets in Android

    BottomSheet是support library 23.2加入的, 是從底部滑上來的一個塊塊, 用來向用戶展現(xiàn)更多內(nèi)容.
    Support Library提供了:
    BottomSheetBehavior: 加在CoordinatorLayout的直接child view上, 然后在java代碼里get出來, 設(shè)置state控制其狀態(tài).
    有HIDE, COLLAPSED和EXPANDED三種狀態(tài), 分別對應(yīng)隱藏, 展開到指定高度(peekHeight)和完全展開.
    BottomSheetDialog:
    BottomSheetDialogFragment.
    Behaviour是給View加行為, 后面這兩種是更加模塊化的dialog, 狀態(tài)控制都一樣.

    這里推薦一下筆者自己的demo: AndroidDesignWidgetsSample
    再推薦一下這篇文章里面的Bottom Sheets部分: CodePath-Handling-Scrolls-with-CoordinatorLayout

    Certificate public key pinning using Retrofit 2

    SSL handshake, 交換了證書(Certificate), 這樣客戶端就可以通過證書來驗證服務(wù)器的身份.
    什么是Certificate public key pinning呢? 也叫作SSL pinning.

    把host name和public key關(guān)聯(lián)起來, 這個public key將用來和證書中的public key比較, 如果匹配了, 就證明你正在和正確的server通信.
    而直接pinning證書相比pinning public key更容易一些, 但是也有不好的地方, 如果網(wǎng)站(比如Google)經(jīng)常輪換證書(rotate its certificate), 你的應(yīng)用就也得經(jīng)常更新, 而這種情況一般證書里面的public keys是保持不變的.
    如何在Android中用Retrofit實現(xiàn)pinning呢?
    首先需要網(wǎng)站的public key的hash, 有很多獲取方法, 參見okhttp3-CertificatePinner.
    然后構(gòu)建CertificatePinner類對象, 加到OkHttpClient上.

    CertificatePinner certificatePinner = new CertificatePinner.Builder().add("api.github.com", "sha256/6wJsqVDF8K19zxfLxV5DGRneLyzso9adVdUN/exDacw=").build();final OkHttpClient client = httpBuilder.certificatePinner(certificatePinner).build();Retrofit retrofit = new Retrofit.Builder().baseUrl(END_POINT).addConverterFactory(GsonConverterFactory.create()).client(client).build();

    TLSv1.2從Android16+開始支持, 但是對于20+的設(shè)備默認是disabled的, 為了強制獲取支持, 可以繼承SSLSocketFactory, 強制設(shè)置為enabled, 代碼見原文吧.
    Github上有完整的代碼PublicKeyPinning
    作者最后還推薦了一個測試的工具mitmproxy.

    Isometric AnimatedVectorDrawable - Part 3

    作者繼續(xù)講了他如何構(gòu)建方塊地形圖的動態(tài)效果.
    一個AnimatedVectorDrawable的xml文件實際上是用來建立一個映射關(guān)系, 關(guān)聯(lián)objectAnimators和VectorDrawable上的獨立元素. 我們可以建立一個objectAnimator, 操縱我們的一塊元素的動畫效果.
    文中實現(xiàn)了讓方塊地形動起來的動畫效果.

    The many flavors of commit()

    FragmentTransaction的提交方法:
    support library的FragmentTransaction現(xiàn)在提供了四種不同的方法來commit一個transaction:
    commit()
    commitAllowingStateLoss()
    commitNow()
    commitNowAllowingStateLoss()
    這篇文章分析了這四個方法的不同.

    commit() vs commitAllowingStateLoss():
    用commit()提交有時候會遇到IllegalStateException, 說你在onSaveInstanceState()之后提交, 這里有另一個文章很好地分析了這個問題:Fragment Transactions & Activity State Loss
    commit()和commitAllowingStateLoss()在實現(xiàn)上唯一的不同就是當你調(diào)用commit()的時候, FragmentManger會檢查是否已經(jīng)存儲了它自己的狀態(tài), 如果已經(jīng)存了, 就拋出IllegalStateException.
    那么如果你調(diào)用的是commitAllowingStateLoss(), 并且是在onSaveInstanceState()之后, 你可能會丟失掉什么狀態(tài)呢?
    答案是你可能會丟掉FragmentManager的狀態(tài), 即save之后任何被添加或被移除的Fragments.
    舉例說明:
    1.在Activity里顯示一個FragmentA;
    2.然后Activity被后臺, onStop()和onSaveInstanceState()被調(diào)用;
    3.在某個事件觸發(fā)下, 你用FragmentB replace FragmentA , 使用的是 commitAllowingStateLoss().
    這時候, 用戶再返回應(yīng)用, 可能會有兩種情況發(fā)生:
    1.如果系統(tǒng)殺死了你的activity, 你的activity將會重建, 使用了上述步驟2保存的狀態(tài), 所以A會顯示, B不會顯示;
    2.如果系統(tǒng)沒有殺死你的activity, 它會被提到前臺, FragmentB就會顯示出來, 到下次Activity stop的時候, 這個包含了B的狀態(tài)就會被存下來.
    (上述測試可以利用開發(fā)者選項中的”Don’t Keep Activities”選項).
    那么你要選擇哪一種呢? 這就取決于你提交的是什么, 還有你是否能接受丟失.

    commit(), commitNow() 和 executePendingTransactions():
    使用commit()的時候, 一旦調(diào)用, 這個commit并不是立即執(zhí)行的, 它會被發(fā)送到主線程的任務(wù)隊列當中去, 當主線程準備好執(zhí)行它的時候執(zhí)行.
    popBackStack()的工作也是這樣, 發(fā)送到主線程任務(wù)隊列中去. 也即說它們都是異步的.

    但是有時候你希望你的操作是立即執(zhí)行的, 之前的開發(fā)者會在commit()調(diào)用之后加上 executePendingTransactions()來保證立即執(zhí)行, 即變異步為同步.
    support library從v24.0.0開始提供了 commitNow()方法, 之前用executePendingTransactions()會將所有pending在隊列中還有你新提交的transactions都執(zhí)行了, 而commitNow()將只會執(zhí)行你當前要提交的transaction. 所以commitNow()避免你會不小心執(zhí)行了那些你可能并不想執(zhí)行的transactions.

    但是你不能對要加在back stack中的transaction使用commitNow(), 即addToBackStack()和commitNow()不能同時使用.
    為什么呢?
    想想一下, 如果你有一個提交使用了commit(), 緊接著又有另一個提交使用了commitNow(), 兩個都想加入back stack, 那back stack會變成什么樣呢? 到底是哪個transaction在上, 哪個在下? 答案將是一種不確定的狀態(tài), 因為系統(tǒng)并沒有提供任何保證來確保順序, 所以系統(tǒng)決定干脆不支持這個操作.

    前面提過popBackStack()是異步的, 所以它同樣也有一個同步的兄弟popBackStackImmediate().

    所以實際應(yīng)用的時候怎么選擇呢?

  • 如果你需要同步的操作, 并且你不需要加到back stack里, 使用commitNow().
    support library在FragmentPagerAdapter里就使用了commitNow()來保證在更新結(jié)束的時候, 正確的頁面被加上或移除.
  • 如果你操作很多transactions, 并且不需要同步, 或者你需要把transactions加在back stack里, 那就使用commit().
  • 如果你希望在某一個指定的點, 確保所有的transactions都被執(zhí)行, 那么使用executePendingTransactions().
  • Break circular dependency with RxJava 用RxJava打破循環(huán)依賴.

    當你把代碼分成各個部分, 比如用MVP, 這些各個部分之間可能會有相互依賴, 比如View需要Presenter, Presenter也需要View.
    作者也沒有說雙向關(guān)聯(lián)有什么缺點, 但是他說RxJava可以把這種雙向的依賴改成單向的.
    作者的辦法是使用RxBinding把button的click事件變成一個Observable, 然后Presenter監(jiān)聽click這個Observable, 后面接一個flatMap, 里面發(fā)網(wǎng)絡(luò)請求, 得到結(jié)果之后再調(diào)用view的方法.
    這么一改以后View中就不需要再持有Presenter的引用了.
    舉這個例子, 最后是想說, 如果你想從A中調(diào)用B的異步方法, 你不用總是在A中保存一個B的引用, 你可以把A中的事件作為一個Observable. 這樣只需要B保存了A的引用就可以了.

    Asynchronous layout inflation 異步解析layout

    最近的support library revision 24中, Google的開發(fā)者在v4包中加入了一個新的輔助類AsyncLayoutInflater, 來實現(xiàn)布局的異步解析.

    我們現(xiàn)在常用的布局解析inflate方法都是同步的, 那什么時候需要異步地做這件事情呢?
    比如你想延遲加載布局中的一塊, 或者你想把布局解析作為用戶某個交互的一個響應(yīng). 這樣就可以用這個異步布局解析類, 保證了主線程在inflation進行的時候仍然可響應(yīng).
    怎么使用呢?
    首先, 在主線程創(chuàng)建對象AsyncLayoutInflater(this),
    用它inflate布局的時候第三個參數(shù)是一個OnInflateFinishedListener回調(diào).
    以前同步方法的第三個參數(shù)是一個boolean, 說布局是否需要attach到parent上, 現(xiàn)在沒有這個boolean參數(shù)了.
    當然, 使用異步解析也有缺點:

    • 父類方法generateLayoutParams()必須是線程安全的.
    • 被創(chuàng)建的所有View不能創(chuàng)建Handler,或者調(diào)用Looper.myLooper()方法.
    • 不支持設(shè)置LayoutInflater.Factory和LayoutInflater.Factory2
    • 不支持布局里有Fragment.
      如果我們要異步inflate的布局不能支持異步, inflate的過程將會自動轉(zhuǎn)化為在UI線程的解析.
      作者文中附有Kotlin的例子.

    Introduction to Automated Android Testing - Part 5

    系列文章的第五篇, 之前第四篇的時候?qū)懥薖resenter, 定義了V和P的接口, 本篇接著寫View接口的實現(xiàn).

    這里Presenter和View關(guān)聯(lián)作者寫了兩個attachView()和detachView()方法, 前者在Presenter構(gòu)造之后調(diào)用, 后者在Activity的onDestroy()里調(diào)用. 這里同時會unregister RxJava的subscriptions, 避免了內(nèi)存泄露的發(fā)生.

    作者在布局時用了ConstraintLayout, 關(guān)于這個layout的使用她有另一個blog
    另外作者還加了Toolbar上的SearchView, 到此, 作者的這個app就基本完成了.
    作者的代碼里還有一個Injection類, 用來提供retrofit的service, 即代碼中UserRepo的獲取, 在Presenter構(gòu)造時傳入.

    作者的代碼: GithubUsersSearchApp
    預(yù)告下一篇將會加入UI測試.

    DiffUtil is a must!

    support library 24.2.0推出了一個新的輔助類DiffUtil, 它是用來解決什么問題的呢?
    如果你的RecyclerView.Adapter第一次接收到了新的數(shù)據(jù), 這很簡單, 只需要將它們顯示出來, 但如果已經(jīng)有了數(shù)據(jù), 新的數(shù)據(jù)又來了, 這時候怎么做才是最好的呢?
    DiffUtil來了, 它就是專門為了解決RecyclerView的Adapter更新而設(shè)計的, 他可以計算出前后兩個list的不同, 然后返回一組更新操作, 把第一個list變?yōu)榈诙€list.
    DiffUtil需要知道你的兩個list的基本信息: 長度, 基本item的比較.
    DiffUtil.Callback是用來向DiffUtil提供這些基本信息的, 它是一個抽象類, 你需要繼承它, 然后覆寫里面的幾個方法. 它的構(gòu)造傳入了兩個待比較的list, 覆寫的方法主要是get它們的size, 比較它們的內(nèi)容.
    Callback里還有一個getChangePayload()方法, 它不是抽象的, 這個方法在areItemsTheSame() 返回true, 但是areContentsTheSame()返回false的時候被調(diào)用.
    這意味著我們的item還是之前的那個item,但是可能里面的字段變化了.
    這個方法的返回值即為兩個對應(yīng)item的diff, 基本來說, 這個方法返回的是為什么我們認為list變化了.
    文中的代碼例子返回了一個Bundle, 把compare不相等的字段都放進去了, 用的是new item的值.

    一旦我們寫好了這個Callback類, 剩下的事情就很簡單了, 我們只需要在新數(shù)據(jù)到來的時候計算一下diff, 然后更新.

    @ Override public void onNewProducts(List<Product> newProducts) {DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new ProductListDiffCallback(mProducts, newProducts));diffResult.dispatchUpdatesTo(mProductAdapter);}

    當然上面getChangePayload()返回的對象還得我們自己利用起來, 它會被DiffResult分發(fā)到Adapter.
    用的是notifyItemRangeChange(position, count, payload)方法, 傳到了Adapter的onBindViewHolder()方法, 我們判斷payload不為空時, 從里面拿出diff做更新.

    文檔里說DiffUtil對很大的數(shù)據(jù)集可能比較費時, 所以建議把計算放在后臺線程.

    作者還給出了一個RxJava的例子, 各種flatMap.

    DESIGN

    Diverse Device Hands
    Facebook的design資源, 很多拿著手機的手的照片.

    LIBRARIES & CODE

    unipiazza-android-twostepslogin

    一個實現(xiàn)兩步登錄的庫, 比如Google web登錄, Material Design.
    要用它的布局, 然后設(shè)置一些屬性, 還有UI交互事件的Listener.

    Om Recorder

    一個簡單的Pcm / Wav 錄音機, API簡單, 可以錄制Pcm和Wav音頻, 可以配置輸出, 有暫停功能.

    tiger

    又一個依賴注入庫, 但是README里說這不算一個Google的官方產(chǎn)品, 官方的是Dagger和Guice.
    這個tiger好像自稱是目前最快的java依賴注入.

    NEWS

    Taking the final wrapper off of Android 7.0 Nougat
    Android 7.0已經(jīng)問世了, 從Nexus開始, 同時API 24的source code已經(jīng)push到AOSP了.

    轉(zhuǎn)載于:https://www.cnblogs.com/mengdd/p/5829870.html

    總結(jié)

    以上是生活随笔為你收集整理的Android Weekly Notes Issue #220的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 一级国产精品 | 欧美男人又粗又长又大 | 97影院在线午夜 | 在线欧美一区 | 涩涩视频免费观看 | 国产中文一区二区三区 | 97精品一区二区三区 | 日本一级黄色 | 国产精品成人国产乱一区 | 日韩网站免费观看 | 97超碰人人澡人人爱学生 | 少妇被又大又粗又爽毛片久久黑人 | 国产综合第一页 | 日韩一二在线 | 亚洲区欧美区 | 国产123在线| 麻豆网站在线 | 日本二区在线观看 | 婷婷丁香九月 | av男人资源 | 青青草一区二区三区 | 99视频热| 一级久久久久久 | 久久免费手机视频 | 在线国产黄色 | 欧美性生活一区二区三区 | 亚洲熟女一区二区 | 在线播放无码后入内射少妇 | 中国黄色大片 | 成人精品免费在线观看 | 国产一线二线三线女 | 国产精品视频免费观看 | 强公把我次次高潮hd | 国产成人精品一区二区三区在线观看 | 亚洲午夜久久久 | 国产成人激情视频 | 国产午夜精品在线 | 成人三级在线看 | 中文幕无线码中文字夫妻 | 性色一区二区三区 | 绯色av一区二区 | 99re国产在线 | 日韩国产在线观看 | 成人区精品一区二区婷婷 | 第九色 | 日韩福利视频导航 | 这里只有精品在线观看 | 涩涩一区 | 日韩毛片在线视频 | 原神淫辱系列同人h | 波多野结衣在线 | 先锋影音av资源站 | 51久久久 | 天天综合网久久 | 亚洲精品无码久久久久 | 国产精品xxxxxx | 女同在线视频 | 亚洲九九视频 | 操操操插插插 | 色悠久久久| 超碰在线网站 | 国产毛片91 | 日韩经典第一页 | 中文字幕一区二区三区夫目前犯 | 日韩欧美中| 日韩在线免费观看视频 | 一本大道综合伊人精品热热 | www亚洲一区 | 精品视频成人 | 成人做爰视频www网站小优视频 | 999精品视频在线观看 | 五月婷在线 | www.久色| 成人久久国产 | 好大好爽好舒服 | av基地| 少妇太紧太爽又黄又硬又爽 | www.日韩一区 | 一级黄色片视频 | 国产美女精品视频 | 手机看片日韩国产 | 不用播放器av| 丰满人妻一区二区三区在线 | 欧美精品一区二区三区久久久 | 久在线| 在线免费观看日韩视频 | 免费的性爱视频 | 国产999精品视频 | 性色AV无码久久一区二区三 | 91色啪 | 秋霞在线视频观看 | 国产又粗又猛又爽又黄的视频在线观看动漫 | 久久久在线观看 | 亚洲AV成人无码精电影在线 | 中文字幕精品视频在线观看 | 亚洲一区欧美激情 | 欧美一级性生活视频 | 亚洲精品中文字幕 | 精品久久久久久久久久岛国gif |