PowerManagerService之自動滅屏流程解析
前言
PowerManagerService之亮屏流程分析 歸納了亮屏/滅屏的通用流程,PowerManagerService之手動滅屏 對手動滅屏流程進行了整體的分析。 本文以前兩篇文章為基礎(chǔ),來分析自動滅屏,請讀者務(wù)必仔細(xì)閱讀前兩篇文章。
自動滅屏
要想分析自動滅屏,需得回顧下 PowerManagerService之亮屏流程分析 的亮屏邏輯的一些細(xì)節(jié)。
在亮屏的時候,會保存亮屏的時間,以及用戶行為的時間,這兩個時間用于決定用戶行為,如下
// PowerManagerService.java private void updateUserActivitySummaryLocked(long now, int dirty) { // ... for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) { int groupUserActivitySummary = 0; long groupNextTimeout = 0; if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) { final long lastUserActivityTime = mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId); final long lastUserActivityTimeNoChangeLights = mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked( groupId); // mLastWakeTime 表示上次亮屏的時間 // lastUserActivityTime 表示上次用戶行為的時間 if (lastUserActivityTime >= mLastWakeTime) { // 計算使屏幕變暗的超時時間 groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else { // ... } } // ... } // ... }
此時得到的用戶行為是 USER_ACTIVITY_SCREEN_BRIGHT,表明用戶行為是要點亮屏幕。
之后會向 DisplayManagerService 發(fā)起請求,而最終決定屏幕狀態(tài)(亮、滅、暗,等等)的請求策略,它的更新過程如下
int getDesiredScreenPolicyLocked(int groupId) { final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId); final int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId); if (wakefulness == WAKEFULNESS_ASLEEP || sQuiescent) { // ... } else if (wakefulness == WAKEFULNESS_DOZING) { // ... } if (mIsVrModeEnabled) { // ... } if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0 || !mBootCompleted || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & USER_ACTIVITY_SCREEN_BRIGHT) != 0 || mScreenBrightnessBoostInProgress) { return DisplayPowerRequest.POLICY_BRIGHT; } // ... }
由于用戶行為是 USER_ACTIVITY_SCREEN_BRIGHT,因此策略為 DisplayPowerRequest.POLICY_BRIGHT,它最終導(dǎo)致屏幕變亮。
那么亮屏后,是如何自動滅屏呢?
// PowerManagerService.java private void updateUserActivitySummaryLocked(long now, int dirty) { // ... for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) { int groupUserActivitySummary = 0; long groupNextTimeout = 0; if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) { final long lastUserActivityTime = mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId); final long lastUserActivityTimeNoChangeLights = mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked( groupId); if (lastUserActivityTime >= mLastWakeTime) { // 使屏幕變暗的超時時間 groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else { // ... } } // ... } // 使用屏幕變暗的超時時間,發(fā)送一個定時消息來更新用戶行為 if (hasUserActivitySummary && nextTimeout >= 0) { scheduleUserInactivityTimeout(nextTimeout); } } private void scheduleUserInactivityTimeout(long timeMs) { final Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT); msg.setAsynchronous(true); // 利用超時時間,發(fā)送一個定時消息,更新用戶行為 // 最終調(diào)用 handleUserActivityTimeout mHandler.sendMessageAtTime(msg, timeMs); } private void handleUserActivityTimeout() { // runs on handler thread synchronized (mLock) { // 標(biāo)記用戶行為需要更新 mDirty |= DIRTY_USER_ACTIVITY; // 重新更新電源狀態(tài),其實就是為了更新用戶行為 updatePowerStateLocked(); } }
從上面的代碼邏輯可以看出,當(dāng) Power 鍵亮屏后,會計算出使屏幕變暗的超時時間,然后利用這個超時時間,發(fā)送了一個定時消息,當(dāng)屏幕變暗的超時時間到了,就會再次更新用戶行為,如下
// PowerManagerService.java private void updateUserActivitySummaryLocked(long now, int dirty) { // ... for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) { int groupUserActivitySummary = 0; long groupNextTimeout = 0; if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) { final long lastUserActivityTime = mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId); final long lastUserActivityTimeNoChangeLights = mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked( groupId); if (lastUserActivityTime >= mLastWakeTime) { groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { // ... } else { // 計算滅屏的超時時間 groupNextTimeout = lastUserActivityTime + screenOffTimeout; if (now < groupNextTimeout) { // 進入 DIM 時間段 // 更新用戶行為 groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; } } } // ... } // ... // 使用滅屏的超時時間,發(fā)送一個定時消息來更新用戶行為 if (hasUserActivitySummary && nextTimeout >= 0) { scheduleUserInactivityTimeout(nextTimeout); } }
此次用戶行為的更新,計算的是滅屏的超時時間,然后用戶行為更新為 USER_ACTIVITY_SCREEN_DIM,表示用戶行為要使屏幕變暗。最后利用滅屏的超時時間,發(fā)送了一個定時消息來再次更新用戶行為。
現(xiàn)在用戶行為是使屏幕變暗,再看看請求策略是如何更新的
int getDesiredScreenPolicyLocked(int groupId) { final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId); final int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId); if (wakefulness == WAKEFULNESS_ASLEEP || sQuiescent) { // ... } else if (wakefulness == WAKEFULNESS_DOZING) { // ... } if (mIsVrModeEnabled) { // ... } if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0 || !mBootCompleted || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & USER_ACTIVITY_SCREEN_BRIGHT) != 0 || mScreenBrightnessBoostInProgress) { // ... } return DisplayPowerRequest.POLICY_DIM; }
請求策略更新為 DisplayPowerRequest.POLICY_DIM,最終它會使屏幕變暗。
當(dāng)滅屏的超時時間到了,我們看下再次更新用戶行為時,會發(fā)生什么
// PowerManagerService.java private void updateUserActivitySummaryLocked(long now, int dirty) { // ... for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) { int groupUserActivitySummary = 0; long groupNextTimeout = 0; if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) { final long lastUserActivityTime = mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId); final long lastUserActivityTimeNoChangeLights = mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked( groupId); if (lastUserActivityTime >= mLastWakeTime) { groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else { groupNextTimeout = lastUserActivityTime + screenOffTimeout; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; } } } // 滅屏超時前,帶有 PowerManager.ON_AFTER_RELEASE 這個flag的喚醒鎖釋放,延長屏幕的亮/暗的時間 if (groupUserActivitySummary == 0 && lastUserActivityTimeNoChangeLights >= mLastWakeTime) { // ... } // 滅屏超時,允許進入屏保 if (groupUserActivitySummary == 0) { // ... } // 按鍵 KeyEvent.KEYCODE_SOFT_SLEEP 進入屏保 if (groupUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) { // ... } // 用 AttentionDetector 重新計算超時時間,目前不分析 if ((groupUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0 && (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId) & WAKE_LOCK_STAY_AWAKE) == 0) { // ... } // 確定是否有用戶行為 hasUserActivitySummary |= groupUserActivitySummary != 0; // 保存超時時間 if (nextTimeout == -1) { nextTimeout = groupNextTimeout; } else if (groupNextTimeout != -1) { nextTimeout = Math.min(nextTimeout, groupNextTimeout); } } // DisplayGroupPowerStateMapper 保存用戶行為 mDisplayGroupPowerStateMapper.setUserActivitySummaryLocked(groupId, groupUserActivitySummary); } final long nextProfileTimeout = getNextProfileTimeoutLocked(now); if (nextProfileTimeout > 0) { nextTimeout = Math.min(nextTimeout, nextProfileTimeout); } // 利用超時時間,發(fā)送一個定時消息 if (hasUserActivitySummary && nextTimeout >= 0) { scheduleUserInactivityTimeout(nextTimeout); } }
可以看到滅屏超時時間到了時,有很多因素會再次影響用戶行為和超時時間,我們忽略這些因素,因此超時時間和用戶行為都為0。 既然沒有了用戶行為和超時時間,那么自然不會發(fā)送定時消息來更新用戶行為了,因為馬上就要滅屏的嘛,就沒必要去定時更新用戶行為了。
此時,我要提醒大家,從亮屏到自動滅屏的過程中,此時 wakefulness 還是 WAKEFULNESS_AWAKE,現(xiàn)在馬上要滅屏了,因此需要再次更新 wakefulness,這就是更新電源狀態(tài)過程中,updateWakefulnessLocked() 做的
// PowerManagerService.java private boolean updateWakefulnessLocked(int dirty) { boolean changed = false; if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE | DIRTY_DOCK_STATE | DIRTY_ATTENTIVE | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) { final long time = mClock.uptimeMillis(); for (int id : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) { if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(id) == WAKEFULNESS_AWAKE && isItBedTimeYetLocked(id)) { if (isAttentiveTimeoutExpired(id, time)) { // ... 不考慮 attentive timeout,大部分項目不支持 ... } else if (shouldNapAtBedTimeLocked()) { // ... 如果開啟了屏保,屏幕超時也會進入屏保 ... } else { // 更新 wakefulness 為 WAKEFULNESS_DOZING changed = sleepDisplayGroupNoUpdateLocked(id, time, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT, 0, Process.SYSTEM_UID); } } } } return changed; } private boolean isItBedTimeYetLocked(int groupId) { if (!mBootCompleted) { return false; } long now = mClock.uptimeMillis(); // 不考慮 attentive timeout,大部分項目不支持 if (isAttentiveTimeoutExpired(groupId, now)) { return !isBeingKeptFromInattentiveSleepLocked(groupId); } else { return !isBeingKeptAwakeLocked(groupId); } } private boolean isBeingKeptAwakeLocked(int groupId) { return mStayOn // 開發(fā)者模式中是否打開"充電常亮"功能 || mProximityPositive // 是否距離傳感器保持亮屏 || (mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId) & WAKE_LOCK_STAY_AWAKE) != 0 // 是否有喚醒鎖保持亮屏 || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & ( USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0 // 是否有亮屏的用戶行為 || mScreenBrightnessBoostInProgress; // 屏幕是否在亮度增強的過程中 }
現(xiàn)在要進入滅屏,只要沒有因素保持屏幕長亮,那么就會更新 wakefulness 為 WAKEFULNESS_DOZING。
現(xiàn)在設(shè)備進入了打盹狀態(tài),打盹狀態(tài)的流程不就是 PowerManagerService之手動滅屏 分析過了嗎? 如果設(shè)備進入打盹狀態(tài),并且能成功啟動 doze dream,就會真正進入打盹狀態(tài),否則進入休眠狀態(tài)。無論是設(shè)備進入打盹狀態(tài),還是休眠狀態(tài),屏幕最終會滅。
自動滅屏小結(jié)
自動滅屏的原理就是利用計算出的超時時間,發(fā)送一個定時消息來更新用戶行為,必要時更新 wakefulness,也就是更新系統(tǒng)狀態(tài),從而改變請求的策略,最終改變了屏幕的狀態(tài)(亮、滅、暗,等等)。
延長亮屏?xí)r間
現(xiàn)在我們討論一個與自動滅屏有關(guān)的話題,那就是延長亮屏?xí)r間
private void updateUserActivitySummaryLocked(long now, int dirty) { // ... for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) { int groupUserActivitySummary = 0; long groupNextTimeout = 0; if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) { final long lastUserActivityTime = mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId); final long lastUserActivityTimeNoChangeLights = mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked( groupId); // 1. 自動滅屏前,用戶觸摸TP,會導(dǎo)致用戶行為時間更新,從而延長亮屏?xí)r間 if (lastUserActivityTime >= mLastWakeTime) { groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else { groupNextTimeout = lastUserActivityTime + screenOffTimeout; if (now < groupNextTimeout) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; } } } // 2. 如果有更新用戶行為時帶有 PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,那么也會延長亮屏 if (groupUserActivitySummary == 0 && lastUserActivityTimeNoChangeLights >= mLastWakeTime) { // 根據(jù) lastUserActivityTimeNoChangeLights 時間點重新計算滅屏?xí)r間 groupNextTimeout = lastUserActivityTimeNoChangeLights + screenOffTimeout; if (now < groupNextTimeout) { final DisplayPowerRequest displayPowerRequest = mDisplayGroupPowerStateMapper.getPowerRequestLocked(groupId); if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT || displayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) { // 理論上講,屏幕超時,屏幕會先變暗,然而這里處理的為何是亮屏的請求策略 // 這是因為,假如沒有暗屏的時間呢? groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else if (displayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { groupUserActivitySummary = USER_ACTIVITY_SCREEN_DIM; } } } } mDisplayGroupPowerStateMapper.setUserActivitySummaryLocked(groupId, groupUserActivitySummary); } // ... if (hasUserActivitySummary && nextTimeout >= 0) { scheduleUserInactivityTimeout(nextTimeout); } }
可以看到,有兩種情況可以延長亮屏的時間
- 屏幕處于亮/暗時,如果用戶觸摸TP,那么會更新更新用戶行為時間,從而導(dǎo)致延長亮屏的時間。特別地,如果屏幕處于暗屏狀態(tài),那么點擊觸摸屏,會導(dǎo)致屏幕變亮。
- 如果有更新用戶行為時帶有 PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,那么也會延長亮屏。
本文分析用戶觸摸TP導(dǎo)致的延長亮屏過程,另外一個請讀者自行分析。
當(dāng)用戶觸摸TP時,底層Input系統(tǒng)會通過JNI調(diào)用 PowerManagerService#userActivityFromNative()
// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) { android_server_PowerManagerService_userActivity(eventTime, eventType); } // frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) { if (gPowerManagerServiceObj) { // 調(diào)用 Java 層的 PowerManagerService#userActivityFromNative() env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.userActivityFromNative, nanoseconds_to_milliseconds(eventTime), eventType, 0); } }
// PowerManagerService.java private void userActivityFromNative(long eventTime, int event, int displayId, int flags) { userActivityInternal(displayId, eventTime, event, flags, Process.SYSTEM_UID); } private void userActivityInternal(int displayId, long eventTime, int event, int flags, int uid) { synchronized (mLock) { // ... // 更新用戶活動時間 if (userActivityNoUpdateLocked(groupId, eventTime, event, flags, uid)) { // 更新電源狀態(tài) updatePowerStateLocked(); } } }
原來用戶觸摸TP,會更新用戶行為的時間,那么用戶行為也會發(fā)生改變
private void updateUserActivitySummaryLocked(long now, int dirty) { // ... // 先移除更新用戶行為的定時消息 mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT); // ... for (int groupId : mDisplayGroupPowerStateMapper.getDisplayGroupIdsLocked()) { int groupUserActivitySummary = 0; long groupNextTimeout = 0; if (mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId) != WAKEFULNESS_ASLEEP) { final long lastUserActivityTime = mDisplayGroupPowerStateMapper.getLastUserActivityTimeLocked(groupId); final long lastUserActivityTimeNoChangeLights = mDisplayGroupPowerStateMapper.getLastUserActivityTimeNoChangeLightsLocked( groupId); // 用戶觸摸TP,更新了用戶行為時間 lastUserActivityTime,因此這里重新計算超時時間 // 也就是說,延長了亮屏的時間 if (lastUserActivityTime >= mLastWakeTime) { // 重新計算暗屏的超時時間 groupNextTimeout = lastUserActivityTime + screenOffTimeout - screenDimDuration; if (now < groupNextTimeout) { // 用戶行為是亮屏 groupUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT; } else { // ... } } } // ... // 再次發(fā)送定時消息,更新用戶行為 if (hasUserActivitySummary && nextTimeout >= 0) { scheduleUserInactivityTimeout(nextTimeout); } }
由于用戶行為時間的更新,導(dǎo)致重新計算了暗屏的超時時間,并且用戶行為會更新為 USER_ACTIVITY_SCREEN_BRIGHT。
用戶行為的更新,也導(dǎo)致了請求策略的更新,如下
int getDesiredScreenPolicyLocked(int groupId) { final int wakefulness = mDisplayGroupPowerStateMapper.getWakefulnessLocked(groupId); final int wakeLockSummary = mDisplayGroupPowerStateMapper.getWakeLockSummaryLocked(groupId); if (wakefulness == WAKEFULNESS_ASLEEP || sQuiescent) { // ... } else if (wakefulness == WAKEFULNESS_DOZING) { // ... } if (mIsVrModeEnabled) { // ... } if ((wakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0 || !mBootCompleted || (mDisplayGroupPowerStateMapper.getUserActivitySummaryLocked(groupId) & USER_ACTIVITY_SCREEN_BRIGHT) != 0 || mScreenBrightnessBoostInProgress) { return DisplayPowerRequest.POLICY_BRIGHT; } // ... }
可以看到,如果屏幕處于亮/暗狀態(tài),用戶觸摸TP,請求策略更新為 DisplayPowerRequest.POLICY_BRIGHT, 最終導(dǎo)致屏幕為亮屏狀態(tài)。
另外,重新計算出的暗屏超時時間,會被用來發(fā)送定時消息來更新用戶行為,因此就相當(dāng)于重置了屏幕超時時間。
因此,觸摸TP導(dǎo)致屏幕處于亮屏狀態(tài),并且重置了屏幕超時時間,那么就相當(dāng)于延長了亮屏的時間。
結(jié)束
如果明白了亮屏與滅屏的過程,自動滅屏的原理就沒有那么復(fù)雜,如果讀者在閱讀本文時,發(fā)現(xiàn)很多東西講的很簡單,那是因為前面的文章已經(jīng)分析過,所以讀者務(wù)必仔細(xì)閱讀前面兩篇文章。
以目前的三篇文章為根基,下一篇文章,我們將討論 PowerManagerService 的最后一個話題,喚醒鎖。
以上就是PowerManagerService之自動滅屏流程解析的詳細(xì)內(nèi)容,更多關(guān)于PowerManagerService 自動滅屏的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android應(yīng)用自動跳轉(zhuǎn)到應(yīng)用市場詳情頁面的方法
最近在工作中遇到一個需求,推廣部門要求實現(xiàn)應(yīng)用自動跳轉(zhuǎn)到應(yīng)用市場詳情頁面,通過查找一些資料,實現(xiàn)出來了,覺得有必要整理下方便以后或者有需要的朋友們參考借鑒,下面來一起詳細(xì)看看Android應(yīng)用自動跳轉(zhuǎn)到應(yīng)用市場詳情頁面的方法吧。2016-12-12Android中App字體大小不隨系統(tǒng)改變而改變
這篇文章主要介紹了Android中App字體大小不隨系統(tǒng)改變而改變,需要的朋友可以參考下2017-04-04Android實現(xiàn)QQ新用戶注冊界面遇到問題及解決方法
這篇文章主要介紹了Android實現(xiàn)QQ新用戶注冊界面遇到問題及解決方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09Android UI控件RatingBar實現(xiàn)自定義星星評分效果
這篇文章主要為大家詳細(xì)介紹了Android UI控件RatingBar實現(xiàn)自定義星星評分效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02Android?內(nèi)存優(yōu)化知識點梳理總結(jié)
這篇文章主要介紹了Android?內(nèi)存優(yōu)化知識點梳理總結(jié),Android?操作系統(tǒng)給每個進程都會分配指定額度的內(nèi)存空間,App?使用內(nèi)存來進行快速的文件訪問交互,長時間如此便需要優(yōu)化策略,文章分享優(yōu)化知識點總結(jié),需要的朋友可以參考一下2022-06-06Android RenderScript實現(xiàn)高斯模糊
這篇文章主要為大家詳細(xì)介紹了Android RenderScript實現(xiàn)高斯模糊的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12