胸怀万里世界, 放眼无限未来。这篇文章主要讲述Android之第三方框架使用汇总相关的知识,希望能为你提供帮助。
1. image loading 框架:
1.1Glide
1.2Picasso
1.3后续更新
...
2.网络框架:
2.1xUtil3
2.2OkHttp3
2.3Retrofit
2.4后续更新
...
3.数据库框架:
3.1ormlite
3.2后续更新
1.1Glide: 一、Glide-Getting Started Glide:
Glide就像Picasso, 能从许多资源上加载和显示图片, 也照顾了缓存和做图片操作的时候保持一个低的内存影响, 它已经被官方谷歌应用程序(如Google I / O的应用程序2015)和Picasso一样受欢迎, 在本系列中,我们将探索Glide在Picasso的差异和优势。
Why Use Glide?
经验丰富的android开发人员可以跳过这一节,但对于初学者来说:你可能会问自己为什么要使用Glide代替自己的实现。
在处理图像时Android是非常细致的,因为它会逐个像素加载到内存。手机照相机中的相片平均大小是2592*1936像素( 5百万像素) 大约占19MB内存。如果你有一个复杂的网络请求去缓存和处理图片, 自己写你将花费大量的时间, 甚至安全问题会使你头疼, 但是如果你使用一个测试好的框架像Glide变将变得安全方便.
Gradle
如同大多数依赖关系一样你的Gradler project的build.gradle增加一行:
compile '
com.github.bumptech.glide:glide:3.7.0'
Maven
Glide也支持Maven projects
<
dependency>
<
groupId>
com.github.bumptech.glide<
/groupId>
<
artifactId>
glide<
/artifactId>
<
version>
3.7.0<
/version>
<
type>
aar<
/type>
<
/dependency>
First Loading Image from a URL
就像Picasso,Glide库使用一个连贯接口。Glide的builder至少需要三个参数作为一个完整的方法请求:
- with(Context context) :
许多Android API调用上下文是必要的。Glide没有区别。Glide很方便因为它还可以传入Activity和Fragment对象
- load(String imageUrl) :
在这里你指定图像应该被加载。通常这里传入的是一个URL的字符串去加载网络图片
- into(ImageView targetImageView) :
目标ImageView,
你想要显示的ImageView
ImageView targetImageView =
(ImageView) findViewById(R.id.imageView);
String internetUrl =
"
http://i.imgur.com/DvpvklR.png"
;
Glide
.with(context)
.load(internetUrl)
.into(targetImageView);
二、Glide-Advanced Loading Loading from Resources
从Android加载资源。而不是给一个字符串URL指向一个互联网,给定int类型资源。
int resourceId =
R.mipmap.ic_launcher;
Glide
.with(context)
.load(resourceId)
.into(imageViewResource);
如果你对R.mipmap困惑,它是Android图标处理的新方法。
当然上述你可以直接给ImageView指定一个资源, 但是使用Glide是否更加有趣
Loading from File
从文件加载图片
// this file probably does not exist on your device. However, you can use any file path, which points to an image fileFile file =
new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "
Running.jpg"
);
Glide
.with(context)
.load(file)
.into(imageViewFile);
Loading from Uri
最后,您还可以加载图像定义为一个Uri。这个请求不同于前面的操作:
// this could be any Uri. for demonstration purposes we'
re just creating an Uri pointing to a launcher iconUri uri =
resourceIdToUri(context, R.mipmap.future_studio_launcher);
Glide
.with(context)
.load(uri)
.into(imageViewUri);
这个帮助函数是一个简单的从resourceId到一个Uri的转变, 它可以是任何的Uri
public static final String ANDROID_RESOURCE =
"
android.resource://"
;
public static final String FOREWARD_SLASH =
"
/"
;
private static Uri resourceIdToUri(Context context, int resourceId) {
return Uri.parse(ANDROID_RESOURCE +
context.getPackageName() +
FOREWARD_SLASH +
resourceId);
}
三、Glide-Sample Gallery Implementation: ListView 效果图:
文章图片
首先添加网络权限:
<
uses-permission android:name=
"
android.permission.INTERNET"
/>
activity_main:
<
RelativeLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:tools=
"
http://schemas.android.com/tools"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
tools:context=
"
${relativePackage}.${activityClass}"
>
<
ListView
android:id=
"
@
+
id/listView"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
/>
<
/RelativeLayout>
listview_item_image:
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
ImageView xmlns:android=
"
http://schemas.android.com/apk/res/android"
android:layout_width=
"
match_parent"
android:layout_height=
"
200dp"
/>
MainActivity:
import com.bumptech.glide.Glide;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
public class MainActivity extends Activity {ListView listView;
public static String[] eatFoodyImages =
{
"
http://i.imgur.com/rFLNqWI.jpg"
,
"
http://i.imgur.com/C9pBVt7.jpg"
,
"
http://i.imgur.com/rT5vXE1.jpg"
,
"
http://i.imgur.com/aIy5R2k.jpg"
,
"
http://i.imgur.com/MoJs9pT.jpg"
,
"
http://i.imgur.com/S963yEM.jpg"
,
"
http://i.imgur.com/rLR2cyc.jpg"
,
"
http://i.imgur.com/SEPdUIx.jpg"
,
"
http://i.imgur.com/aC9OjaM.jpg"
,
"
http://i.imgur.com/76Jfv9b.jpg"
,
"
http://i.imgur.com/fUX7EIB.jpg"
,
"
http://i.imgur.com/syELajx.jpg"
,
"
http://i.imgur.com/COzBnru.jpg"
,
"
http://i.imgur.com/Z3QjilA.jpg"
,
};
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=
(ListView) findViewById(R.id.listView);
listView.setAdapter(new ImageListAdapter(MainActivity.this, eatFoodyImages));
}
public class ImageListAdapter extends ArrayAdapter {
private Context context;
private LayoutInflater inflater;
private String[] imageUrls;
public ImageListAdapter(Context context, String[] imageUrls) {
super(context, R.layout.listview_item_image, imageUrls);
this.context =
context;
this.imageUrls =
imageUrls;
inflater =
LayoutInflater.from(context);
}@
Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null =
=
convertView) {
convertView =
inflater.inflate(R.layout.listview_item_image, parent, false);
}Glide
.with(context)
.load(imageUrls[position])
.into((ImageView) convertView);
return convertView;
}
}}
总结: 其实不论你加载一张还是多张图片Glide的调用还是一样的
四、Glide-Placeholder & Fade Animations 我们可能甚至不需要解释或讨论:空imageview在任何界面不好看。如果你使用Glide,你最有可能是通过一个网络连接加载图像。根据用户的环境中,这可能要花费大量的时间。一个应用程序的预期行为是显示一个占位符( 就是还未加载图片前显示给用户的图片) ,直到图像加载和处理占位符消失, 这样就可以给用户留给一个很好的体验效果。
Glide的封装使得这个很容易做到!只要调用.placeHolder()和一个引用(资源)和,作为一个占位符,直到你的实际图像已经准备好了。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.placeholder(R.mipmap.ic_launcher) // can also be a drawable
.into(imageViewPlaceholder);
很明显,你不能设置一个互联网url作为占位符,因为那个需要加载。应用resources和drawable是保证是可用的和可访问。
Error Placeholder: .error()
目前, 让我们假设我们的程序试图加载一个图像从一个网站,。Glide返回给我们一个错误的回调 , 这时候我们可以使用Glide的连贯接口是与前面的示例相同pre-display占位符,只是用不同的函数调用error():
Glide
.with(context)
.load("
http://futurestud.io/non_existing_imag e.png"
)
.placeholder(R.mipmap.ic_launcher) // can also be a drawable
.error(R.mipmap.future_studio_launcher) // will be displayed if the image cannot be loaded
.into(imageViewError);
【Android之第三方框架使用汇总】当我们定义的图片不能加载时, Glide将展示R.mipmap.future_studio_launcher替代, error()参数必定是已经存在的resources和drawable
Use of crossFade()
无论如果你加载图片之前还是错误加载显示一个占位符,改变图像的ImageView UI是一个非常重要的变化。一个简单的选择使这种变化更顺利和容易映入眼帘,是使用crossfase(淡入淡出)动画。Glide附带标准crossfade(淡入淡出)动画,这是默认(当前版本3.6.1)活动。如果你想Glide显示crossfase(淡入淡出)动画,你所要做的就是调用crossFade()方法;
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.placeholder(R.mipmap.ic_launcher) // can also be a drawable
.error(R.mipmap.future_studio_launcher) // will be displayed if the image cannot be loaded
.crossFade()
.into(imageViewFade);
crossFade()方法还有另一个重载函数crossFase(int duration),如果你想加速或减速这个动画, 你可以通过这个函数添加一个时间,默认是300毫秒
Use of dontAnimate()
使用这个方法表示是没有crossfase(淡入淡出)动画的, 直接展现imageView给用户。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.placeholder(R.mipmap.ic_launcher) // can also be a drawable
.error(R.mipmap.future_studio_launcher) // will be displayed if the image cannot be loaded
.dontAnimate()
.into(imageViewFade);
总结: 以上的每个函数都是不相关的, 比如你可以调用error()而不调用placeholder()等等。
五、Glide-Image Resizing & Scaling 在你的服务器或这API需要合适的尺寸这将是一个完美的解决方式,
相比Picasso, Glide在memory-wise更有效率, Glide自定图像大小范围在缓存和内存中, Picasso有相同的能力,但是需要调用fit().对于Glide, 如果图像没有显示在合适的大小, 调用override(horizontalSize, verticalSize),之后将重置大小后显示给用户
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.override(600, 200) // resizes the image to these dimensions (in pixel). does not respect aspect ratio
.into(imageViewResize);
Scaling Images
- CenterCrop : 一种尺度图像的裁剪技术,填补了ImageView的要求范围,然后裁减了多余的。ImageView将被完全填满,但图像可能显示不全。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.override(600, 200) // resizes the image to these dimensions (in pixel)
.centerCrop() // this cropping technique scales the image so that it fills the requested bounds and then crops the extra.
.into(imageViewResizeCenterCrop);
- FitCenter : fitCenter()是一种尺度图像的裁剪技术,这样两个尺寸等于或小于请求的ImageView的界限, 图像将显示完全,但可能不会填满整个ImageView。
Glide
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.override(600, 200)
.fitCenter()
.into(imageViewResizeFitCenter);
六、Glide — Displaying Gifs & Videos Displaying Gifs
大多数的图片加载框架只支持加载和显示图片, 在Glide中Gif将是一个特殊的功能
String gifUrl =
"
http://i.kinja-img.com/gawker-media/image/upload/s--B7tUiM5l--/gf2r69yorbdesguga10i.gif"
;
Glide
.with( context )
.load( gifUrl )
.into( imageViewGif );
在这里你仍然可以调用error()当GIF不能加载时, 和placeholder()GIF加载之前
Glide
.with( context )
.load( gifUrl )
.placeholder( R.drawable.cupcake )
.error( R.drawable.full_cake )
.into( imageViewGif );
Gif Check
上面的代码存在一个潜在问题, 就是如果你的Url不是一个Gif的话, 可能就是一个普通的图像, Glide不能自动识别它, 所以如果我们期望加载一个GIF还必须做一个声明:
Glide
.with( context )
.load( gifUrl )
.asGif()//声明
.error( R.drawable.full_cake )
.into( imageViewGif );
如果gifUrl是gif,没有什么变化。然而,与之前不同的是,如果gifUrl不是一个Gif,Glide会理解加载失败。Glide有优势, error()方法被调用和错误占位符显示,即使gifUrl是一个正确的Url图像(但不是一个Gif)。
Display Gif as Bitmap
在某些情况下可能我们只想显示GIF图像的第一帧, 你可以调用asBitmap()方法
Glide
.with( context )
.load( gifUrl )
.asBitmap()
.into( imageViewGifAsBitmap );
Display of Local Videos
如果gif是视频。Glide也能够显示视频的缩略图,只要他们存储在手机。让我们假设你得到文件路径,让用户选择一个视频:
String filePath =
"
/storage/emulated/0/Pictures/example_video.mp4"
;
Glide
.with( context )
.load( Uri.fromFile( new File( filePath ) ) )
.into( imageViewGifAsBitmap );
然而这适用于本地视频, 而且只能显示第一帧, 如果是网络或者其他的视频将不能显示, 你应该使用VideoView
七、Glide — Caching Basics Using Cache Strategies
Memory Cache:
让我们想象它从一个非常简单的要求:从互联网ImageView加载一张图片:
Glide
.with( context )
.load( eatFoodyImages[0] )
.skipMemoryCache( true )
.into( imageViewInternet );
你已经注意到我们。skipMemoryCache(true)专门告诉Glide跳过内存缓存。这意味着Glide不会把图像在内存缓存中。重要的是要理解,这只会影响内存缓存!Glide仍将利用磁盘高速缓存,以避免另一个网络请求。
还好知道Glide将所有图像资源默认缓存到内存中。因此,一个特定的调用skipMemoryCache(false)不是必需的。
提示: 如果你请求相同的Url和调用.skipMemoryCache( true )方法, 资源将会放在内存中缓存, 确保你的所有调用相同的资源,当你想要调整缓存行为!
Skipping Disk Cache
当你学到的在上面的部分中,即使你关闭内存缓存,请求图像仍将存储在设备上的磁盘存储。如果你一个图像,在相同的URL,但正在迅速改变,你可能希望禁用磁盘缓存。 你可以改变Glide的磁盘缓存.diskCacheStrategy()方法。与.skipMemoryCache()方法不同的是它接受一个enum,而不是一个简单的布尔。如果你想禁用磁盘缓存请求时,使用DiskCacheStrategy枚举值DiskCacheStrategy.NONE作为参数
Glide
.with( context )
.load( eatFoodyImages[0] )
.diskCacheStrategy( DiskCacheStrategy.NONE )
.into( imageViewInternet );
这个代码片段的图像将不会保存在磁盘高速缓存。然而,默认情况下它仍然会使用内存缓存!以禁用缓存,将方法调用:
Glide
.with( context )
.load( eatFoodyImages[0] )
.diskCacheStrategy( DiskCacheStrategy.NONE )
.skipMemoryCache( true )
.into( imageViewInternet );
Customize Disk Cache Behavior
Glide缓存原始,完全解决图像和另外小版本的图片。举个例子,如果你请求与1000 x1000像素,和500 x500像素两个图像, Glide将两个版本的图像缓存。
. diskCacheStrategy() 参数:
- DiskCacheStrategy.NONE:
禁止缓存
- DiskCacheStrategy.SOURCE :缓存只有原来的全分辨率图像。
- DiskCacheStrategy.RESULT: 缓存只有最终的图像,在降低分辨率(也可能是转换)(默认行为)
- DiskCacheStrategy.ALL :缓存所有版本的图像
Getting to know the Priority enum
enum给你四个不同的选项。这是优先级增加的命令列表
- Priority.LOW
- Priority.NORMAL
- Priority.HIGH
- Priority.IMMEDIATE
刚才那个例子, 理论上讲我们将大图片的优先级设置为HIGH就应该足够了, 但是我们这里还将小图片的优先级设为LOW;
private void loadImageWithHighPriority() {
Glide
.with( context )
.load( UsageExampleListViewAdapter.eatFoodyImages[0] )
.priority( Priority.HIGH )
.into( imageViewHero );
}private void loadImagesWithLowPriority() {
Glide
.with( context )
.load( UsageExampleListViewAdapter.eatFoodyImages[1] )
.priority( Priority.LOW )
.into( imageViewLowPrioLeft );
Glide
.with( context )
.load( UsageExampleListViewAdapter.eatFoodyImages[2] )
.priority( Priority.LOW )
.into( imageViewLowPrioRight );
}
运行的话大图片将第一显示, 但是这也会增加显示时间。
九、Glide — Thumbnails Advantages of Thumbnails
操作缩略图之前,确保你理解和Glide所有选项缓存和请求的优先级。如果你前面你懂了,然后使用了解缩略图可以帮助你进一步提高你的Android应用程序。
缩略图是不同的比之前的占位符。占位符必须附带的应用程序作为一个捆绑的资源。缩略图是一个动态的占位符,也可以从互联网上加载。缩略图会在显示实际的请求之前加载并处理。如果缩略图,不管出于什么原因,到达原始图像后,它不替换原来的形象。它只是将被销毁。
Simple Thumbnails
Glide为缩略图提供了两种不同的方式。首先是简单的选择,使用原始图像,只是在一个更小的分辨率。这个方法特别有用的组合ListView和detail Views。如果你已经在ListView显示图像,我们假设,在250 x250像素,图像将需要一个更大的分辨率detail Views。然而,从用户的角度来看,他已经看到了一个小版本的形象,为什么会有几秒钟的占位符,直到同样的图像显示(高分辨率)?
在这种情况下,它更多的意义继续显示250 x250像素版本细节视图,在后台加载完整的分辨率。Glide使之成为可能,调用.thumbnail()方法。在这种情况下,参数是一个浮点数大小:
Glide
.with( context )
.load( UsageExampleGifAndVideos.gifUrl )
.thumbnail( 0.1f )
.into( imageView2 );
例如,如果你通过0.1 f作为参数,Glide将显示原始图像大小的10%。如果原始图像1000 x1000像素,缩略图100 x100像素。自比ImageView图像会小的多,你需要确保ScaleType正确设置。 注意所有请求设置应用到原始请求也应用于缩略图。例如,如果您使用一个转换图像灰度,都会发生同样的缩略图。
Advanced Thumbnails with Complete Different Requests
使用.thumbnail()与一个浮点参数是容易设置,可以非常有效的,它并不总是有意义。如果缩略图需要负载相同的全分辨率图像通过网络,它可能不是更快。因此,Glide提供了另一种选择加载和显示缩略图。 第二个方式是通过一个完整的新的Glide请求参数。让我们来看一个例子:
private void loadImageThumbnailRequest() {
// setup Glide request without the into() method
DrawableRequestBuilder<
String>
thumbnailRequest =
Glide
.with( context )
.load( eatFoodyImages[2] );
// pass the request as a a parameter to the thumbnail request
Glide
.with( context )
.load( UsageExampleGifAndVideos.gifUrl )
.thumbnail( thumbnailRequest )
.into( imageView3 );
}
所不同的是,第一个缩略图请求完全独立于第二原始请求。缩略图可以是不同的资源或图像的URL,您可以应用不同的转换,等等。
提示,如果你想要更加疯狂,你可以使用递归和应用请求额外的缩略图请求到缩略图…
十、Glide — Callbacks: SimpleTarget and ViewTarget for Custom View Classes 这篇文章中我们将使用Bitmap作为我们的image, 而不是ImageView
Callbacks in Glide: Targets:
如果我们想使用Bitmap来显示Image,Glide提供了一个简单的方法来与Targets图像的位图资源的访问。Targets只是一个回调, 用来处理Glide加载完成后结果。Glide提供各种各样的Targets,而每个都有一个明确的target。我们从SimpleTarget开始。
SimpleTarget:
代码:
private SimpleTarget target =
new SimpleTarget<
Bitmap>
() {
@
Override
public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
// do something with the bitmap
// for demonstration purposes, let'
s just set it to an ImageView
imageView1.setImageBitmap( bitmap );
}
};
private void loadImageSimpleTarget() {
Glide
.with( context ) // could be an issue!
.load( eatFoodyImages[0] )
.asBitmap()
.into( target );
}
代码第一部分是声明一个域对象, 给图片设置Bitmap,
第二部分是和之前一样将target传入into(), 不同的是, 这里需要声明asBitmap(), 防止URL加载的图片可能是GIF或者Viedo
Pay Attention with Targets
除了知道怎么实现Glide的Taegts之后, 你还必须知道两点:
- 首先我们知道Android和java中我们可以直接在into(new
SimpleTarget( (){}); ,但是这也是一个缺陷这可能当加载完图片缺未加载回调时SimpleTarget就被回收了, 所以我们必须和我们如上一样, 定义成一个域对象
止, 请记住这一点。最后, 如果你的请求需要以外的activity生命周期,使用以下代码片段:
private void loadImageSimpleTargetApplicationContext() {
Glide
.with( context.getApplicationContext() ) // safer!
.load( eatFoodyImages[1]
.asBitmap()
.into( target2 );
}
Target with Specific Size
target另一个潜在的问题是他们没有一个特定的大小。如果你通过ImageView .into的参数(),Glide的大小将使用ImageView限制图像的大小。例如,如果加载图片是1000 x1000像素,但是ImageView只有250 x250像素,Glide将使用size较小的图像保存进内存。很明显,target并不能这样做,因为没有已知的大小。然而,如果你有一个特定的大小,您可以增加回调。如果你知道图像应该多大,你应该指定它以便节省内存:
private SimpleTarget target2 =
new SimpleTarget<
Bitmap>
( 250, 250 ) {
@
Override
public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
imageView2.setImageBitmap( bitmap );
}
};
private void loadImageSimpleTargetApplicationContext() {
Glide
.with( context.getApplicationContext() ) // safer!
.load( eatFoodyImages[1] )
.asBitmap()
.into( target2 );
}
ViewTarget
我们知道Glide不支持加载自定义View的ImageVeiw,但是Glide提供了ViewTarget很好的帮我们解决了这类问题:
public class FutureStudioView extends FrameLayout {
ImageView iv;
TextView tv;
public void initialize(Context context) {
inflate( context, R.layout.custom_view_futurestudio, this );
iv =
(ImageView) findViewById( R.id.custom_view_image );
tv =
(TextView) findViewById( R.id.custom_view_text );
}public FutureStudioView(Context context, AttributeSet attrs) {
super( context, attrs );
initialize( context );
}public FutureStudioView(Context context, AttributeSet attrs, int defStyleAttr) {
super( context, attrs, defStyleAttr );
initialize( context );
}public void setImage(Drawable drawable) {
iv =
(ImageView) findViewById( R.id.custom_view_image );
iv.setImageDrawable( drawable );
}
}
因为自定义View不是继承ImageView, 所以我们不能直接将它传入.into()中, 现在我们去创建一个ViewTarget:
private void loadImageViewTarget() {
FutureStudioView customView =
(FutureStudioView) findViewById( R.id.custom_view );
viewTarget =
new ViewTarget<
FutureStudioView, GlideDrawable>
( customView ) {
@
Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<
? super GlideDrawable>
glideAnimation) {
this.view.setImage( resource.getCurrent() );
}
};
Glide
.with( context.getApplicationContext() ) // safer!
.load( eatFoodyImages[2] )
.into( viewTarget );
}
在target的回调方法,我们使用函数setImage(Drawable drawable)给自定义View的ImageView设置图片。
同时,确保看到ViewTarget的构造函数:new ViewTarget < FutureStudioView GlideDrawable > (customView)。 这个应该覆盖所有你需要自定义视图。你也可以在回调函数中做额外的事情。例如,我们可以分析传入的位图的主要颜色和设置TextView的值。
十一、Glide — Loading Images into Notifications and AppWidgets
文章图片
从以上我们看到是一个NotificationCompat.Builder, 我们可以看到通知是有icon的, 如果icon是本地的我们可以直接加载, 然而如果icon来自网络呢, 没关系, Glide提供了一个方便的NotificationTarget.
NotificationTarget
文章图片
代码:
activity_main:
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
LinearLayout
xmlns:android=
"
http://schemas.android.com/apk/res/android"
android:layout_width=
"
match_parent"
android:layout_height=
"
wrap_content"
android:background=
"
@
android:color/white"
android:orientation=
"
vertical"
>
<
LinearLayout
android:layout_width=
"
match_parent"
android:layout_height=
"
wrap_content"
android:orientation=
"
horizontal"
android:padding=
"
2dp"
>
<
ImageView
android:id=
"
@
+
id/remoteview_notification_icon"
android:layout_width=
"
50dp"
android:layout_height=
"
50dp"
android:layout_marginRight=
"
2dp"
android:layout_weight=
"
0"
android:scaleType=
"
centerCrop"
/>
<
LinearLayout
android:layout_width=
"
0dp"
android:layout_height=
"
wrap_content"
android:layout_weight=
"
1"
android:orientation=
"
vertical"
>
<
TextView
android:id=
"
@
+
id/remoteview_notification_headline"
android:layout_width=
"
match_parent"
android:layout_height=
"
wrap_content"
android:ellipsize=
"
end"
android:singleLine=
"
true"
android:textSize=
"
12sp"
/>
<
TextView
android:id=
"
@
+
id/remoteview_notification_short_message"
android:layout_width=
"
match_parent"
android:layout_height=
"
wrap_content"
android:ellipsize=
"
end"
android:paddingBottom=
"
2dp"
android:singleLine=
"
true"
android:textSize=
"
14sp"
android:textStyle=
"
bold"
/>
<
/LinearLayout>
<
/LinearLayout>
<
/LinearLayout>
MainActivity:
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.NotificationTarget;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.widget.RemoteViews;
public class MainActivity extends Activity {
Context context;
private final int NOTIFICATION_ID=
1;
private NotificationTarget notificationTarget;
public static String[] eatFoodyImages =
{
"
http://i.imgur.com/rFLNqWI.jpg"
,
"
http://i.imgur.com/C9pBVt7.jpg"
,
"
http://i.imgur.com/rT5vXE1.jpg"
,
"
http://i.imgur.com/aIy5R2k.jpg"
,
"
http://i.imgur.com/MoJs9pT.jpg"
,
"
http://i.imgur.com/S963yEM.jpg"
,
"
http://i.imgur.com/rLR2cyc.jpg"
,
"
http://i.imgur.com/SEPdUIx.jpg"
,
"
http://i.imgur.com/aC9OjaM.jpg"
,
"
http://i.imgur.com/76Jfv9b.jpg"
,
"
http://i.imgur.com/fUX7EIB.jpg"
,
"
http://i.imgur.com/syELajx.jpg"
,
"
http://i.imgur.com/COzBnru.jpg"
,
"
http://i.imgur.com/Z3QjilA.jpg"
,
};
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context=
this;
final RemoteViews rv =
new RemoteViews(context.getPackageName(), R.layout.activity_main);
rv.setImageViewResource(R.id.remoteview_notification_icon, R.drawable.ic_launcher);
rv.setTextViewText(R.id.remoteview_notification_headline, "
Headline"
);
rv.setTextViewText(R.id.remoteview_notification_short_message, "
Short Message"
);
// build notification
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("
Content Title"
)
.setContentText("
Content Text"
)
.setContent(rv)
.setPriority( NotificationCompat.PRIORITY_MIN);
final Notification notification =
mBuilder.build();
// set big content view for newer androids
if (android.os.Build.VERSION.SDK_INT >
=
16) {
notification.bigContentView =
rv;
}NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(NOTIFICATION_ID, notification);
notificationTarget =
new NotificationTarget(
context,
rv,
R.id.remoteview_notification_icon,
notification,
NOTIFICATION_ID);
Glide
.with( context.getApplicationContext() ) // safer!
.load( eatFoodyImages[3] )
.asBitmap()
.into( notificationTarget );
}
}
步骤:
- 代码中我们首先定义一个RemoteViews 加载和设置值,
- 接着我们自定义了一个notification并将rv作为content传入,
- 接这new NotificationTarget ()将rv,notificaiton传入,
- 最后将配置好的notificationTarget 传入Glide.into()即可
如果你的程序中有widgets并且有图片来自网络, 使用AppWidgetTarget将是非常方便的, 下面看一个实例;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.AppWidgetTarget;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.widget.RemoteViews;
public class FSAppWidgetProvider extends AppWidgetProvider {private AppWidgetTarget appWidgetTarget;
@
Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {RemoteViews rv =
new RemoteViews(context.getPackageName(), R.layout.activity_main);
appWidgetTarget =
new AppWidgetTarget( context, rv,R.id.remoteview_notification_icon, appWidgetIds );
Glide
.with( context.getApplicationContext() ) // safer!
.load( MainActivity.eatFoodyImages[3] )
.asBitmap()
.into( appWidgetTarget );
pushWidgetUpdate(context, rv);
}public static void pushWidgetUpdate(Context context, RemoteViews rv) {
ComponentName myWidget =
new ComponentName(context, FSAppWidgetProvider.class);
AppWidgetManager manager =
AppWidgetManager.getInstance(context);
manager.updateAppWidget(myWidget, rv);
}
}
重要行是声明appWidgetTarget对象和Glide的构建。好消息是AppWidgetTarget你不需要进一步覆盖onResourceReady方法。Glide自动为你做好了。非常好!
十二、Glide — Exceptions: Debugging and Error Handling Local Debugging
Glide的GeneralRequest类提供了一个方法来设置log级别。不幸的是,你不能容易的使用。然而,有一个非常简单的方法得到Glide的debug log。你所要做的就是通过使用命令行 adb shell 来激活它。打开终端,使用以下命令:
adb shell setprop log.tag.GenericRequest DEBUG
最后一个字段DEBUG是log等级, 有如下几种:
- VERBOSE
- DEBUG
- INFO
- WARN
- ERROR
例如你有一个图片不存在的错误, 它会这样输出:
io.futurestud.tutorials.glide D/GenericRequest: load failed
io.futurestud.tutorials.glide D/GenericRequest: java.io.IOException: Request failed 404: Not Found
...
你已经猜到了, 上述只能有错误在才能调试测试app, 所以下面我们将讲解回调
General Exception Logging
Glide不提供直接访问GenericRequest类设置log记录,但是你可以捕获异常,以防出现错误的请求。例如,如果一个图像不可用,Glide(默默地)会抛出一个异常并会将drawable显示在你指定的. error()中。如果你明确想知道异常信息,你可以创建一个监听器并将其传递给.listener()方法:
为了防止被回收, 我们必须将它定义在域字段
private RequestListener<
String, GlideDrawable>
requestListener =
new RequestListener<
String, GlideDrawable>
() {
@
Override
public boolean onException(Exception e, String model, Target<
GlideDrawable>
target, boolean isFirstResource) {
// todo log exception// important to return false so the error placeholder can be placed
return false;
}@
Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<
GlideDrawable>
target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
};
在onException方法()您可以捕获问题,决定你需要做什么,例如需要进行log记录。如果Glide处理结果,如显示一个错误占位符, 你应该在onException方法返回false:
Glide
.with( context )
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.listener( requestListener )
.error( R.drawable.cupcake )
.into( imageViewPlaceholder )
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Android Studio 2.2.2导入Eclipse中创建的项目
- Qt for Android之Hello World
- Android开发--布局
- Android - Style问题
- 关于编译Android源码
- Android NDK常见配置问题的解决方案
- Android MonoGame坑记
- Android入门开发之Linearlayout布局
- MPAndroidChart 教程