我使用Firebase UI和RecyclerView卡,每张卡都有文字和小图片(90dp / 90dp)。我没有将图像下载到设备,我得到图像的URI,并使用getDownloadUrl()
方法,我得到图像URL并用Picasso显示它。
问题是如果recyclerView中有很多记录,如果我滚动到页面的底部或顶部,则需要一些时间来刷新图像。
例如,如果我快速滚动到底部,它会显示页面顶部的图像一秒钟,然后显示需要的真实图像。
我想知道将图像下载到设备是否是今天流行加载图像的流行方式?因为我知道有些应用会这样做。
谢谢。
答案 0 :(得分:1)
例如,如果我快速滚动到底部,它会在页面顶部显示一秒钟的图像,然后显示需要在那里的真实图像。
之所以看到较新的位置会显示较旧的图像,是因为RecylerView会回收其视图。因此,在以下代码中getDownloadUrl()
的时间,
getDownloadUrl().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Picasso.with(context).
load(task.getResult())
into(holder.imageView);
}
});
已解决,可以将预期的视图回收以在其他位置显示内容(对于您而言,当您向下滚动时,将在列表底部显示一个较新的项目)。
通常要警惕使用回调在回收站视图适配器的onBindViewHolder
方法内加载任何类型的数据。
我想知道将图像下载到设备是否是当今流行的快速加载图像的方法?因为我知道有些应用程序会这样做。
在本地下载图像内容然后进行显示确实可以提供最佳的用户体验,特别是如果要加载的内容变化不大的话。这也将减少Firebase的计费费用,因为您是按下载的GB计费的。但是您不必手动实现它。
解决方案
首先使用自定义的Firebase请求处理程序来处理诸如gs://somefirebasepath/somefile
之类的Firebase存储URL。 load
方法上的代码实现您的缓存逻辑。
import android.graphics.BitmapFactory;
import android.util.Log;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.StreamDownloadTask;
import com.squareup.picasso.Request;
import com.squareup.picasso.RequestHandler;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutionException;
import static com.squareup.picasso.Picasso.LoadedFrom.NETWORK;
public class FirebasePicassoRequestHandler extends RequestHandler {
@Override
public boolean canHandleRequest(Request data) {
return data.uri != null && "gs".equals(data.uri.getScheme();
}
@Override
public Result load(Request request, int networkPolicy) throws IOException {
//Implement your caching logic here, or load from network as follows
StorageReference gsReference = FirebaseStorage.getInstance().getReferenceFromUrl(request.uri.toString());
StreamDownloadTask mStreamTask;
InputStream inputStream ;
mStreamTask = gsReference.getStream();
try {
inputStream = Tasks.await(mStreamTask).getStream();
Log.i("FireBaseRequestHandler", "Loaded " + gsReference.getPath() );
return new Result(BitmapFactory.decodeStream(inputStream), NETWORK);
} catch (ExecutionException e) {
throw new IOException();
} catch (InterruptedException e) {
throw new IOException();
}
}
}
并使用Picasso.Builder
构建Picasso实例。并将您的自定义处理程序添加到Picasso。 (可选)您可以添加错误侦听器,以帮助调试处理程序出现的问题。
Picasso.Builder builder = new Picasso.Builder(this);
builder.addRequestHandler(new FirebasePicassoRequestHandler());
builder.listener(new Picasso.Listener() {
@Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
Log.e("Picasso", "Failure for " + uri.toString(), exception);
}
});
Picasso.setSingletonInstance(builder.build());
现在,我们不再需要解析适配器中的firebase存储url。在执行加载请求之前,我们将取消对该ImageView
的所有待处理请求,然后按如下所示加载firebase uri
//inside your onBindViewHolder method
Picasso.with(context).cancelRequest(imageViewInstance);
Picasso.with(context)
.load("gs://somefirebase/imagefile")
.into(imageViewInstance);
其余部分由毕加索负责。