使用网址显示图片或下载到设备?

时间:2016-10-11 08:31:35

标签: android firebase picasso firebaseui

我使用Firebase UI和RecyclerView卡,每张卡都有文字和小图片(90dp / 90dp)。我没有将图像下载到设备,我得到图像的URI,并使用getDownloadUrl()方法,我得到图像URL并用Picasso显示它。

问题是如果recyclerView中有很多记录,如果我滚动到页面的底部或顶部,则需要一些时间来刷新图像。

例如,如果我快速滚动到底部,它会显示页面顶部的图像一秒钟,然后显示需要的真实图像。

我想知道将图像下载到设备是否是今天流行加载图像的流行方式?因为我知道有些应用会这样做。

谢谢。

1 个答案:

答案 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);

其余部分由毕加索负责。