美文网首页Android实战Android开发
【译】使用标签实现图像加载的分组管理

【译】使用标签实现图像加载的分组管理

作者: 小鄧子 | 来源:发表于2016-06-20 02:34 被阅读223次

    Picasso的标签概念

    在上一篇博客中,你已经了解了如何为特定的图像请求分配优先级。因为你可能在同一时刻取消,暂停或者恢复多个图像请求,因此之前的那些技巧或许不能完全满足你的要求。如果你的视图变化很快,那么对于取消较早的图像加载,已经离开屏幕的,以及为新的视图开启图像加载来说是非常有用的。幸运的是,Picasso提供了.tag()函数,用来实现这些需求。

    .tag(Object object)可以传入任何java对象作为参数。因此,你可以基于任何逻辑来建立你的图像请求组。关于图像加载分组,需要关注以下几点:

    • 使用.pauseTag()暂停请求
    • 使用.resumeTag()恢复请求
    • 使用.cancelTag()取消请求

    基本来讲,无论何时,你需要取消或者暂停一个甚至多个图像加载时,首先应该为这些Picasso请求添加标签,然后调用合适的方法。这听起来可能有些抽象,让我们看一些示例吧。

    示例#1:.pauseTag()和.resumeTag()

    这个示例演示了如何在一个标准的ListView中使用标签。让我们想象一个收件箱的ListView,用来展示收到的消息以及发送者。发送者通过他们的头像来呈现。

    试想如下场景:用户正在寻找一个过时的消息,并且快速的向上翻滚列表。ListView的自身设计能够快速的对条目进行回收和重用。如果实现了正确的adapter,那么用户体验将非常顺滑。然而,由于用户滑动速度太快,Picasso一次又一次的尝试为每个单元条目启动图像加载请求,然后又不得不立刻取消该加载请求。

    更有效的方式应该是暂停所有的图像加载,直到停止滚动。用户不会感受到任何不同,但应用却大大减少了请求数量。

    实现起来也非常简单。首先,为Picasso请求添加标签:

    Picasso
        .with(context)
        .load(UsageExampleListViewAdapter.eatFoodyImages[0])
        .tag("Profile ListView") // can be any Java object
        .into(imageViewWithTag);
    

    其次,实现一个AbsListView.OnScrollListener接口,并重写onScrollStateChanged()函数:

    @Override
      public void onScrollStateChanged(AbsListView view, int scrollState) {
        final Picasso picasso = Picasso.with(context);
    
        if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
              picasso.resumeTag(context);
        } else {
              picasso.pauseTag(context);
        }
      }
    

    最后,设置这个监听回调到ListView上:

    ListView listView = ... // e.g. findById()
    listView.setOnScrollListener(onScrollListener);
    

    ListView处于SCROLL_STATE_FLING状态时,暂停所有的请求。如果ListView处于SCROLL_STATE_IDLE或者SCROLL_STATE_TOUCH_SCROLL状态,再恢复这些请求。

    以上示例中的代码,摘自于Picasso官方实例工程

    示例#2:cancelTag()

    上面所涉及的ListView代码示例,并没有使用到cancelTag()函数。让我们试想另一个场景。你实现了一个购物车,以图片条目的形式来展示所有被选中的商品。一旦用户点击“结算”按钮,立即弹出ProgressDialog并向服务器发送请求来验证本次事务的有效性。当用户点击“结算”后,之前的条目列表有一部分会被隐藏。因此,没有什么理由让图像持续加载,从而为网络,电量和内存等增加无谓的负担。

    我们可以在显示ProgressDialog之后,通过调用.cancelTag()来优化这种行为。

    public void buyButtonClick(View v) {
        // display ProgressDialog
        // ...
    
        // stop image requests
        Picasso
            .with(context)
            .cancelTag("ShoppingCart");
    
        // make 'buy'-request to server
        // ...
    }
    

    总结与提醒

    上面提到的两个示例只不过是标签功能的冰山一角。你可能需要各式各样的对象来作为标签,这完全取决于你的用例场景。这篇博客中使用的标签类型是String,但是不局限于此,你完全可以使用任何类型。有些时候可能会使用Context(或Activity)作为标签,理论上来讲这是允许的,但是我们应该牢记一下这段摘自官方javaDocs的提醒:

    Picasso will keep a reference to the tag for as long as this tag is paused and/or has active requests. Look out for potential leaks.

    换言之,如果用户离开了一个已经暂停了Picasso请求的Activity,那么GC可能无法回收这个Activity实例。这就造成了内存泄露。

    相关文章

      网友评论

        本文标题:【译】使用标签实现图像加载的分组管理

        本文链接:https://www.haomeiwen.com/subject/fstudttx.html