我特别关注CardScrollAdapter
中的这种情况,但在将卡发布到时间线时,在LiveCard情况下也很清楚。有没有办法使用齐射或任何其他网络库来使用通用Card
类加载图像?
答案 0 :(得分:3)
虽然你不能直接使用Volley的NetworkImageView
课程Card
(因为Card
管理自己的布局),你应该可以使用Volley中的其他功能来处理延迟加载你的图像。
在高级别,你可以使用这样的方法:
Card
时,如果所需的图像尚未可用(在某处缓存),请最初使用占位符图像。跟踪某处Card
的实例(例如,在适配器中)。file:
URL将其添加到卡中。Card.toView()
以重新生成卡片的观看次数并根据需要更新您的用户界面。答案 1 :(得分:2)
"更新:加载包含10个以上图像的列表会减慢速度。我不确定是否因为在每次图像加载后调用updateViews()或者是什么。"
确保您的CardScrollAdapter getView()方法不会尝试在每次调用时加载图像。
例如:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if ( getCards() == null ) return null;
MyCard card = getCards().get(position);
if (! card.isImageLoaded()) {
CardImageLoader.loadCardImage(...);
}
return card.toView();
}
答案 2 :(得分:1)
好的,有办法做到这一点,但它有点令人费解。诀窍是你不能在适配器的getView()
中调度异步图像加载任务,就像你通常在android中那样。如果您尝试,则会在您准备加载图片时发现ImageView
返回的card.toView()
将为GC。似乎是GDK中的一个错误,或者它可能是它的设计方式,我不确定。
当前的XE12 GDK仅支持card.addImage(Uri)
本地资源和文件URI的额外复杂性。因此,除了上面的警告之外,您还必须将图像下载到文件中,然后才能将其添加为卡片图像。
我将使用Android Universal Image Loader协助进行图片下载任务。这是完成所有工作的课程:
public class CardImageLoader {
private static final String TAG = CardImageLoader.class.getSimpleName();
private static final boolean DEBUG = false;
private static final int MAX_IMAGE_LOAD_RETRIES = 3;
private static Map<String, Integer> mLoadFailures = new ConcurrentHashMap<String, Integer>();
public static void init(Context context) {
File cacheDir = StorageUtils.getCacheDirectory(context);
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheOnDisc(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.discCache(new UnlimitedDiscCache(cacheDir))
.defaultDisplayImageOptions(options)
.build();
ImageLoader.getInstance().init(config);
}
public static void loadCardImage(final Card card, final String imageUri, final CardScrollView cardScrollView) {
card.setImageLayout(Card.ImageLayout.FULL);
int failures = mLoadFailures.containsKey(imageUri) ? mLoadFailures.get(imageUri) : 0;
if (failures > MAX_IMAGE_LOAD_RETRIES) {
if (DEBUG) Log.i(TAG, "Exceeded max retries on imageUri=" + imageUri);
return;
}
File file = ImageLoader.getInstance().getDiscCache().get(imageUri);
if (file != null && file.exists() && file.length() > 0) {
Uri uri = Uri.fromFile(file);
card.addImage(uri);
}
else {
ImageLoader.getInstance().loadImage(imageUri, new ImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
if (DEBUG) Log.i(TAG, "onLoadingStarted");
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
if (DEBUG) Log.i(TAG, "onLoadingFailed");
int failures = mLoadFailures.containsKey(imageUri) ? mLoadFailures.get(imageUri) : 0;
mLoadFailures.put(imageUri, ++failures);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
File file = ImageLoader.getInstance().getDiscCache().get(imageUri);
if (DEBUG) Log.i(TAG, "onLoadingComplete uri=" + imageUri + " file=" + file
+ " len=" + (file == null ? 0 : file.length()));
if (file != null && file.exists() && file.length() > 0) {
if (DEBUG) Log.i(TAG, "onLoadingComplete scheduling update of scroll views");
if (cardScrollView != null)
cardScrollView.updateViews(true);
}
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
if (DEBUG) Log.i(TAG, "onLoadingCancelled");
}
});
}
}
}
这是它的工作原理。在适配器的getView()
中,我们找到了要加载的URL。我们询问图像加载器是否已经缓存了图像。如果有,我们找到本地文件Uri并致电card.addImage(Uri)
,我们就完成了。如果我们没有缓存图像,我们就不能使用正常的图像加载器displayImage()
调用,因为前面描述的原因。相反,我们使用loadImage()' and if successful, ask the
CardScrollView'下载文件以重新显示(不要尝试在此设置卡,即使使用final
变量,也不会发生任何事情)。这将最终导致再次调用getView()
,只有这次文件将被缓存。因此,图像将被添加到卡中,并且您的卡将正确显示。
还会对下载失败进行一些跟踪,以防止在下载失败时出现CardScrollView
重新显示的循环。
你如何使用它?满容易。首先在onCreate()
中,您需要使用以下行初始化图像加载器:
CardImageLoader.init(this);
其次,在适配器getView()
方法中,当您想要在卡中加载图像时,请调用此方法:
CardImageLoader.loadCardImage(card, url, mCardScrollView);
然后你会看到显示图像的卡片。我发现到目前为止只是警告,不要一次加载超过20张图像,否则你可能会遇到性能问题。装载150个碎玻璃,所以要小心。除此之外它一直很好。
更新:我加载了包含10多张图片的列表。我不确定是否是因为在每次图像加载后调用updateViews()
或者是什么。
答案 3 :(得分:1)
“目前的XE12 GDK只支持带有本地资源和文件URI的card.addImage(Uri),这是一个额外的复杂性。所以除了上面的警告,你必须先将图像下载到文件中,然后才能添加它作为卡片图像。“
看起来XE16 +现在支持card.addImage(位图),因此可能不再需要使用文件作为临时缓存。