什么是异步加载
异步加载就是用异步的方式去加载数据,也就是用非主线程去加载数据的意思
为什么要异步加载
原因大概有两个:
第一、 为了提高用户体验,让用户加载数据的时候不会感到明显的卡顿
第二、 另一点,就是Android要求我们这么做,耗时操作不能在主线程中执行。
异步加载最常用的两种方式:
第一种:就是利用多线程和线程池的方式
第二种:就是利用Android提供的封装好的AsyncTask来异步加载,不过AsyncTask的底层也是基于线程池去实现的
实际操作异步加载(加载网络图片)
慕课网提过的一个返回JSON格式数据的API
http://www.imooc.com/api/teacher?type=4&num=30
如果浏览器显示出现部分乱码,或则是格式太乱的现象
请点击下面的连接
【工具类系列】浏览器解析JSON数据插件,解决数据加密乱码,以及JSON格式化问题
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/lv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_world" />
</LinearLayout>
item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/image_icon"
android:layout_width="64dp"
android:layout_height="64dp"
android:src="@drawable/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="64dp"
android:paddingLeft="4dp"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:layout_weight="1"
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxLines="1"
android:textSize="15sp"
android:text="Title" />
<TextView
android:layout_weight="1"
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxLines="3"
android:textSize="10sp"
android:text="content" />
</LinearLayout>
</LinearLayout>
NewsBean.java
package bnuz.lwj.asynctaskteaching2;
import android.graphics.Bitmap;
public class NewsBean {
private Bitmap bitmap;
private String newsIconUrl;
private String newsTitle;
private String newsContent;
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public String getNewsIconUrl() {
return newsIconUrl;
}
public void setNewsIconUrl(String newsIconUrl) {
this.newsIconUrl = newsIconUrl;
}
public String getNewsTitle() {
return newsTitle;
}
public void setNewsTitle(String newsTitle) {
this.newsTitle = newsTitle;
}
public String getNewsContent() {
return newsContent;
}
public void setNewsContent(String newsContent) {
this.newsContent = newsContent;
}
}
MyAdapter.java
package bnuz.lwj.asynctaskteaching2;
import java.util.List;
import android.content.Context;
import android.media.Image;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class MyAdapter extends BaseAdapter{
private List<NewsBean> mList;
private LayoutInflater mInflater;
public MyAdapter(Context context,List<NewsBean> mList) {
super();
this.mList = mList;
this.mInflater =LayoutInflater.from(context);
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHoler=null;
if(convertView==null){
viewHoler=new ViewHolder();
convertView=mInflater.inflate(R.layout.item_layout,null);
viewHoler.title=(TextView) convertView.findViewById(R.id.tv_title);
viewHoler.content=(TextView) convertView.findViewById(R.id.tv_content);
viewHoler.ImageIcon=(ImageView) convertView.findViewById(R.id.image_icon);
convertView.setTag(viewHoler);
}else{
viewHoler=(ViewHolder) convertView.getTag();
}
//viewHoler.ImageIcon.setImageResource(R.drawable.ic_launcher);
viewHoler.ImageIcon.setImageBitmap(mList.get(position).getBitmap());
viewHoler.title.setText(mList.get(position).getNewsTitle());
viewHoler.content.setText(mList.get(position).getNewsContent());
return convertView;
}
class ViewHolder{
public TextView title;
public TextView content;
public ImageView ImageIcon;
}
}
MyAsyncTask.java
package bnuz.lwj.asynctaskteaching2;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ListView;
//实现网络的异步访问
//传入一个URL,不记录过程,返回一个NewsBean类型的List集合
public class MyAsyncTask extends AsyncTask<String, Void, List<NewsBean>>{
//传入一个context,为了Myadapter的执行
private Context mcontext;
private ListView mlistView;
public MyAsyncTask(Context context,ListView listView) {
super();
this.mcontext=context;
this.mlistView=listView;
}
//将URL对应的JSON格式数据转化为我们所封装的NEWSbEAN对象
private List<NewsBean> getJsonDate(String url) {
List<NewsBean> newsBeanList=new ArrayList<NewsBean>();
try {
String jsonString=readStream(new URL(url).openStream());
//调试是否返回正确json格式的数据字符串
Log.i("info", "getJsonData:"+jsonString);
JSONObject jsonObject;
NewsBean newsBean;
//通过传入json格式的数据字符串,用JSON内置函数解析字符串,得到json数据
jsonObject=new JSONObject(jsonString);
//data就是我们在浏览器看到的data数组,不要把data写成了date,刚就犯了这个错,获取不到数据
JSONArray jsonArray=jsonObject.getJSONArray("data");
//得到整个date数组后,我们就可以通过遍历数组,得到数组里每个一个对象的值
for(int i=0;i<jsonArray.length();i++){
jsonObject =jsonArray.getJSONObject(i);
newsBean=new NewsBean();
newsBean.setNewsIconUrl(jsonObject.getString("picSmall"));
newsBean.setBitmap(loadImage(newsBean.getNewsIconUrl()));
newsBean.setNewsTitle(jsonObject.getString("name"));
newsBean.setNewsContent(jsonObject.getString("description"));
newsBeanList.add(newsBean);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (JSONException e) {
e.printStackTrace();
}
return newsBeanList;
}
//通过URL获取网页返回的字符串信息
private String readStream(InputStream is)
{
InputStreamReader isr;
String result="";
//一次性将URL的所有JSON格式数据都截取,赋值到result
//获取的是一个JSON加密的格式,在浏览器访问的时候,系统会自动将乱码格式转换了正常的格式
try {
String line="";
isr=new InputStreamReader(is,"utf-8");
BufferedReader br=new BufferedReader(isr);
while((line=br.readLine())!=null){
result+=line;
Log.i("info1", "line:"+line);
Log.i("info1", "result:"+result);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
return result;
}
//解析网络图片URL获取网络图片
private Bitmap loadImage(String url){
Bitmap bitmap=null;
InputStream is;
try {
URL myurl = new URL(url);
is=myurl.openStream();
//包装一下
BufferedInputStream bis=new BufferedInputStream(is);
//将一个输入流解析为一个BitMap对象
bitmap=BitmapFactory.decodeStream(is);
//关闭输入流
is.close();
bis.close();
} catch (MalformedURLException e) {
Log.i("info", "MalformedURLException");
e.printStackTrace();
} catch (IOException e) {
Log.i("info", "IOException:"+e.toString());
e.printStackTrace();
}
return bitmap;
}
@Override
protected List<NewsBean> doInBackground(String... params) {
return getJsonDate(params[0]);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(List<NewsBean> newsBeanList) {
super.onPostExecute(newsBeanList);
MyAdapter adapter=new MyAdapter(mcontext,newsBeanList);
mlistView.setAdapter(adapter);
}
}
MainActivity.java
package bnuz.lwj.asynctaskteaching2;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView mListView;
private static String URL=
"http://www.imooc.com/api/teacher?type=4&num=30";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView)findViewById(R.id.lv_main);
MyAsyncTask myAsyncTask =new MyAsyncTask(MainActivity.this,mListView);
myAsyncTask.execute(URL);
}
}
然后别忘记了加上Android对网络的权限
<uses-permission android:name="android.permission.INTERNET"/>
实现效果
总的来说,还没有对图片的加载做什么优化,就是基本的实现。
如果有什么不明白的问题,可以留言,大家一起交流学习
总结到此结束~
欢迎关注我的博客,一起学习讨论
要转载,请附上原文链接,作者:SnailMann
传送门:【Android学习笔记系列】BaseAdapter适配器的介绍、使用及优化(详细)
传送门:【Android学习笔记系列】AsyncTask的使用和介绍(获取网络图片与进度条实例)
大家也可以关注我的私人github: https://github.com/SnailMann,欢迎watch ,star, fork
虽然现在暂时没有什么东西,但是总会有的