Android异步加载
生活随笔
收集整理的這篇文章主要介紹了
Android异步加载
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
為什么要異步加載:
為了用戶體驗(yàn),避免卡頓
Android系統(tǒng)要求使用異步加載,耗時(shí)操作會(huì)阻塞UI線程
異步加載的常用的方式:
多線程/線程池
AsyncTask
以下以加載網(wǎng)絡(luò)圖片為示例
在主類之外聲明一個(gè)單獨(dú)的MyBean類:
class MyBean{public String MyIconUrl;public String MyTitle;public String MyContent; }和一個(gè)MyAdapter類:
public class MyAdapter extends BaseAdapter{private List<MyBean> mList;private LayoutInflater mInflater;public MyAdapter(Context context, List<MyBean> data){mList = data;mInflater = LayoutInflater.from(context);}public int getCount(){return mList.size();}public Object getItem(int position){return mList.get(position);}public long getItemId(int position){return position;}public View getView(int position, View convertView, ViewGroup parent){ViewHolder viewHolder = null;if(convertView == null){viewHolder = new ViewHolder();convertView = mInflater.inflate(R.layout.item_layout, null);viewHolder.ivIcon = (ImageView)convertView.findViewById(R.id.iv_icon);viewHolder.tvTitle = (TextView)convertView.findViewById(R.id.tv_title);viewHolder.tvContent = (TextView)convertView.findViewById(R.id.tv_content);convertView.setTag(viewHolder);}else{viewHolder = (ViewHolder)convertView.getTag();}viewHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);//這是使用默認(rèn)的ic_launcher作為圖標(biāo) //-----------------下述是調(diào)用異步加載圖片的內(nèi)容作為圖標(biāo) new ImageLoader().showImageByThread(viewHolder.ivIcon, mList.get(position).myIconUrl); //-----------------viewHolder.tvTitle.setText(mList.get(position).MyTitle);viewHolder.tvContent.setText(mList.get(position).MyContent);return convertView;}class ViewHolder{public TextView tvTitle, tvContent;public ImageView ivIcon;} }接下來是主類中的方法:
private ListView mListView; private static String URL = "http://www.xxxxxxxxx.com/xxx/xxx/xxx";protected void OnCreate(Bundle savedInstanceState){super.OnCreate(savedInstanceState);setContentView(R.Layout.activity_main);mListView = (ListView)findViewById(R.id.lv_main);new MyAsyncTask().execute(URL); } private List<MyBean> getJsonData(String url){//將Url的Json數(shù)據(jù)轉(zhuǎn)化為所封裝的MyBean對(duì)象List<MyBean> myBeanList = new ArrayList<>();try{String jsonString = readStream(new URL(url).openStream());//上述語句功能與url.openConnection().getInputStream()相同,//可根據(jù)URL直接聯(lián)網(wǎng)獲取網(wǎng)絡(luò)數(shù)據(jù),簡單粗暴,返回值類型為InputStreamJSONObject jsonObject;MyBean myBean;try{jsonObject = new jsonObject(jsonString);JSONArray jsonArray = jsonObject.getJSONArray("data");for(int i =0;i<jsonArray.length();i++){jsonObject = jsonArray.getJSONObject(i);myBean = new MyBean();myBean.MyIconUrl = jsonObject.getString("picSmall");myBean.MyTitle = jsonObject.getString("name");myBean.MyContent = jsonObject.getString("description");myBeanList.add(myBean);//循環(huán)完畢時(shí),將所有數(shù)據(jù)加入MyBean對(duì)象中,之后就可以將數(shù)據(jù)設(shè)置在ListView中}}catch(JSONException e){e.printStackTrace();}}catch(IOException e){e.printStackTrace();}return myBeanList; }private String readStream(InputStream is){//通過InputStream解析網(wǎng)頁返回的數(shù)據(jù)InputSrteamReader isr;String result = "";try{String line = "";isr = new InputStream(is, "utf-8");BufferedReader br = new BufferedReader(isr);while((line = br.readLine())!= null){result+=line;}}catch(UnsupportedEncodingException e){e.printStackTrace();}catch(IOException e){e.printStackTrace();}return result; }class MyAsyncTask extends AsyncTask<String, Void, List<MyBean>>{//實(shí)現(xiàn)網(wǎng)絡(luò)的異步訪問protected List<MyBean> doInBackground(String... params){return getJsonData(params[0]);}protected void onPostExecute(List<MyBean> myBean){super.onPostExecute(myBean);MyAdapter adapter = new MyAdapter(MainActivity.this, myBean );mListView.setAdapter(adapter);} }上述實(shí)現(xiàn)了ListView圖文混排接下來是對(duì)圖像的異步加載:
public class ImageLoader{private ImageView mImageView;private Handler mHandler = new Handler();private Handler handler = new Handler(){public void handleMessage(Message msg){super.handleMessage(msg);mImageView.setImageBitmap((Bitmap)msg.obj);}}public void showImageByThread(ImageView imageView, String url){mImageView = imageView;new Thread(){public void run(){super.run();Bitmap bitmao = getBitmapFromURL(url);Message message = Message.obtain();message.obj = bitmap;mHandler.sendMessage(message);}}.start();}public Bitmap getBitmapFromURL(String urlStirng){Bitmap bitmap;InputStream is;try{URL url = new URL(urlStirng);HttpURLConnection connection = (HttpURLConnection)url.openConnection();is = new BufferedInputStream(connection.getInputStream());bitmap = BitmapFactory.decodeStream(is);connection.disconnect();return bitmap;}catch(java.io.IOException e){e.printStackTrace();}finally{is.close();}return null;} }事實(shí)上,上面的方法,在網(wǎng)速不是很快的時(shí)候,會(huì)出現(xiàn)刷新時(shí)圖片錯(cuò)亂的現(xiàn)象,因?yàn)長istView的緩存機(jī)制導(dǎo)致圖片顯示錯(cuò)位,則只需要改進(jìn)一步,在MyAdapter類中的getView()方法中增加三行代碼: viewHolder.ivIcon.setImageResource(R.mipmap.ic_launcher);String utl = mList.get(position).MyIconUrl;viewHolder.ivIcon.setTag(utl);new ImageLoader().showImageByThread(viewHolder.ivIcon, url);viewHolder.tvTitle.setText(mList.get(position).MyTitle);viewHolder.tvContent.setText(mList.get(position).MyContent);return convertView;之后在ImageLoader類中handleMessage()方法中增加判斷語句,最終修改為: public class ImageLoader{private ImageView mImageView;private Handler mHandler = new Handler();private String mUrl;private Handler handler = new Handler(){public void handleMessage(Message msg){super.handleMessage(msg);if(mImageView.getTag().equals(mUrl))mImageView.setImageBitmap((Bitmap)msg.obj);}}public void showImageByThread(ImageView imageView, String url){mImageView = imageView;mUrl = url;new Thread(){public void run(){super.run();Bitmap bitmao = getBitmapFromURL(url);Message message = Message.obtain();message.obj = bitmap;mHandler.sendMessage(message);}}.start();}public Bitmap getBitmapFromURL(String urlStirng){Bitmap bitmap;InputStream is;try{URL url = new URL(urlStirng);HttpURLConnection connection = (HttpURLConnection)url.openConnection();is = new BufferedInputStream(connection.getInputStream());bitmap = BitmapFactory.decodeStream(is);connection.disconnect();return bitmap;}catch(java.io.IOException e){e.printStackTrace();}finally{is.close();}return null;} }一般有兩種辦法避免ListView的緩存特性帶來的ListView的Item的錯(cuò)亂,一種是在BaseAdapter中設(shè)置tag,將身份驗(yàn)證信息與相應(yīng)的Item綁定,在加載時(shí)判斷身份驗(yàn)證信息是否正確,正確才設(shè)置圖片操作,第二種,是使用成員變量,將對(duì)應(yīng)的數(shù)據(jù)進(jìn)行緩存,從而避免網(wǎng)絡(luò)下載時(shí)間不確定導(dǎo)致的時(shí)序的混亂。大部分的異步加載錯(cuò)誤都可以使用這兩種辦法解決。
使用AsyncTask()方法異步加載
之后再回到MyAdapter類中,將多線程的方法加載圖片的語句換掉: //new ImageLoader().showImageByThread(viewHolder.ivIcon, url);new ImageLoader().showImageByAsyncTask(viewHolder.ivIcon, url);同樣,AsyncTask方法也會(huì)出現(xiàn)刷新時(shí)圖片錯(cuò)亂的現(xiàn)象,因?yàn)锳syncTask本身就是基于多線程,所以對(duì)其進(jìn)行處理,修改之后: public void showImageByAsyncTask(ImageView imageView, String url){new MyAsyncTask(imageView, url).execute(url); }private class MyAsyncTask extends AsyncTask<String, Void, Bitmap>{private ImageView imageView;private String mUrl;public MyAsyncTask(ImageView imageView, String url){mImageView = imageView;mUrl = url;}protected Bitmap doInBackground(String... params){return getBitmapFromURL(params[0]);}protected void onPostExecute(Bitmap bitmap){super.onPostExecute(bitmap);if(mImageView.getTag().equals(mUrl))mImageView.setImageBitmap(bitmap);} }
至此,便實(shí)現(xiàn)了異步加載網(wǎng)絡(luò)圖片。
總結(jié)
以上是生活随笔為你收集整理的Android异步加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 异步任务AsyncTask
- 下一篇: 接上,进一步优化,LruCache缓存