标签:visual contain actionbar border obj 空间 php test follow
图片框架是在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张图片,是不是要苦等几分钟?这显然是不行的。
我们能够这么做:
用户每时每刻都仅仅是浏览部分(即屏幕停留的地方)。那么已滑过或者未滑到的位置就不是必需载入。
这是一个比較直接有效的思路。
举报
2条评论