高仿糗事百科学习(三)NET

高仿糗事百科,是一个典型的cs模式,所以我们获取数据就要通过net,今天我就开始书写关于网络连接方面的书写。
在安卓中,我们将联网请求往往是放在次线程中,如果放在主线程中,将会导致主线程要处理事件太多导致崩溃,而放在次线程中,那么将出现管理线程的问题,于是我们就可以使用一个线程池辅助类ThreadPoolUtils

/**
 * 线程池辅助类,整个应用程序就只有一个线程池去管理线程。
 * 可以设置核心线程数、最大线程数、额外线程空状态生存时间,阻塞队列长度来优化线程池
 */
public class ThreadPoolUtils {
    private ThreadPoolUtils() {
    }

    // 定义核心线程数,并行线程数
    private static int CORE_POOL_SIZE = 3;

    // 线程池最大线程数:除了正在运行的线程额外保存多少个线程
    private static int MAX_POOL_SIZE = 200;

    // 额外线程空闲状态生存时间
    private static int KEEP_ALIVE_TIME = 5000;

    // 阻塞队列。当核心线程队列满了放入的
    // 初始化一个大小为10的泛型为Runnable的队列
    private static BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(10);
    // 线程工厂,把传递进来的runnable对象生成一个Thread
    private static ThreadFactory threadFactory = new ThreadFactory() {
        // 原子型的integer变量生成的integer值不会重复
        private final AtomicInteger ineger = new AtomicInteger();
        @Override
        public Thread newThread(Runnable arg0) {
            return new Thread(arg0, "MyThreadPool thread:"
                    + ineger.getAndIncrement());
        }
    };
    // 当线程池发生异常的时候回调进入
    private static RejectedExecutionHandler handler = new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            // 进行重启操作
        }

    };
    // 线程池ThreadPoolExecutor java自带的线程池
    private static ThreadPoolExecutor threadpool;
    // 静态代码块,在类被加载的时候进入
    static {
        threadpool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
                KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue, threadFactory,
                handler);
    }

    public static void execute(Runnable runnable) {
        threadpool.execute(runnable);
    }
}

有了ThreadPoolUtils我们就可以管理线程
下面开始书写第一个关于网络get请求的请求线程:

public class HttpGetThread implements Runnable {
    private Handler hand;
    private String url;
    private MyGet myGet=new MyGet();
    public HttpGetThread(Handler hand, String endParamerse) {
        this.hand = hand;
        // 拼接访问服务器完整的地址
        url = Model.HTTPURL + endParamerse;
    }

    @Override
    public void run() {
        // 获取我们回调主ui的message
        Message msg = hand.obtainMessage();
        msg = hand.obtainMessage();
        Log.e("liuxiaowei", url);
        try {
            String result = myGet.doGet(url);
            msg.what = 200;
            msg.obj = result;
        } catch (ClientProtocolException e) {
            msg.what = 404;
        } catch (IOException e) {
            msg.what = 100;
        }
        hand.sendMessage(msg);
    }
}

在这个线程中我们主要做了两件事:
一个是通过String result = myGet.doGet(url);这段代码在NET工具类中通过url获取所需要的数据
第二件事是通过handler的message将下载进程与主ui进程进行交互用来更新ui中的数据.

下面就进入myGet工具类:

public String doGet(String url) throws ClientProtocolException, IOException {
        String result = null;// 我们的网络交互返回值
        HttpGet myGet = new HttpGet(url);//網絡請求url
        HttpClient httpClient = new DefaultHttpClient();
        httpClient.getParams().setIntParameter(
        //设置连接超时
        HttpConnectionParams.CONNECTION_TIMEOUT, 5 * 1000);
        //设置socket连接超时
        httpClient.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT,
                30 * 1000);
        HttpResponse httpResponse = httpClient.execute(myGet);
        if (httpResponse.getStatusLine().getStatusCode() == 200) {
            result = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
        }
        return result;
    }

