<html>

图片框架是在Android开发上占领了非常重要的位置。我们经常使用的有Gilde,picasso,Fresco等,在功能上,这些框架已经基本满足我们的开发需求,在此不多讲它们的操作原理。如今我们開始学习自制一个网络图片载入框架

在做之前,我们先了解一下线程池的操作流程


  线程池的特点:
  1)提升性能。创建和消耗对象费时费CPU资源
  2)防止内存过度消耗。控制活动线程的数量。防止并发线程过多。
  使用条件:
     如果在一台server完毕一项任务的时间为T
     T1 创建线程的时间    
     T2 在线程中运行任务的时间,包含线程间同步所需时间    
     T3 线程销毁的时间     
     显然T = T1+T2+T3。注意这是一个极度简化的如果。
     能够看出T1,T3是多线程本身的带来的开销,我们渴望降低T1,T3所用的时间,从而降低T的时间。但一些线程的使用者并没有注意到这一点,所以在程序中频繁的创建或销毁线程,这导致T1和T3在T中占有相当比例。

显然这是突出了线程的弱点(T1,T3),而不是长处(并发性)。
     线程池技术正是关注怎样缩短或调整T1,T3时间的技术,从而提高server程序性能的。它把T1,T3分别安排在server程序的启动和结束的时间段或者一些空暇的时间段。这样在server程序处理客户请求时。不会有T1,T3的开销了。
     线程池不仅调整T1,T3产生的时间段。并且它还显著降低了创建线程的数目。

     在Android中当同一时候并发多个网络线程时,引入线程池技术会极大地提高APP的性能。


以下以一实例做介绍:

1.ImageTask

注:此处的sleep 仅仅是为了測试效果,下同,没有别的用意

try{
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }

package com.example.officer.yycimageloader.tools;

import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.support.v4.util.LruCache;
import android.util.Log;

import com.example.officer.yycimageloader.MainActivity;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by officer on 2015/12/15.
 */
public class ImageTask implements Runnable{
    /**
     * 图片任务
     */
    //缓存存放图片
    private LruCache<String, Bitmap> mLruCache;

    public static final String TAG=ImageTask.class.getSimpleName();
    String name;
    Context mContext;
    public ImageTask(String name,Context context){
        this.name=name;
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        int cacheSize = maxMemory / 8;
        mLruCache = new LruCache<String, Bitmap>(cacheSize);
        mContext=context;
    }
    @Override
    public void run() {
//        // 读取uri所在的图片
//        try {
//            Uri uri=Uri.parse(name);
//            Bitmap bitmap = MediaStore.Images.Media.
//                    getBitmap(mContext.getContentResolver(), uri);
//            mLruCache.put("bit",bitmap);
//        }catch (Exception e){
//            e.printStackTrace();
//        }
        try{
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }

        Log.v(TAG,name+"  完毕载入");
    }



    public String getName(){
        return this.name;
    }


}
2.ImageTaskManager
package com.example.officer.yycimageloader.tools;

import android.util.Log;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;

/**
 * Created by officer on 2015/12/15.
 */
public class ImageTaskManager {
    /**
     * 图片任务管理
     */
    public static final String TAG=ImageTaskManager.class.getSimpleName();
    //请求线程队列
    private LinkedList<ImageTask> imageTasks;
    //任务不能反复
    private Set<String> taskIdSet;

    private static ImageTaskManager imageTaskManager;

    public static synchronized ImageTaskManager getInstance(){
        if (null == imageTaskManager) {
            imageTaskManager = new ImageTaskManager();
        }
        return imageTaskManager;
    }

    private ImageTaskManager() {
        imageTasks = new LinkedList<ImageTask>();
        taskIdSet = new HashSet<String>();
    }

    public void addImageTask(ImageTask downloadTask){
        synchronized (imageTasks) {
            if (!isTaskRepeat(downloadTask.getName())) {
                imageTasks.addLast(downloadTask);
            }
        }
    }

    public boolean isTaskRepeat(String fileId) {
        synchronized (taskIdSet) {
            if (taskIdSet.contains(fileId)) {
                return true;
            } else {
               Log.v(TAG,"任务管理  加入任务" + fileId);
                taskIdSet.add(fileId);
                return false;
            }
        }
    }

    public ImageTask getImageTask() {
        synchronized (imageTasks) {//强制同步
            if (imageTasks.size() > 0) {
                Log.v(TAG,"任务管理   " + "取出任务");
                ImageTask imageTask = imageTasks.removeFirst();//先进先出。取出顶部的任务
                return imageTask;
            }
        }
        return null;
    }
}
3.ImageTaskManagerThread

package com.example.officer.yycimageloader.tools;

import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by officer on 2015/12/15.
 */
public class ImageTaskManagerThread implements Runnable{
    /**
     * 线程池
     */

    private ImageTaskManager imageTaskManager;
    private ExecutorService pool;//可重用固定线程数的线程池
    private final int SIZE=10;//线程数
    private final int SLEEP=1000;//轮询时间
    private boolean isStop=false;

