日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Picasso

發(fā)布時(shí)間:2024/1/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Picasso 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、例子



直接上代碼

如下就是Picasso最簡(jiǎn)單的例子,我們?cè)谑褂玫臅r(shí)候就是這么簡(jiǎn)單,直接with、load、into

// 普通加載圖片Picasso.with(PicassoActivity.this).load("http://n.sinaimg.cn/translate/20160819/9BpA-fxvcsrn8627957.jpg").into(ivPicassoResult1);// 裁剪的方式加載圖片Picasso.with(PicassoActivity.this).load("http://n.sinaimg.cn/translate/20160819/9BpA-fxvcsrn8627957.jpg").resize(100,100).into(ivPicassoResult2);// 選擇180度Picasso.with(PicassoActivity.this).load("http://n.sinaimg.cn/translate/20160819/9BpA-fxvcsrn8627957.jpg").rotate(180).into(ivPicassoResult3);

二、原理

首先來看三個(gè)函數(shù),第一個(gè)是with函數(shù),很顯然使用的是單例模式和Builder模式,然后創(chuàng)建一個(gè)Picasso的實(shí)例

public static Picasso with(Context context) {if (singleton == null) {synchronized (Picasso.class) {if (singleton == null) {singleton = new Builder(context).build();}}}return singleton;}
然后load函數(shù),這個(gè)有好幾個(gè),分別針對(duì)的是不同的資源類型

public RequestCreator load(Uri uri) {... } public RequestCreator load(String path) {... } public RequestCreator load(int resourceId) {... }


最后是into函數(shù),這個(gè)函數(shù)還是比較復(fù)雜的一個(gè)函數(shù)

public void into(Target target) {long started = System.nanoTime();checkMain();if (target == null) {throw new IllegalArgumentException("Target must not be null.");}if (deferred) {throw new IllegalStateException("Fit cannot be used with a Target.");}if (!data.hasImage()) {picasso.cancelRequest(target);target.onPrepareLoad(setPlaceholder ? getPlaceholderDrawable() : null);return;}Request request = createRequest(started);String requestKey = createKey(request);if (shouldReadFromMemoryCache(memoryPolicy)) {Bitmap bitmap = picasso.quickMemoryCacheCheck(requestKey);if (bitmap != null) {picasso.cancelRequest(target);target.onBitmapLoaded(bitmap, MEMORY);return;}}target.onPrepareLoad(setPlaceholder ? getPlaceholderDrawable() : null);Action action =new TargetAction(picasso, target, request, memoryPolicy, networkPolicy, errorDrawable,requestKey, tag, errorResId);picasso.enqueueAndSubmit(action); }這里最主要的就是創(chuàng)建一個(gè)Reques對(duì)象,我們前面做的一些封裝和設(shè)置都會(huì)封裝到這個(gè)Request對(duì)象中

檢查我們要顯示的圖片是否可以直接在緩存中獲取,如果有就直接顯示出來好了。

緩存沒命中,那就只能費(fèi)點(diǎn)事把源圖片down下來了。這個(gè)過程是異步的,并且通過一個(gè)Action來完成請(qǐng)求前后的銜接工作。


首先進(jìn)行參數(shù)的設(shè)置,然后創(chuàng)建request請(qǐng)求對(duì)象,最后通過通過action來進(jìn)行圖片的請(qǐng)求。



三、深入

1. 首先看一下構(gòu)造函數(shù)

Picasso(Context context, Dispatcher dispatcher, Cache cache, Listener listener,RequestTransformer requestTransformer, List<RequestHandler> extraRequestHandlers, Stats stats,Bitmap.Config defaultBitmapConfig, boolean indicatorsEnabled, boolean loggingEnabled) {... }我們是通過單例和建造者模式來完成實(shí)例化的,在build的過程中向picasso中傳遞這些參數(shù),自己來靈活的定制


2、看一build函數(shù)中的代碼是什么樣子