通过调用MyGet工具类获取服务器中的信息,其中谷歌公司对HttpGet进行了屏蔽,我们需要去apache官网去下载httpcilent和httpcore两个jar包进行方法的导入
有了以上的下载线程已经get获取工具,我们还需要在Fragment中进行进程的启动,在HotFragment中我们是在createListModel()方法中进行数据的加载,根据干货、嫩草、文字我们进行url的切换从而访问不同的数据,最后 ThreadPoolUtils.execute(new HttpGetThread(hand, url));通过进程管理工具进行网络进程的使用,其中的hand正是主ui线程的handler.

在handler中我们通过对msg传输的值进行判断是否传输成功,并且通过json解析器进行解析,将消息存进AshamedInfo list中最后通过Adapter的notifychanged通知listView进行数据的更新

上面我们将数据传输写完了,下面我们做图片加载的书写:

/**
 * 控制图片的加载类
 * 列表在滑动过程时,没有图片会进行下载,并保存到sdcard与 imageCaches 当中去,使用软引用进行封装,如果内存不够时
 * 我们的imageCaches 当中的Bitmap对象会被清理掉,图片被释放掉 再次需要加载的时候,先从1级缓存当中获取,如果没有的话,去
 * 本地获取,本地也获取不到的话,去网络下载。 一级缓存作用:对于listview当中刚刚滑动过的item显示的图片进行保存
 * 二级缓存作用:对于listview当中很久前查看的图片或已经被释放掉图片 进行保存
 */
public class LoadImage {
    //下载图片最大并行线程数
    private static int MAX = 5;
    //图片的一级缓存
    private Map<String, SoftReference<Bitmap>> imageCaches = null;
    // 查看本地缓存工具类
    private FileUtiles fileUtiles;
    // android 提供给我们的一个线程池,使用方便
    private ExecutorService threadPools = null;

    // 初始化上面的相关的变量
    public LoadImage(Context ctx) {
        imageCaches = new HashMap<String, SoftReference<Bitmap>>();
        fileUtiles = new FileUtiles(ctx);
    }

    // 加载图片时,入口
    public Bitmap loadImage(final ImageView imageView, final String imageUrl,
                            final ImageDownloadCallBack imageDownloadCallBack) {
        // imageUrl 由于其唯一型,把他作为我们map当中的key
        // 获取图片名称
        final String filename = imageUrl.substring(
                imageUrl.lastIndexOf("/") + 1, imageUrl.length());
        // 图片保存到本地时的地址
        String filepath = fileUtiles.getAbsolutePath() + "/" + filename;
        // 查找一级缓存,看看是否有这张图片
        // 如果map当中有这个key返回一个true
        if (imageCaches.containsKey(imageUrl)) {
            // 找到对应图片软引用的封装
            SoftReference<Bitmap> soft = imageCaches.get(imageUrl);
            // 从软引用当中获取图片
            Bitmap bit = soft.get();
            if (bit != null)
                return bit;
            // 从我们的一级缓存(程序内部获取图片)
        }
        //从二级缓存中获取图片
        if (fileUtiles.isBitmap(filename)) {
            Bitmap bit = BitmapFactory.decodeFile(filepath);
            // 在二级缓存读取的时候直接添加到一级缓存当中
            imageCaches.put(imageUrl, new SoftReference<Bitmap>(bit));
            return bit;
        }
        // 一级缓存,二级缓存都不存在,直接到网络加载
        if (imageUrl != null && !imageUrl.equals("")) {
            if (threadPools == null) {
                // 实例化我们的线程池
                threadPools = Executors.newFixedThreadPool(MAX);
            }
            // 下载回图片回调Handler
            final Handler hand = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // 如果图片下载成功,并且回调对象不为空时
                    if (msg.what == 111 && imageDownloadCallBack != null) {
                        Bitmap bit = (Bitmap) msg.obj;
                        // 调用回调自定义适配器的接口方法传递数据
                        imageDownloadCallBack.onImageDownload(imageView, bit);
                    }
                    super.handleMessage(msg);
                }
            };

