您的当前位置:首页正文

Android - AsyncTask (SDK 24)

来源:要发发知识网

利用AsyncTask给ListView异步加载图片 实现图文混排

#  AsyncTask
 // 无参 无进度显示 有返回值
JSONObjectpublic class NewsTask extends AsyncTask<Void,Void,JSONObject> {   
   private Activity activity;  
   private String url;   
   private OnTaskListener listener;   

 //构造方法  将 act 以及 url 传进来  listen实例化    
public NewsTask (Activity activity, String url,OnTaskListener onTaskListener) { 
  this.activity = activity;       
  this.url = url;        
  this.listener = onTaskListener;    
}   

 // 将 url 对应的json数据 转为  JSONObject    
private JSONObject getJsonData(String url){ 
       JSONObject jsonObject = null;        
try { 
   // new URL(url).getConnection.getInputStream 合成           
    String jsonStr = readStream(new URL(url).openStream());          
     jsonObject = new JSONObject(jsonStr);        //json字符串转为 json对象        
} catch (IOException e) {           
 e.printStackTrace();        
}catch (JSONException e) {            
  e.printStackTrace();        
}        return  jsonObject;    
}  
// 转成 json 字符串    
private String readStream (InputStream is){        
  InputStreamReader isr;        
  String result ="";        
try {            
  String line = "";            
  // 通过定义字符集格式 将字节流 转为 字符流
  isr = new InputStreamReader(is,"utf-8");                 
  BufferedReader br = new BufferedReader(isr); // 缓存 策略 Buffer            
  while ((line = br.readLine()) != null){      // 逐行 读 直到为空                
    result += line;            
 }        
} catch (UnsupportedEncodingException e) {            
  e.printStackTrace();        
} catch (IOException e) {            
  e.printStackTrace();        
}        
  return result;    
}    

// 子线程 任务    
@Override
    protected JSONObject doInBackground(Void... params) {       
   return getJsonData(url);    
}    
// execute后  doInBackground前 初始化    
@Override
    protected void onPreExecute() {        
  super.onPreExecute();    
}    
@Override
    protected void onPostExecute(JSONObject jsonObject) {
                      super.onPostExecute(jsonObject);        
  if (jsonObject == null){            
  listener.onFailed("数据为空");        
}else {            
// 成功            
  listener.onSucceed(jsonObject);        
}        
// 注意释放       
   listener = null;        
   activity = null;    
}    
@Override
    protected void onProgressUpdate(Void... values) {
          super.onProgressUpdate(values);
    }
}

# act 
new NewsTask(this, url, new OnTaskListener() {    
@Override    public void onSucceed(JSONObject jsonObject){      
  List<NewsBean> beanList = new ArrayList<NewsBean>();       
 JSONArray jsonArray = null;      
  //  操作数据      
  try {         
   jsonArray = jsonObject.getJSONArray("data");         
   for (int i=0;i<jsonArray.length();i++){             
   JSONObject object = (JSONObject) jsonArray.get(i);            
    NewsBean bean = new NewsBean();             
   bean.newsImgUrl = object.getString("picBig");              
  bean.newsTitle = object.getString("name");              
  bean.newsContent = object.getString("description");              
  beanList.add(bean);          
  }          
  //  adapter 将 listView 与 数据绑定         
   listView.setAdapter(new NewsAdapter(beanList,MainActivity.this,listView));      
  } catch (JSONException e) {          
  e.printStackTrace();      
    }  
  }   
 @Override    public void onFailed(String msg) {   
   }
}).execute();

# BaseAdapter

public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener{
    private List<NewsBean> beanList;
    private LayoutInflater inflater;
    private Context context;
    private ImageThreadLoader imgLoader;
    private int startIdx, endIdx;
    public static String[] imgUrls;  //创建静态数组
    private boolean firstFlag;

    public NewsAdapter(List<NewsBean> beanList, Context context) {
        this.beanList = beanList;
        this.context = context;
        inflater = LayoutInflater.from(context);
        imgLoader = new ImageThreadLoader();

        // 将所有 newsImgUrl 单独出来成为一个静态数组
      imgUrls = new String[beanList.size()];
      for (int i=0;i<beanList.size();i++){
          imgUrls[i] = beanList.get(i).newsImgUrl;
      }
      listView.setOnScrollListener(this);
      firstFlag = true; // 首次加载
    }
    @Override
    public int getCount() {
        return beanList.size();
    }
    @Override
    public Object getItem(int position) {
        return beanList.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        HolderView holderView;
        if (convertView == null){
            holderView = new HolderView();
            convertView = inflater.inflate(R.layout.item_layout,null);
            holderView.mImgView = (ImageView) convertView.findViewById(R.id.imgView);
            holderView.mTitle = (TextView) convertView.findViewById(R.id.tv_title);
            holderView.mContent = (TextView) convertView.findViewById(R.id.tv_content);
            convertView.setTag(holderView);  //绑定
        }else{
            holderView = (HolderView) convertView.getTag();
        }
        // 赋值
        NewsBean bean = beanList.get(position);
        holderView.mImgView.setImageResource(R.mipmap.ic_launcher);
        // 绑定
        holderView.mImgView.setTag(bean.newsImgUrl);

        // 多线程
//        new ImageThreadLoader().getImageByThrea(holderView.mImgView,bean.newsImgUrl);

        //  AsyncTask 方式  依次执行任务
//        new ImageThreadLoader().setImageByAsyncTask(holderView.mImgView,bean.newsImgUrl);

        // 使用LruCache 以内存换效率
       // imgLoader.setImageByAsyncTask(holderView.mImgView,bean.newsImgUrl);

        holderView.mTitle.setText(bean.newsTitle);
        holderView.mContent.setText(bean.newsContent);
    }

// AbsListView.OnScrollListener 滑动监听
@Overridepublic
 void onScrollStateChanged(AbsListView view, int scrollState) {
    // 状态改变
    if (scrollState == SCROLL_STATE_IDLE){
        //  滚动停止  加载数据
        imgLoader.loadImages(startIdx,endIdx);
    }else {
        // 停止后台线程 保证滚动的流畅
        imgLoader.cancleAllTasks();
    }
}
//  onScroll 一开始就会执行
@Overridepublic
 void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    startIdx = firstVisibleItem; // 第一个可见项
    endIdx = firstVisibleItem + visibleItemCount;  // 最后一个可见项
    if (firstFlag && totalItemCount > 0){
        // 第一次 第一屏 加载 (此时 未主动滑动 且 totalItemCount不为0而且已经计算出来)
        imgLoader.loadImages(startIdx,endIdx);
        firstFlag = false;
    }
}
    // ViewHolder 内部类
    private class HolderView{
        private ImageView mImgView;
        private TextView mTitle,mContent;
    }