public Picasso build() {Context context = this.context;if (downloader == null) {downloader = Utils.createDefaultDownloader(context);}if (cache == null) {cache = new LruCache(context);}if (service == null) {service = new PicassoExecutorService();}if (transformer == null) {transformer = RequestTransformer.IDENTITY;}Stats stats = new Stats(cache);Dispatcher dispatcher = new Dispatcher(context, service, HANDLER, downloader, cache, stats);return new Picasso(context, dispatcher, cache, listener, transformer, requestHandlers, stats,defaultBitmapConfig, indicatorsEnabled, loggingEnabled); }
Downloader:它是一個(gè)接口,規(guī)定了一些通用的方法,這也就意味著,我們可以提供自己的下載器

Cache:Picasso的緩存,這里實(shí)例化的是LruCache,其內(nèi)部使用的是LinkedHashMap

ExecutorService:這里Picasso實(shí)現(xiàn)了自己的PicassoExecutorService,它繼承了ThreadPoolExecutor,也就是Picasso自己維護(hù)了一個(gè)線程池,用于異步加載圖片。

Stats:這個(gè)類只要是維護(hù)圖片的一些狀態(tài)Dispatcher:從名字上就可以判斷出來,這個(gè)類在這里起到了一個(gè)調(diào)度器的作用,圖片要不要開始下載以及下載后Bitmap的返回都是通過這個(gè)調(diào)度器來執(zhí)行的


3、也是通過異步請(qǐng)求的方式來進(jìn)行的

上面的into方法中中最終會(huì)創(chuàng)建一個(gè)action,這個(gè)action里邊包含picasso對(duì)象、目標(biāo)和Request請(qǐng)求等

然后會(huì)調(diào)用enqueueAndSubmit方法,而最終是調(diào)用了Dispatcher的dispatchSubmit方法,也就是我們前面說的,Dispatcher起到了調(diào)度器的作用。在Dispatcher內(nèi)部,Dispatcher定義了DispatcherThread和DispatcherHandler兩個(gè)內(nèi)部類,并在Dispatcher的構(gòu)造函數(shù)中對(duì)他們經(jīng)行了實(shí)例化,所有的調(diào)度也都是通過handler異步的執(zhí)行的,如下是Dispatcher

Dispatcher(Context context, ExecutorService service, Handler mainThreadHandler,Downloader downloader, Cache cache, Stats stats) {this.dispatcherThread = new DispatcherThread();this.dispatcherThread.start();...this.handler = new DispatcherHandler(dispatcherThread.getLooper(), this);... }構(gòu)建實(shí)例之后建立一個(gè) BitmapHunter類來進(jìn)行圖片的加載,這個(gè)類也是繼承Runnable接口的類,加載完成圖片之后怎么去進(jìn)行進(jìn)行主線程的更新是個(gè)問題


4、進(jìn)行圖片的主線程跟新操作

因?yàn)槭钱惒降?#xff0c;最終也是通過消息機(jī)制來進(jìn)行發(fā)送的,同message的方式發(fā)送到主線程中進(jìn)行圖片的渲染和更新的操作

Picasso并不是立即將圖片顯示出來,而是用到了一個(gè)批處理,其實(shí)就是把操作先暫存在一個(gè)list中,等空閑的時(shí)候再拿出來處理,這樣做得好處也是盡量減少主線程的執(zhí)行時(shí)間,一方面防止ANR,另一方面快速返回,響應(yīng)頁面的其他渲染操作,防止卡頓用戶界面。

private void batch(BitmapHunter hunter) {if (hunter.isCancelled()) {return;}batch.add(hunter);if (!handler.hasMessages(HUNTER_DELAY_NEXT_BATCH)) {handler.sendEmptyMessageDelayed(HUNTER_DELAY_NEXT_BATCH, BATCH_DELAY);} }




尊重作者,尊重原創(chuàng),參考文章:


http://www.jianshu.com/p/459c8ca3f337






總結(jié)

以上是生活随笔為你收集整理的Picasso的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。