            // 下载图片线程
            Thread thread = new Thread() {
                Bitmap bit = null;

                public void run() {
                    // 网络下载时的字节流
                    InputStream inputStream = DownBitmap.getInstance()
                            .getInputStream(imageUrl);
                    //图片压缩到原来一般
                    BitmapFactory.Options op=new BitmapFactory.Options();
                    op.inSampleSize=6;
                    if(Model.IMGFLAG)
                        op.inSampleSize = 1;
                    Bitmap bit = BitmapFactory.decodeStream(inputStream, null,
                            op);
                    if (bit != null) {
                        // 添加到一级缓存当中
                        imageCaches.put(imageUrl,
                                new SoftReference<Bitmap>(bit));
                        // 添加到二级缓存
                        fileUtiles.saveBitmap(filename, bit);
                        // 传递给Handler
                        Message msg = hand.obtainMessage();
                        msg.what = 111;
                        msg.obj = bit;
                        hand.sendMessage(msg);
                    }
                }
            };

            threadPools.execute(thread);
        }
        return null;
    }

    // 通过回调机制设置图片时的接口(类似于Button的Onclick)
    public interface ImageDownloadCallBack {
        // ImageView 你所想要设定的imageview Bitmap 想要设定的图片
        void onImageDownload(ImageView imageView, Bitmap bitmap);
    }

从内存和本地加载都十分的容易理解,但是在下载中却出现了一个回调我们可以着重观察下

 // 下载回图片回调Handler
            final Handler hand = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // 如果图片下载成功,并且回调对象不为空时
                    if (msg.what == 111 && imageDownloadCallBack != null) {
                        Bitmap bit = (Bitmap) msg.obj;
                        // 调用回调自定义适配器的接口方法传递数据
                        imageDownloadCallBack.onImageDownload(imageView, bit);
                    }
                    super.handleMessage(msg);
                }
            };

            // 下载图片线程
            Thread thread = new Thread() {
                Bitmap bit = null;
                public void run() {
                    // 网络下载时的字节流
                    InputStream inputStream = DownBitmap.getInstance()
                            .getInputStream(imageUrl);
                    //图片压缩到原来一般
                    BitmapFactory.Options op=new BitmapFactory.Options();
                    op.inSampleSize=6;
                    if(Model.IMGFLAG)
                        op.inSampleSize = 1;
                    Bitmap bit = BitmapFactory.decodeStream(inputStream, null,
                            op);
                    if (bit != null) {
                        // 添加到一级缓存当中
                        imageCaches.put(imageUrl,
                                new SoftReference<Bitmap>(bit));
                        // 添加到二级缓存
                        fileUtiles.saveBitmap(filename, bit);
                        // 传递给Handler
                        Message msg = hand.obtainMessage();
                        msg.what = 111;
                        msg.obj = bit;
                        hand.sendMessage(msg);
                    }
                }
            };
            threadPools.execute(thread);
        }

首先定义的handler,通过这个handler我们可以与下载图片线程进行交互从而获取图片,然后通过回调接口,将图片传入到listViewadapter中进行图片的加载。在下载线程中我们通过DownBitmap获取了图片的输入流再通过图片工厂进行图片的绘制。
下面将DownBitmap进行书写:

/**
 * 下载服务器网络图片
 * */
public class DownBitmap {
    private DownBitmap() {
    }
    //单例设计模式
    private static DownBitmap my=null;
    public static synchronized DownBitmap getInstance() {
        if (my == null)
            my = new DownBitmap();
        return my;
    }
    // 获取网络图片下载时返回的流
    public InputStream getInputStream(String Biturl){
        //使用Get获取图片资源
        HttpGet get=new HttpGet(Biturl);
        HttpParams httpParams = new BasicHttpParams();
        //连接超时时间
        HttpConnectionParams.setConnectionTimeout(httpParams, 5 * 1000);
        //设置socket超时时间
        HttpConnectionParams.setSoTimeout(httpParams, 30 * 1000);
        HttpClient httpClient = new DefaultHttpClient(httpParams);
        try {
            HttpResponse hr = httpClient.execute(get);
            if (hr.getStatusLine().getStatusCode() == 200) {
                return hr.getEntity().getContent();// 得到服务器返回的输入流
            }
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }// 建立response连接从而方便获取状态吗
        return null;
    }
}

因为获取图片的数据流只需要这一个类,因此我们可以通过单例模式只存在一个DownBitmap 类通过传入不同的url就可以获取不同的图片资源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值