提交 e6a4ea36 编写于 作者: S Sam Judd

Add GlideModule for lazily initialization.

Fixes #299.
上级 e099ef65
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bumptech.glide.integration.okhttp">
<application />
<application>
<meta-data
android:name="com.bumptech.glide.integration.okhttp.OkHttpGlideModule"
android:value="GlideModule" />
</application>
</manifest>
package com.bumptech.glide.integration.okhttp;
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.GlideModule;
import java.io.InputStream;
/**
* A {@link com.bumptech.glide.module.GlideModule} implementation to replace Glide's default
* {@link java.net.HttpURLConnection} based {@link com.bumptech.glide.load.model.ModelLoader} with an OkHttp based
* {@link com.bumptech.glide.load.model.ModelLoader}.
*
* <p>
* If you're using gradle, you can include this module simply by depending on the aar, the module will be merged
* in by manifest merger. For other build systems or for more more information, see
* {@link com.bumptech.glide.module.GlideModule}.
* </p>
*/
public class OkHttpGlideModule implements GlideModule {
@Override
public void initialize(Context context, Glide glide) {
glide.register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bumptech.glide.integration.volley">
<application />
<application>
<meta-data
android:name="com.bumptech.glide.integration.volley.VolleyGlideModule"
android:value="GlideModule" />
</application>
</manifest>
package com.bumptech.glide.integration.volley;
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.GlideModule;
import java.io.InputStream;
/**
* A {@link com.bumptech.glide.module.GlideModule} implementation to replace Glide's default
* {@link java.net.HttpURLConnection} based {@link com.bumptech.glide.load.model.ModelLoader} with a Volley based
* {@link com.bumptech.glide.load.model.ModelLoader}.
*
* <p>
* If you're using gradle, you can include this module simply by depending on the aar, the module will be merged
* in by manifest merger. For other build systems or for more more information, see
* {@link com.bumptech.glide.module.GlideModule}.
* </p>
*/
public class VolleyGlideModule implements GlideModule {
@Override
public void initialize(Context context, Glide glide) {
glide.register(GlideUrl.class, InputStream.class, new VolleyUrlLoader.Factory(context));
}
}
package com.bumptech.glide.module;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import com.bumptech.glide.Glide;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, emulateSdk = 18)
public class ManifestParserTest {
private static final String MODULE_VALUE = "GlideModule";
@Mock Context context;
private ManifestParser parser;
private ApplicationInfo applicationInfo;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
applicationInfo = new ApplicationInfo();
applicationInfo.metaData = new Bundle();
String packageName = "com.bumptech.test";
when(context.getPackageName()).thenReturn(packageName);
PackageManager pm = mock(PackageManager.class);
when(pm.getApplicationInfo(eq(packageName), eq(PackageManager.GET_META_DATA)))
.thenReturn(applicationInfo);
when(context.getPackageManager()).thenReturn(pm);
parser = new ManifestParser(context);
}
@Test
public void testParse_returnsEmptyListIfNoModulesListed() {
assertThat(parser.parse()).isEmpty();
}
@Test
public void testParse_withSingleValidModuleName_returnsListContainingModule() {
addModuleToManifest(TestModule1.class);
List<GlideModule> modules = parser.parse();
assertThat(modules).hasSize(1);
assertThat(modules.get(0)).isInstanceOf(TestModule1.class);
}
@Test
public void testParse_withMultipleValidModuleNames_returnsListContainingModules() {
addModuleToManifest(TestModule1.class);
addModuleToManifest(TestModule2.class);
List<GlideModule> modules = parser.parse();
assertThat(modules).hasSize(2);
assertThat(modules).contains(new TestModule1());
assertThat(modules).contains(new TestModule2());
}
@Test
public void testParse_withValidModuleName_ignoresMetadataWithoutGlideModuleValue() {
applicationInfo.metaData.putString(TestModule1.class.getName(), MODULE_VALUE + "test");
assertThat(parser.parse()).isEmpty();
}
@Test(expected = RuntimeException.class)
public void testThrows_whenModuleNameNotFound() {
addToManifest("fakeClassName");
parser.parse();
}
@Test(expected = RuntimeException.class)
public void testThrows_whenClassInManifestIsNotAModule() {
addModuleToManifest(InvalidClass.class);
parser.parse();
}
@Test(expected = RuntimeException.class)
public void testThrows_whenPackageNameNotFound() {
when(context.getPackageName()).thenReturn("fakePackageName");
parser.parse();
}
private void addModuleToManifest(Class<?> moduleClass) {
addToManifest(moduleClass.getName());
}
private void addToManifest(String key) {
applicationInfo.metaData.putString(key, MODULE_VALUE);
}
public static class InvalidClass { }
public static class TestModule1 implements GlideModule {
@Override
public void initialize(Context context, Glide glide) { }
@Override
public boolean equals(Object o) {
return o instanceof TestModule1;
}
@Override
public int hashCode() {
return super.hashCode();
}
}
public static class TestModule2 implements GlideModule {
@Override
public void initialize(Context context, Glide glide) { }
@Override
public boolean equals(Object o) {
return o instanceof TestModule2;
}
@Override
public int hashCode() {
return super.hashCode();
}
}
}
\ No newline at end of file
......@@ -56,6 +56,8 @@ import com.bumptech.glide.load.resource.transcode.GlideBitmapDrawableTranscoder;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
import com.bumptech.glide.load.resource.transcode.TranscoderRegistry;
import com.bumptech.glide.manager.RequestManagerRetriever;
import com.bumptech.glide.module.GlideModule;
import com.bumptech.glide.module.ManifestParser;
import com.bumptech.glide.provider.DataLoadProvider;
import com.bumptech.glide.provider.DataLoadProviderRegistry;
import com.bumptech.glide.request.FutureTarget;
......@@ -241,6 +243,10 @@ public class Glide {
bitmapFitCenter = new FitCenter(bitmapPool);
drawableFitCenter = new GifBitmapWrapperTransformation(bitmapPool, bitmapFitCenter);
for (GlideModule module : new ManifestParser(context).parse()) {
module.initialize(context, this);
}
}
/**
......
package com.bumptech.glide.module;
import android.content.Context;
import com.bumptech.glide.Glide;
/**
* An interface allowing lazy registration of {@link com.bumptech.glide.load.model.ModelLoader ModelLoaders}.
*
* <p>
* To use this interface:
* <ol>
* <li>
* Implement the GlideModule interface in a class with public visibility, calling
* {@link com.bumptech.glide.Glide#register(Class, Class, com.bumptech.glide.load.model.ModelLoaderFactory)}
* for each {@link com.bumptech.glide.load.model.ModelLoader} you'd like to register:
* <pre>
* <code>
* public class FlickrGlideModule implements GlideModule {
* {@literal @}Override
* public void initialize(Context context, Glide glide) {
* glide.register(Model.class, Data.class, new MyModelLoader());
* }
* }
* </code>
* </pre>
* </li>
* <li>
* Add your implementation to your list of keeps in your proguard.cfg file:
* <pre>
* {@code
* -keepnames class * com.bumptech.glide.samples.flickr.FlickrGlideModule
* }
* </pre>
* </li>
* <li>
* Add a metadata tag to your AndroidManifest.xml with your GlideModule implementation's fully qualified
* classname as the key, and {@code GlideModule} as the value:
* <pre>
* {@code
* <meta-data
* android:name="com.bumptech.glide.samples.flickr.FlickrGlideModule"
* android:value="GlideModule" />
* }
* </pre>
* </li>
* </ol>
* </p>
*
* <p>
* All implementations must be publicly visible and contain only an empty constructor so they can be instantiated
* via reflection when Glide is lazily initialized.
* </p>
*/
public interface GlideModule {
void initialize(Context context, Glide glide);
}
package com.bumptech.glide.module;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import java.util.ArrayList;
import java.util.List;
/**
* Parses {@link com.bumptech.glide.module.GlideModule} references out of the AndroidManifest file.
*/
public final class ManifestParser {
private static final String GLIDE_MODULE_VALUE = "GlideModule";
private final Context context;
public ManifestParser(Context context) {
this.context = context;
}
public List<GlideModule> parse() {
List<GlideModule> modules = new ArrayList<GlideModule>();
try {
ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
context.getPackageName(), PackageManager.GET_META_DATA);
if (appInfo.metaData != null) {
for (String key : appInfo.metaData.keySet()) {
if (GLIDE_MODULE_VALUE.equals(appInfo.metaData.getString(key))) {
modules.add(parseModule(key));
}
}
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Unable to find metadata to parse GlideModules", e);
}
return modules;
}
private static GlideModule parseModule(String className) {
Class<?> clazz;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Unable to find GlideModule implementation", e);
}
Object module;
try {
module = clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to instantiate GlideModule implementation for " + clazz, e);
}
if (!(module instanceof GlideModule)) {
throw new RuntimeException("Expected instanceof GlideModule, but found: " + module);
}
return (GlideModule) module;
}
}
......@@ -23,6 +23,9 @@
<activity android:name=".FullscreenActivity" />
<meta-data
android:name="com.bumptech.glide.samples.flickr.FlickrGlideModule"
android:value="GlideModule" />
</application>
</manifest>
package com.bumptech.glide.samples.flickr;
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.module.GlideModule;
import com.bumptech.glide.samples.flickr.api.Photo;
import java.io.InputStream;
/**
* {@link com.bumptech.glide.module.GlideModule} for the Flickr sample app.
*/
public class FlickrGlideModule implements GlideModule {
@Override
public void initialize(Context context, Glide glide) {
glide.register(Photo.class, InputStream.class, new FlickrModelLoader.Factory());
}
}
......@@ -33,7 +33,6 @@ import com.bumptech.glide.samples.flickr.api.Api;
import com.bumptech.glide.samples.flickr.api.Photo;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
......@@ -90,7 +89,6 @@ public class FlickrSearchActivity extends ActionBarActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Glide.get(this).register(Photo.class, InputStream.class, new FlickrModelLoader.Factory());
backgroundThread = new HandlerThread("BackgroundThumbnailHandlerThread");
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
......
......@@ -19,6 +19,10 @@
</intent-filter>
</activity>
<activity android:name=".FullscreenActivity" />
<meta-data
android:name="com.bumptech.glide.samples.giphy.GiphyGlideModule"
android:value="GlideModule" />
</application>
</manifest>
package com.bumptech.glide.samples.giphy;
import android.content.Context;
import com.bumptech.glide.Glide;
import com.bumptech.glide.module.GlideModule;
import java.io.InputStream;
/**
* {@link com.bumptech.glide.module.GlideModule} implementation for the Giphy sample app.
*/
public class GiphyGlideModule implements GlideModule {
@Override
public void initialize(Context context, Glide glide) {
glide.register(Api.GifResult.class, InputStream.class, new GiphyModelLoader.Factory());
}
}
......@@ -20,7 +20,6 @@ import com.bumptech.glide.ListPreloader;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.util.ViewPreloadSizeProvider;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
......@@ -31,15 +30,12 @@ public class MainActivity extends Activity implements Api.Monitor {
private static final String TAG = "GiphyActivity";
private GifAdapter adapter;
private DrawableRequestBuilder<Api.GifResult> gifItemRequest;
private ViewPreloadSizeProvider<Api.GifResult> preloadSizeProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Glide.get(this).register(Api.GifResult.class, InputStream.class, new GiphyModelLoader.Factory());
ImageView giphyLogoView = (ImageView) findViewById(R.id.giphy_logo_view);
Glide.with(this)
......@@ -49,12 +45,12 @@ public class MainActivity extends Activity implements Api.Monitor {
ListView gifList = (ListView) findViewById(R.id.gif_list);
gifItemRequest = Glide.with(this)
DrawableRequestBuilder<Api.GifResult> gifItemRequest = Glide.with(this)
.from(Api.GifResult.class)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.fitCenter();
preloadSizeProvider = new ViewPreloadSizeProvider<Api.GifResult>();
ViewPreloadSizeProvider<Api.GifResult> preloadSizeProvider = new ViewPreloadSizeProvider<Api.GifResult>();
adapter = new GifAdapter(this, gifItemRequest, preloadSizeProvider);
gifList.setAdapter(adapter);
ListPreloader<Api.GifResult> preloader = new ListPreloader<Api.GifResult>(adapter, preloadSizeProvider, 2);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册