# Thread

public class ImageThreadLoader { 
   private ImageView mImageView; 
   private String mUrl;
   // Lru(least recently used近期最少使用 算法)  LruCache是Android基于LRU封装的缓存 (类型类似于map)
private LruCache<String,Bitmap> mCache;
private ListView mListView;
private Set<ImageAsycTask> mVisiableTasks;

    //  匿名Handler  处理子线程和主线程的消息传递 更新UI
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            // url 一一对应ImgView  避免 多次赋值 以及 赋值混乱
            if (mImageView.getTag() == mUrl){
                mImageView.setImageBitmap((Bitmap) msg.obj);
            }
        }
    };
    public void getImageByThrea(ImageView imgView, final String imgUrl){
        // 存储 imgView 和 url
        mImageView = imgView;
        mUrl = imgUrl;
        //
        new Thread(){
            @Override
            public void run() {
                super.run();
                Bitmap bitmap = getBitmapBy(imgUrl);
                Message msg = new Message();
                msg.obj = bitmap;
                mHandler.sendMessage(msg);   //发送消息
            }
        }.start();
    }
    private Bitmap getBitmapBy(String imgUrl)  {
        Bitmap bitmap = null;
        InputStream is = null;
        URL url = null;
        try {
            url = new URL(imgUrl);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        HttpURLConnection connection = null;
        try {
            connection = (HttpURLConnection) url.openConnection();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            is = connection.getInputStream();
        } catch (IOException e) {            e.printStackTrace();        }
        BufferedInputStream bis = new BufferedInputStream(is);
        bitmap = BitmapFactory.decodeStream(bis);
        return bitmap;
    }

// 构造方法  外界 实例化ImageThreadLoader的成员变量 保证只有一个 LruCache对象
public ImageThreadLoader() {
mListView = listView;
// 初始化 集合
mVisiableTasks = new HashSet<>();
    // 获得当前 最大可以内存
    int maxSize = (int) Runtime.getRuntime().maxMemory();
    //  分多少内存给缓存
    int cacheSize = maxSize / 4;
    // 实例化
    mCache = new LruCache<String, Bitmap>(cacheSize){
        // 必须实现的方法 返回每次存入时 key 对应的value的大小
        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getByteCount();
        }
    };
}
private void addToCache(String key,Bitmap value){
    if (getFromCache(key) == null){
  // 内存中不存在
        mCache.put(key,value);
    }
}
private Bitmap getFromCache(String key){
    return mCache.get(key);
}
//  AsyncTask方式
public void setImageByAsyncTask(ImageView imgView,String url){
    mImageView = imgView;
    mUrl = url;
    // 先从缓存中取数据
    Bitmap bitmap = getFromCache(url);
    if (bitmap == null){
        // 没有缓存 下载
        new ImageAsycTask().execute(url);
    }else {
        imgView.setImageBitmap(bitmap);
    }
}

// 加载序列中 指定的所有图片
public void loadImages(int startIdx,int endIdx){
    for (int i=startIdx;i<endIdx;i++){
        String url = NewsAdapter.imgUrls[i];
        // 先从缓存中取数据
        Bitmap bitmap = getFromCache(url);
        if (bitmap == null){
            // 没有缓存 下载
            ImageAsycTask task = new ImageAsycTask(url);
            task.execute(url);
            mVisiableTasks.add(task);    // 加到Set集合中
        }else {
            // listView 根据 tag 找到url对应的ImgView
            ImageView imgView = (ImageView) mListView.findViewWithTag(url);
            imgView.setImageBitmap(bitmap);
        }
    }
}
public void cancleAllTasks(){
    if (mVisiableTasks != null){
        for (ImageAsycTask task : mVisiableTasks) {
            task.cancel(true);
        }
    }
}

private class ImageAsycTask extends AsyncTask<String,Void,Bitmap>{
private String taskImgUrl;
public ImageAsycTask(String taskImgUrl) {
    this.taskImgUrl = taskImgUrl;
}
    @Override
    protected Bitmap doInBackground(String... params) {
        String url = params[0];
        Bitmap bitmap = getBitmapBy(url);
        if (bitmap != null){
            // 加入到缓存
            addToCache(url,bitmap);
        }
        return bitmap;
    }
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
       ImageView imgView = (ImageView) mListView.findViewWithTag(taskImgUrl);
if (imgView != null && bitmap != null){
    imgView.setImageBitmap(bitmap);
}
mVisiableTasks.remove(this);
    }
}
}

#  接口
public interface OnTaskListener  {
    // 将Task独立出来以及 定义接口和将返回值 定义成 JSONObject  都是为了封装
    public void onSucceed(JSONObject jsonObject);
    public void onFailed(String msg);
}

链接