前言:因为在项目中获取网络就会出现耗时操作,便需要用到异步的方式将耗时操作与组件分开,于是去找了视频去学习异步加载,在此对整体的思想做个总结并附上部分源码。
Android中的异步加载:Android中,异步实现,一般用handler和AsyncTask,通常handler是一个消息栈,而AsyncTask不是。
具体区别:AsyncTask比Java原始的Thread更灵活和强大,但对于轻量级的使用更为占用系统资源。Thread是Java早期为实现多线程而设计的,比较简单不支持concurrent中很多特性在同步和线程池类中需要自己去实现很多的东西,对于分布式应用来说更需要自己写调度代码,而为了Android UI的刷新Google引入了Handler和Looper机制,它们均基于消息实现,有事可能消息队列阻塞或其他原因无法准确的使用。
实现手段:本次Demo加载数据我采用的是AsyncTask,而加载图片采用的是 handler+Thread。
实现效果:
在ListView中呈现出通过网络获取到的视频信息,向下滑动会进行更新。
一、对数据的加载:通过AsyncTask异步访问网络,获取到JSON字符串所对应的数据并展示到ListView中。
1、传进去一个URL,实现对这个URL的异步加载
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mListView = (ListView) findViewById(R.id.lv_main);
- new NewsAsyncTask().execute(URL); //1、传进去一个URL,实现对这个URL的异步加载
- }
- private List<NewsBean> getJosnData(String url) {
- List<NewsBean> newsBeanList = new ArrayList<NewsBean>();
- try {
- String jsonString = readString(new URL(url).
- openConnection().getInputStream());
- // String jsonString = readString(new URL(url).openStream());
- // Log.i("arvin", jsonString);
- JSONObject jsonObject;
- try {
- jsonObject = new JSONObject(jsonString);
- JSONArray jsonArray = jsonObject.getJSONArray("data");
- for (int i = 0; i < jsonArray.length(); i ++)
- {
- jsonObject = jsonArray.getJSONObject(i);
- NewsBean newsBean = new NewsBean();
- newsBean.setNewsIconUrl(jsonObject.getString("picSmall"));
- newsBean.setNewsTitle(jsonObject.getString("name"));
- newsBean.setNewsContent(jsonObject.getString("description"));
- newsBeanList.add(newsBean);
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return newsBeanList;
- }
- }
- }
3、将NEWSBEAN对象传递给list的适配器,将数据源设置给了ListView
- class NewsAsyncTask extends AsyncTask<String, Void, List<NewsBean>>
- {
- /**
- * 实现网络的异步访问
- */
- @Override
- protected List<NewsBean> doInBackground(String... params) {
- return getJosnData(params[0]);
- }
- @Override
- protected void onPostExecute(List<NewsBean> newsbean) {
- // TODO Auto-generated method stub
- super.onPostExecute(newsbean);
- //3、将NEWSBEAN对象传递给list的适配器,将数据源设置给了ListView
- NewsAdapter adapter = new NewsAdapter(newsbean, MainActivity.this, mListView);
- mListView.setAdapter(adapter);
- }
二、对图像的加载
因为图像所使用的空间较大,而程序的内存有限,所以要对图片进行高效正确的加载。
创建ImageLoader类用来处理图片的加载,通过Thread+Handler
- public void showImageByThread(ImageView imageView,final String url)
- {
- mImageView = imageView;
- mUrl = url;
- new Thread()
- {
- public void run()
- {
- super.run();
- Bitmap bitmap = getBitmapFromUrl(url);
- Message message = Message.obtain();
- message.obj = bitmap;
- handler.sendMessage(message);
- }
- }.start();
- }
三、优化
1、图片每次都要加载,耗费用户流量
解决方法:通过Lrulache类来实现Lru算法(Least Recently Used)进行缓存管理。
代码如下:
1、创建Lrulache
- //创建Cache,本质是一个map
- private LruCache<String,Bitmap> mCache;
- //创建部分内存成为缓存空间
- public ImageLoader(ListView listview) {
- mListView = listview;
- mTask = new HashSet<NewsAsyncTask >();
- //获取最大可用内存
- int maxMemory = (int) Runtime.getRuntime().maxMemory();
- int cacheSize = maxMemory / 4;
- mCache = new LruCache<String, Bitmap>(cacheSize){
- protected int sizeOf(String key, Bitmap value) {
- //在每次存入缓存的时候调用
- return value.getByteCount();
- };
- };
- }
- public void showImageByAsyncTask(ImageView imageView,String url)
- {
- //从缓存中取出对应的图片
- Bitmap bitmap = getBitmapFromCache(url);
- //如果缓存中没有,那么必须下载
- if (bitmap == null)
- {
- //new NewsAsyncTask(url).execute(url);
- imageView.setImageResource(R.mipmap.ic_launcher);
- }else
- {
- imageView.setImageBitmap(bitmap);
- }
- }
------end