    public ImageTaskManagerThread(){
        this.imageTaskManager=ImageTaskManager.getInstance();//获得实例
        pool= Executors.newFixedThreadPool(SIZE);
    }
    @Override
    public void run() {
        while(!isStop){
            ImageTask imageTask=imageTaskManager.getImageTask();
            if(imageTask!=null){
                pool.execute(imageTask);
            }else{
                try{
                    Thread.sleep(SLEEP);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        if(isStop){//关闭线程池
            pool.shutdown();
        }
    }

    public void setStop(boolean isStop){
        this.isStop=isStop;
    }
}

执行的MainActivity

package com.example.officer.yycimageloader;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;

import com.example.officer.yycimageloader.tools.ImageTask;
import com.example.officer.yycimageloader.tools.ImageTaskManager;
import com.example.officer.yycimageloader.tools.ImageTaskManagerThread;
import com.example.officer.yycimageloader.tools.ImageUtil;
import com.example.officer.yycimageloader.tools.SearchImage;

import java.io.File;
import java.util.List;


public class MainActivity extends ActionBarActivity {

    Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn=(Button)findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              //  test_pool();
                synchronized (this) {
                   // test_find();
                    test_pool();
                }
            }
        });
    }

    private void test_find(){
        SearchImage s=new SearchImage(this);
    }


    /**
     * 线程池
     */
    private void  test_pool(){
        ImageTaskManager imageTaskManager=ImageTaskManager.getInstance();
        ImageTaskManagerThread imageTaskManagerThread=new ImageTaskManagerThread();
        new Thread(imageTaskManagerThread).start();

//        File f= ImageUtil.getDirName();
//        List<String> list=ImageUtil.getPicName();

        String []items={"图1"
                ,"图2",
                "图3",
                "图4",
                "图5",
                "图6"};

        for(int i=0;i<items.length;i++){
            imageTaskManager.addImageTask(new ImageTask(items[i],this));//加入任务进线程池
                try{
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

如上:

我们将  图1至图6放入任务队列中,以下是打印出的结果:


那么回到我们的主线。继续写图片载入框架。

我们经常遇到的问题是:

用户的高速操作。必须保证浏览图片的流畅。

设想一个应用场景:

用户浏览某网络资源相冊。在GridView中呈现图片。用户高速滑动至底部。假设全然依照顺序来载入的话。会是怎么一个情景呢?比如1000张图片,是不是要苦等几分钟?这显然是不行的。

我们能够这么做:

用户每时每刻都仅仅是浏览部分(即屏幕停留的地方)。那么已滑过或者未滑到的位置就不是必需载入。

这是一个比較直接有效的思路。





版权声明:本文为博主原创文章。未经博主同意不得转载。

举报

  • 本文已收录于下面专栏:

相关文章推荐

Android 框架练成 教你打造高效的图片载入框架

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41874561,本文出自:【张鸿洋的博客】1、概述优秀的图片载入框架不要太多,什么...

【Android图片载入框架】制作自己的图片载入框架

好久没写博客了。接着上一篇的内容。 以下将一些网络图片路径放入线程池操作 /** * 线程池 */ private void test_pool(){ ...

Android三大图片框架的比較

基本的图片框架:Fresco、Glide、Picasso。因为ImageLoader现已不再更新,这里将不再细说 Fresco: 特点: 1、最大的优势便在于5.0下面(最低2.3) b...

Android图片载入框架基本使用方法

本文主要讲述了Android Universal Image Loader,Picasso,Glide。Fresco的一些基本使用方法

Android开源图片载入框架

同事写的一篇文章,mark下。 1. 開始        本文主要介绍了android现下流行的图片载入库中的3个。通过读取源代码,比較设计架构。来总结移动应用中图片载入的共同特点,同一时候比較...

Android图形架构实现分析总结

Android图形架构分析总结总结事实上现方案,主要包含了下面几个关键点: 1、直接FrameBuffer的訪问方式,并对FrameBuffer採用双缓存技术     没有採用X-Server等方案。直...

Android图形框架简单介绍

一、Android图形框架简单介绍    Android图形框架可分为两部分:用于应用程序图形UI显示的上层View体系和用于图形渲染的底层图形驱动,可用下图表示          如图。View/GLS...
  • gogor
  • gogor
  • 2011-07-26 15:11
  • 7355

Android主流图片框架浅析

一、UIL——UniversalImageLoaderUIL能够算是老牌最火的图片载入库了,使用过这个框架的项目能够说多到教你做人,我第一次把第三方开源图片载入框架增加项目中的就是这个了。当时感觉瞬间...

Android图片载入框架

开发一个简洁而有用的Android图片载入缓存框架,并在内存占用与载入图片所需时间这两个方面与主流图片载入框架之中的一个Universal Image Loader做出比較,来帮助我们量化这个框架的性能。通...

Android 视图框架系列1/3——View视图框架

View 是 Android 开发中最基础也是最本质的视图基类。在开发中要想实现自己定义的控件,大多都是直接继承自View,由于那些能够继承View的子类(甚至是子类的子类)的控件事实上都是修改动改,仅仅是...
  • 微博
    微信
    QQ
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多仅仅同意输入30个字)

posted @ 2017-08-20 18:36  zhchoutai  阅读(146)  评论(0编辑  收藏  举报