Picassoを使用してAndroidアプリに画像を表示しています:
/**
* load image.This is within a activity so this context is activity
*/
public void loadImage (){
Picasso picasso = Picasso.with(this);
picasso.setDebugging(true);
picasso.load(quiz.getImageUrl()).into(quizImage);
}
デバッグを有効にすると、常に赤と緑のいずれかが表示されますが、黄色は表示されません
次回同じ画像をロードし、インターネットが利用できない場合、画像はロードされません。
質問:
これは私がやったことです。うまくいく。
まず、OkHttpをappモジュールのgradleビルドファイルに追加します。
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp3:okhttp:3.10.0'
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
次に、Application
を拡張するクラスを作成します
import Android.app.Application;
import com.jakewharton.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
public class Global extends Application {
@Override
public void onCreate() {
super.onCreate();
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE));
Picasso built = builder.build();
built.setIndicatorsEnabled(true);
built.setLoggingEnabled(true);
Picasso.setSingletonInstance(built);
}
}
次のようにマニフェストファイルに追加します。
<application
Android:name=".Global"
.. >
</application>
通常どおりにピカソを使用します。変更なし。
編集:
キャッシュされた画像のみを使用する場合。このようにライブラリを呼び出します。 networkPolicyを追加しない場合、イメージは表示されません完全にオフラインで起動キャッシュされていてもであることに気付きました。以下のコードは問題を解決します。
Picasso.with(this)
.load(url)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView);
編集#2
上記のコードの問題は、キャッシュをクリアすると、Picassoがキャッシュでオフラインで検索を続けて失敗することです。次のコード例では、ローカルキャッシュを調べ、オフラインで見つからない場合はオンラインになり、キャッシュを補充します。
Picasso.with(getActivity())
.load(imageUrl)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError() {
//Try again online if cache failed
Picasso.with(getActivity())
.load(posts.get(position).getImageUrl())
.error(R.drawable.header)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
}
@Override
public void onError() {
Log.v("Picasso","Could not fetch image");
}
});
}
});
1)最初の質問の答え: With with()メソッドのPicasso Doc
With()から返されるグローバルなデフォルトPicassoインスタンスは、ほとんどの実装に適したデフォルトで自動的に初期化されます。
- 使用可能なアプリケーションRAMの15%のLRUメモリキャッシュ
- 最大50MBのストレージ領域が2%で、5MB以上のディスクキャッシュ。
しかし、グローバルなデフォルトのピカソのDisk Cache
操作は、API 14+でのみ利用可能です
2)2番目の質問の答え:Picasso
はHTTP
クライアント要求をDisk Cache
操作に使用しますSo独自のhttp request header
にCache-Control
を持つプロパティmax-age
を作成し、デフォルトのピカソの代わりに独自の静的ピカソインスタンスを作成できます
1] HttpResponseCache (注:API 13+でのみ機能します)
2] OkHttpClient (すべてのAPIで動作)
OkHttpClient
を使用して独自の静的ピカソクラスを作成する例:
最初に新しいクラスを作成して、独自のシングルトンpicasso
オブジェクトを取得します
import Android.content.Context;
import com.squareup.picasso.Downloader;
import com.squareup.picasso.OkHttpDownloader;
import com.squareup.picasso.Picasso;
public class PicassoCache {
/**
* Static Picasso Instance
*/
private static Picasso picassoInstance = null;
/**
* PicassoCache Constructor
*
* @param context application Context
*/
private PicassoCache (Context context) {
Downloader downloader = new OkHttpDownloader(context, Integer.MAX_VALUE);
Picasso.Builder builder = new Picasso.Builder(context);
builder.downloader(downloader);
picassoInstance = builder.build();
}
/**
* Get Singleton Picasso Instance
*
* @param context application Context
* @return Picasso instance
*/
public static Picasso getPicassoInstance (Context context) {
if (picassoInstance == null) {
new PicassoCache(context);
return picassoInstance;
}
return picassoInstance;
}
}
Picasso.With()
の代わりに独自のシングルトンpicasso
オブジェクトを使用する
PicassoCache.getPicassoInstance(getContext()).load(imagePath).into(imageView)
3)3番目の質問に対する答え:ディスクキャッシュ操作にディスクアクセス許可は必要ありません
参考文献: ディスクキャッシュに関するGithubの問題 、2つの質問に答えました @ jake-wharton -> Question1 および Question2
キャッシングの場合、OkHttpinterceptorsを使用して、キャッシングポリシーを制御します。 OkHttpライブラリに含まれているこのサンプルをご覧ください。
RewriteResponseCacheControl.Java
これをピカソで使用する方法です-
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder().header("Cache-Control", "max-age=" + (60 * 60 * 24 * 365)).build();
}
});
okHttpClient.setCache(new Cache(mainActivity.getCacheDir(), Integer.MAX_VALUE));
OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient);
Picasso picasso = new Picasso.Builder(mainActivity).downloader(okHttpDownloader).build();
picasso.load(imageURL).into(viewHolder.image);
1)デフォルトではピカソにキャッシュがあります(アーメドハンディの回答を参照)
2)本当にディスクキャッシュとネットワークから画像を取得する必要がある場合は、独自のダウンローダーを作成することをお勧めします。
public class OkHttpDownloaderDiskCacheFirst extends OkHttpDownloader {
public OkHttpDownloaderDiskCacheFirst(OkHttpClient client) {
super(client);
}
@Override
public Response load(Uri uri, int networkPolicy) throws IOException {
Response responseDiskCache = null;
try {
responseDiskCache = super.load(uri, 1 << 2); //NetworkPolicy.OFFLINE
} catch (Exception ignored){} // ignore, handle null later
if (responseDiskCache == null || responseDiskCache.getContentLength()<=0){
return super.load(uri, networkPolicy); //user normal policy
} else {
return responseDiskCache;
}
}
}
そして、メソッドOnCreateのアプリケーションシングルトンでは、picassoで使用します。
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setCache(new Cache(getCacheDir(), 100 * 1024 * 1024)); //100 MB cache, use Integer.MAX_VALUE if it is too low
OkHttpDownloader downloader = new OkHttpDownloaderDiskCacheFirst(okHttpClient);
Picasso.Builder builder = new Picasso.Builder(this);
builder.downloader(downloader);
Picasso built = builder.build();
Picasso.setSingletonInstance(built);
3)デフォルトのアプリケーションキャッシュフォルダーにアクセス許可は必要ありません
最新のバージョン2.71828の場合これらはあなたの答えです。
Q1:ローカルディスクキャッシュがありませんか?
A1:Picassoにはデフォルトのキャッシュがあり、リクエストフローは次のようになります
App -> Memory -> Disk -> Server
最初に画像に出会ったところはどこでも、その画像を使用してからリクエストフローを停止します。応答フローはどうですか?心配しないでください、ここにあります。
Server -> Disk -> Memory -> App
デフォルトでは、拡張保持キャッシュのために最初にローカルディスクに保存されます。次に、メモリ、キャッシュのインスタンス使用量。
これを有効にすると、Picassoの組み込みインジケーターを使用して、画像が形成される場所を確認できます。
Picasso.get().setIndicatorEnabled(true);
写真の左上に旗が表示されます。
Q2:同じイメージを複数回使用するため、ディスクキャッシュを有効にするにはどうすればよいですか?
A2:有効にする必要はありません。これがデフォルトです。
あなたがする必要があるのは、画像を常に新鮮にしたいときにDISABLEです。 2方向の無効化されたキャッシュがあります。
.memoryPolicy()
をNO_CACHEおよび/またはNO_STOREおよびフローは次のようになります。NO_CACHEは、メモリからの画像の検索をスキップします。
App -> Disk -> Server
NO_STOREは、最初にイメージをロードするときにメモリ内のイメージの保存をスキップします。
Server -> Disk -> App
.networkPolicy()
をNO_CACHEおよび/またはNO_STOREおよびフローは次のようになります。NO_CACHEは、ディスクからの画像の検索をスキップします。
App -> Memory -> Server
NO_STOREは、最初のイメージのロード時にディスク内のイメージの保存をスキップします。
Server -> Memory -> App
DISABLEどちらでもない場合、キャッシュイメージは完全にありません。以下に例を示します。
Picasso.get().load(imageUrl)
.memoryPolicy(MemoryPolicy.NO_CACHE,MemoryPolicy.NO_STORE)
.networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE)
.fit().into(banner);
キャッシュも保存もまったくないフローは、このようになります。
App -> Server //Request
Server -> App //Response
そのため、アプリのストレージ使用量を最小化するためにこれが必要になる場合があります。
Q:Androidマニフェストファイルにディスクアクセス許可を追加する必要がありますか?
A:いいえ。ただし、HTTPリクエストにインターネットアクセス許可を追加することを忘れないでください。
私はこのコードを使用して作業しました。
public static void makeImageRequest(final View parentView,final int id, final String imageUrl) {
final int defaultImageResId = R.mipmap.user;
final ImageView imageView = (ImageView) parentView.findViewById(id);
Picasso.with(context)
.load(imageUrl)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
Log.v("Picasso","fetch image success in first time.");
}
@Override
public void onError() {
//Try again online if cache failed
Log.v("Picasso","Could not fetch image in first time...");
Picasso.with(context).load(imageUrl).networkPolicy(NetworkPolicy.NO_CACHE)
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE).error(defaultImageResId)
.into(imageView, new Callback() {
@Override
public void onSuccess() {
Log.v("Picasso","fetch image success in try again.");
}
@Override
public void onError() {
Log.v("Picasso","Could not fetch image again...");
}
});
}
});
}
Application.onCreate
に次のコードを追加して、通常どおり使用します
Picasso picasso = new Picasso.Builder(context)
.downloader(new OkHttp3Downloader(this,Integer.MAX_VALUE))
.build();
picasso.setIndicatorsEnabled(true);
picasso.setLoggingEnabled(true);
Picasso.setSingletonInstance(picasso);
最初に画像をキャッシュする場合は、ProductImageDownloader.doBackground
でこのようなことをしてください
final Callback callback = new Callback() {
@Override
public void onSuccess() {
downLatch.countDown();
updateProgress();
}
@Override
public void onError() {
errorCount++;
downLatch.countDown();
updateProgress();
}
};
Picasso.with(context).load(Constants.imagesUrl+productModel.getGalleryImage())
.memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback);
Picasso.with(context).load(Constants.imagesUrl+productModel.getLeftImage())
.memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback);
Picasso.with(context).load(Constants.imagesUrl+productModel.getRightImage())
.memoryPolicy(MemoryPolicy.NO_CACHE).fetch(callback);
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(errorCount == 0){
products.remove(productModel);
productModel.isDownloaded = true;
productsDatasource.updateElseInsert(productModel);
}else {
//error occurred while downloading images for this product
//ignore error for now
// FIXME: 9/27/2017 handle error
products.remove(productModel);
}
errorCount = 0;
downLatch = new CountDownLatch(3);
if(!products.isEmpty() /*&& testCount++ < 30*/){
startDownloading(products.get(0));
}else {
//all products with images are downloaded
publishProgress(100);
}
通常のように、またはディスクキャッシュを使用して画像を読み込みます
Picasso.with(this).load(Constants.imagesUrl+batterProduct.getGalleryImage())
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.GalleryDefaultImage)
.error(R.drawable.GalleryDefaultImage)
.into(viewGallery);
注意:
赤色は、画像がネットワークから取得されることを示します。
緑色は、画像がキャッシュメモリから取得されることを示します。
青色は、イメージがディスクメモリから取得されることを示します。
アプリをリリースする前に、false
picasso.setLoggingEnabled(true);
を削除または設定し、必要でない場合はpicasso.setIndicatorsEnabled(true);
を設定します。ありがとう