您的位置:首页 > 其它

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

2016-04-19 19:13 197 查看
高仿糗事百科,是一个典型的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就可以获取不同的图片资源。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: