@CalledByNative private static void registerSystemCallback(Context context) { context.registerComponentCallbacks( new ComponentCallbacks2() { @Override public void onTrimMemory(int level) { maybeNotifyMemoryPresure(level); } @Override public void onLowMemory() { nativeOnMemoryPressure(MemoryPressureLevel.CRITICAL); } @Override public void onConfigurationChanged(Configuration configuration) { } }); }
@SmallTest public void testComponentCallbacksForTargetContext() { Context targetContext = getInstrumentation().getTargetContext(); Application targetApplication = (Application) targetContext.getApplicationContext(); AdvancedMockContext context = new AdvancedMockContext(targetContext); Callback1 callback1 = new Callback1(); Callback2 callback2 = new Callback2(); context.registerComponentCallbacks(callback1); context.registerComponentCallbacks(callback2); targetApplication.onLowMemory(); assertTrue("onLowMemory should have been called.", callback1.mOnLowMemoryCalled); assertTrue("onLowMemory should have been called.", callback2.mOnLowMemoryCalled); Configuration configuration = new Configuration(); targetApplication.onConfigurationChanged(configuration); assertEquals("onConfigurationChanged should have been called.", configuration, callback1.mConfiguration); assertEquals("onConfigurationChanged should have been called.", configuration, callback2.mConfiguration); targetApplication.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE); assertEquals("onTrimMemory should have been called.", ComponentCallbacks2 .TRIM_MEMORY_MODERATE, callback2.mLevel); }
/** * Used by applications to simulate a memory pressure signal. By throwing certain intent * actions. */ public static boolean handleDebugIntent(Activity activity, String action) { if (ACTION_LOW_MEMORY.equals(action)) { simulateLowMemoryPressureSignal(activity); } else if (ACTION_TRIM_MEMORY.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_COMPLETE); } else if (ACTION_TRIM_MEMORY_RUNNING_CRITICAL.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL); } else if (ACTION_TRIM_MEMORY_MODERATE.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_MODERATE); } else { return false; } return true; }
@Override public void onTrimMemory(int level) { switch (level) { case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: Log.d(TAG, "Memory trimmed"); FragmentManager fragmentManager = getFragmentManager(); BookListFragment lf = (BookListFragment) fragmentManager.findFragmentById(R.id.book_list); lf.adapter.getModel().lowMemory(); default: break; } }
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) public static boolean handleDebugIntent(Application application, String action) { switch (action) { case ACTION_TRIM_MEMORY_UI_HIDDEN: simulateTrimMemory(application, ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); break; case ACTION_TRIM_MEMORY_MODERATE: simulateTrimMemory(application, TRIM_MEMORY_MODERATE); break; case ACTION_TRIM_MEMORY_CRITICAL: simulateTrimMemory(application, TRIM_MEMORY_COMPLETE); default: return false; } return true; }
@Override public void onTrimMemory(int level) { ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(this); if(imageLoader != null) { Log.i(TAG, "Memory Trim Level: " + level); if (level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) { imageLoader.onLowMemory(0.75f); } else if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW) { imageLoader.onLowMemory(0.50f); } else if(level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE) { imageLoader.onLowMemory(0.25f); } } else if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) { imageLoader.onLowMemory(0.25f); } else if(level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { imageLoader.onLowMemory(0.75f); } } }
@Override public void onTrimMemory(int level) { switch(level) { // Trims memory when it reaches a moderate level and the session is inactive case ComponentCallbacks2.TRIM_MEMORY_MODERATE: case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: if(session.isActive()) break; // Trims memory when it reaches a critical level case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: Log.w("MusicControl", "Control resources are being removed due to system's low memory (Level: " + level + ")"); destroy(); break; } }
public void start() { //自动回收内存 imageView.getContext().registerComponentCallbacks(new ComponentCallbacks2() { @Override public void onTrimMemory(int level) { LogUtils.log().addMsg("内存较低,自动回收内存缓存,Level:" + level).build().execute(); clearMemCache(level); } @Override public void onConfigurationChanged(Configuration newConfig) { } @Override public void onLowMemory() { LogUtils.log().addMsg("内存不足,自动清空内存缓存").build().execute(); clearMemCache(); } }); new ImageLoader(this).start(); }
@CalledByNative private static void registerSystemCallback() { ContextUtils.getApplicationContext().registerComponentCallbacks( new ComponentCallbacks2() { @Override public void onTrimMemory(int level) { maybeNotifyMemoryPresure(level); } @Override public void onLowMemory() { nativeOnMemoryPressure(MemoryPressureLevel.CRITICAL); } @Override public void onConfigurationChanged(Configuration configuration) { } }); }
/** * Register ComponentCallbacks2 to receive memory pressure signals. * */ @CalledByNative private static void registerComponentCallbacks() { sCallbacks = new ComponentCallbacks2() { @Override public void onTrimMemory(int level) { if (level != ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { nativeOnTrimMemory(level); } } @Override public void onLowMemory() { // Don't support old onLowMemory(). } @Override public void onConfigurationChanged(Configuration config) { } }; ContextUtils.getApplicationContext().registerComponentCallbacks(sCallbacks); }
@Override public void onTrimMemory(int level) { ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(this); if(imageLoader != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { Log.i(TAG, "Memory Trim Level: " + level); if (level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) { imageLoader.onLowMemory(0.75f); } else if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW) { imageLoader.onLowMemory(0.50f); } else if(level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE) { imageLoader.onLowMemory(0.25f); } } else if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) { imageLoader.onLowMemory(0.25f); } else if(level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { imageLoader.onLowMemory(0.75f); } } }
@Override public void onTrimMemory(int level) { switch (level) { case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: releaseUnUsedBitmaps(3); break; case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: releaseUnUsedBitmaps(1); break; case ComponentCallbacks2.TRIM_MEMORY_MODERATE: case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: releaseUnUsedBitmaps(0); break; } }
final void handleLowMemory() { ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null); final int N = callbacks.size(); for (int i=0; i<N; i++) { callbacks.get(i).onLowMemory(); } // Ask SQLite to free up as much memory as it can, mostly from its page caches. if (Process.myUid() != Process.SYSTEM_UID) { int sqliteReleased = SQLiteDatabase.releaseMemory(); EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); } // Ask graphics to free up as much as possible (font/image caches) Canvas.freeCaches(); // Ask text layout engine to free also as much as possible Canvas.freeTextLayoutCaches(); BinderInternal.forceGc("mem"); }
/** * @inheritDoc */ @Override public void trimMemory(int level) { if(level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { emptyCache(); //dump the cache } else if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE){ trimCache(0.5f); // trim to half the max size } else if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND){ trimCache(0.7f); // trim to one seventh max size } else if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL){ trimCache(0.2f); // trim to one fifth max size } }
@CalledByNative private static void registerSystemCallback(Context context) { context.registerComponentCallbacks( new ComponentCallbacks2() { @Override public void onTrimMemory(int level) { maybeNotifyMemoryPresure(level); } @Override public void onLowMemory() { nativeOnMemoryPressure(MemoryPressureLevelList.MEMORY_PRESSURE_CRITICAL); } @Override public void onConfigurationChanged(Configuration configuration) { } }); }
/** * Used by applications to simulate a memory pressure signal. By throwing certain intent * actions. */ public static boolean handleDebugIntent(Activity activity, String action) { if (ACTION_LOW_MEMORY.equals(action)) { simulateLowMemoryPressureSignal(activity); } else if (ACTION_TRIM_MEMORY.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_COMPLETE); } else if (ACTION_TRIM_MEMORY_RUNNING_CRITICAL.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_MODERATE); } else if (ACTION_TRIM_MEMORY_MODERATE.equals(action)) { simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL); } else { return false; } return true; }
/** * 获取修剪级别的名称 */ public static String getTrimLevelName(int level) { switch (level) { case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: return "COMPLETE"; case ComponentCallbacks2.TRIM_MEMORY_MODERATE: return "MODERATE"; case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: return "BACKGROUND"; case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: return "UI_HIDDEN"; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: return "RUNNING_CRITICAL"; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: return "RUNNING_LOW"; case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: return "RUNNING_MODERATE"; default: return "UNKNOWN"; } }
public GlideContext(Context context, Registry registry, ImageViewTargetFactory imageViewTargetFactory, RequestOptions defaultRequestOptions, Engine engine, ComponentCallbacks2 componentCallbacks, int logLevel) { super(context.getApplicationContext()); this.registry = registry; this.imageViewTargetFactory = imageViewTargetFactory; this.defaultRequestOptions = defaultRequestOptions; this.engine = engine; this.componentCallbacks = componentCallbacks; this.logLevel = logLevel; mainHandler = new Handler(Looper.getMainLooper()); }
@Test public void testTrimMemoryBackground() { TrimClearMemoryCacheHarness harness = new TrimClearMemoryCacheHarness(); harness.resourceCache.trimMemory(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND); verify(harness.listener).onResourceRemoved(eq(harness.first)); verify(harness.listener).onResourceRemoved(eq(harness.second)); }
@Test public void testTrimMemoryModerate() { TrimClearMemoryCacheHarness harness = new TrimClearMemoryCacheHarness(); harness.resourceCache.trimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE); verify(harness.listener).onResourceRemoved(harness.first); verify(harness.listener).onResourceRemoved(harness.second); }
@Test public void testTrimMemoryUiHidden() { TrimClearMemoryCacheHarness harness = new TrimClearMemoryCacheHarness(); harness.resourceCache.trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); verify(harness.listener).onResourceRemoved(harness.first); verify(harness.listener, never()).onResourceRemoved(harness.second); }
@Test public void testPreventEviction() { final MemoryCache cache = new LruResourceCache(100); final Resource<?> first = getResource(30); final Key firstKey = new MockKey(); cache.put(firstKey, first); Resource<?> second = getResource(30); Key secondKey = new MockKey(); cache.put(secondKey, second); Resource<?> third = getResource(30); Key thirdKey = new MockKey(); cache.put(thirdKey, third); cache.setResourceRemovedListener(new ResourceRemovedListener() { @Override public void onResourceRemoved(Resource<?> removed) { if (removed == first) { cache.put(firstKey, first); } } }); // trims from 100 to 50, having 30+30+30 items, it should trim to 1 item cache.trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); // and that 1 item must be first, because it's forced to return to cache in the listener @SuppressWarnings("unchecked") LruCache<Key, Resource<?>> lruCache = (LruCache<Key, Resource<?>>) cache; assertTrue(lruCache.contains(firstKey)); assertFalse(lruCache.contains(secondKey)); assertFalse(lruCache.contains(thirdKey)); }
@Override public void onTrimMemory(int level) { super.onTrimMemory(level); if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // The widget preview db can result in holding onto over // 3MB of memory for caching which isn't necessary. SQLiteDatabase.releaseMemory(); // This clears all widget bitmaps from the widget tray // TODO(hyunyoungs) } if (mLauncherCallbacks != null) { mLauncherCallbacks.onTrimMemory(level); } }
public static void maybeNotifyMemoryPresure(int level) { if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { nativeOnMemoryPressure(MemoryPressureLevel.CRITICAL); } else if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND || level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) { // Don't notifiy on TRIM_MEMORY_UI_HIDDEN, since this class only // dispatches actionable memory pressure signals to native. nativeOnMemoryPressure(MemoryPressureLevel.MODERATE); } }
@Override public void onTrimMemory(final int level) { log.info("onTrimMemory({}) called", level); if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) { log.warn("low memory detected, stopping service"); stopSelf(); } }
private void trimMemory(int level) { if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { dispatchMemoryPressure(MemoryPressure.CRITICAL); } else if (level >= TRIM_MEMORY_BACKGROUND || level == TRIM_MEMORY_RUNNING_CRITICAL) { dispatchMemoryPressure(MemoryPressure.MODERATE); } }
@Override public void onTrimMemory(int level) { super.onTrimMemory(level); if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) { shouldReload = true; } }