- 关于AsyncTask,相信大家都不陌生。不过我倒是比较陌生,因为之前都没怎么用过这个类。今天看慕课视频,就写了一个Demo,用到了这个类,算是对AsyncTask的熟悉。
- 之前一直觉得ImageLoader这种东西很高大上,都是在开源框架里面才见过这些类。
- 不过今天看到慕课网关于AsyncTask的讲解的时候,顺便就写了一个ImageLoader,才明白ImageLoader大概是怎么一回事。
- 慕课讲解链接: http://www.imooc.com/note/406 ;
顺便放出我的Demo吧,很粗糙。但是也算是实现了功能,主要是对AsyncTask类的熟悉和加深。
这是一个加载显示新闻条目的ListView的小Demo.因为是网络操作,所以需要添加网络访问权限:
<uses-permission android:name="android.permission.INTERNET" />
然后是xml,一个是Activity的xml布局,一个ListView的Item的xml布局。
1. activity的xml
<RelativeLayout 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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MoocActivity" >
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</RelativeLayout>
- Item的xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/imageview"
android:layout_width="64dp"
android:layout_height="64dp"
android:contentDescription="@string/action_settings"
android:src="@drawable/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imageview"
android:orientation="vertical"
android:paddingLeft="4dp" >
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Title"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:text="Content"
android:textSize="12sp" />
</LinearLayout>
</RelativeLayout>
然后是Activity的代码:
package com.duck.moocAsyncTask;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ListView;
public class MoocActivity extends Activity {
private static final String URL = "http://www.imooc.com/api/teacher?type=4&num=30";
private ListView mListView;
private NewsAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mooc);
mListView = (ListView) findViewById(R.id.listview);
new NewsAsyncTask().execute(URL);
}
class NewsAsyncTask extends AsyncTask<String, Void, List<NewsBean>> {
private static final boolean DEBUG = false;
@Override
protected void onPostExecute(List<NewsBean> result) {
super.onPostExecute(result);
adapter = new NewsAdapter(result, MoocActivity.this);
mListView.setAdapter(adapter);
}
@Override
protected List<NewsBean> doInBackground(String... params) {
String url = params[0];
return getDatasFromUrl(url);
}
private List<NewsBean> getDatasFromUrl(String url) {
try {
URLConnection connection = new URL(url).openConnection();
InputStream is = connection.getInputStream();
String jsonString = getStringFromStream(is);
return getNewsFromJson(jsonString);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private List<NewsBean> getNewsFromJson(String jsonString) {
List<NewsBean> newsBeanList = new ArrayList<NewsBean>();
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
String url = object.getString("picSmall");
String title = object.getString("name");
String content = object.getString("description");
NewsBean bean = new NewsBean();
bean.iconUrl = url;
bean.title = title;
bean.content = content;
newsBeanList.add(bean);
}
} catch (JSONException e) {
e.printStackTrace();
}
if (DEBUG) {
// 数据获取OK!
System.out.println("newsBeanList: " + newsBeanList);
System.out.println("\n \n newsBeanList.SIZE: "
+ newsBeanList.size());
System.out.println("\n \n newsBeanList.3: "
+ newsBeanList.get(3).title);
}
return newsBeanList;
}
private String getStringFromStream(InputStream is) {
String json = "";
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
try {
while ((line = br.readLine()) != null) {
json += line;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return json;
}
}
}
Activity里面有一个AsyncTask类,是获取网络数据json。只有加载一次即可。
然后是Adapter的代码,但是Adapter需要准备数据源,于是需要一个ImageLoader,又涉及到数据的封装,于是又有一个Bean类。
1.Bean代码:
package com.duck.moocAsyncTask;
public class NewsBean {
public String iconUrl;
public String title;
public String content;
}
- ImageLoader代码:
package com.duck.moocAsyncTask;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
public class ImageLoader {
private ImageView mImageView;
private String mUrl;
public ImageLoader(ImageView imageView, String url) {
mImageView = imageView;
mUrl = url;
}
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (mImageView.getTag().equals(mUrl)) {
mImageView.setImageBitmap((Bitmap) msg.obj);
}
}
};
protected Bitmap getBitmapFromUrl(String urlString) {
URLConnection connection = null;
InputStream is = null;
try {
connection = new URL(urlString).openConnection();
is = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public void disPlayByThread(final String url) {
new Thread(new Runnable() {
@Override
public void run() {
Bitmap bitmap = getBitmapFromUrl(url);
Message message = Message.obtain();
message.obj = bitmap;
handler.sendMessage(message);
}
}).start();
}
public void disPlayByAsyncTask(ImageView imageView, String url) {
new LoadImageAsyncTask(imageView,url).execute(url);
}
class LoadImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
private ImageView mImageView;
private String mUrl;
public LoadImageAsyncTask(ImageView imageView,String url) {
mImageView = imageView;
mUrl = url;
}
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
Bitmap bitmap = getBitmapFromUrl(url);
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if(mImageView.getTag().equals(mUrl)){
mImageView.setImageBitmap(result);
}
}
}
}
ImageLoader里面也有一个AsyncTask类。这个AsyncTask是用来加载ListView的Item需要的图片的,所以会在Adapter的getView()方法里面被多次调用。
最后就是Adapter类:
package com.duck.moocAsyncTask;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class NewsAdapter extends BaseAdapter {
private List<NewsBean> mList;
private LayoutInflater mInflater;
public NewsAdapter(List<NewsBean> newsBeans, Context context) {
mList = newsBeans;
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return mList.size();
}
@Override
public NewsBean 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 holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);
holder.ivIcon = (ImageView) convertView
.findViewById(R.id.imageview);
holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
holder.tvContent = (TextView) convertView
.findViewById(R.id.tv_content);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// show data
NewsBean bean = getItem(position);
holder.ivIcon.setImageResource(R.drawable.ic_launcher);
holder.ivIcon.setTag(bean.iconUrl);// 绑定tag
// new ImageLoader(holder.ivIcon, bean.iconUrl)
// .disPlayByThread(bean.iconUrl);
new ImageLoader(holder.ivIcon, bean.iconUrl).disPlayByAsyncTask(
holder.ivIcon, bean.iconUrl);
holder.tvTitle.setText(bean.title);
holder.tvContent.setText(bean.content);
return convertView;
}
class ViewHolder {
ImageView ivIcon;
TextView tvTitle;
TextView tvContent;
}
}
Adapter就是一般的Adapter。在getView方法里面去调用ImageLoader去加载网络图片,其他的没有什么。
以上代码就是这个Demo的所有代码了。
为了方便以后使用。顺便传一个资源链接吧:
项目下载