android关于ListView与自定义适配器配合使用的步骤与优化

来源:互联网 发布:啪啪视频下载软件 编辑:程序博客网 时间:2024/06/14 11:15

//以开放接口http://api.1-blog.com/biz/bizserver/xiaohua/list.do为例子,需要把页面加载成http://1-blog.com/joker/index.html的样式.。

//经过分析其json文件,可以利用一个Joke的Bean类在存放下载的有关数据,只取作者,内容和图片部分


//1.项目开始的第一步,把各自需要的布局页面先设计好,在MainActivity界面中,把ListView控件找到,创建一个自定义适配(MyBaseAdapter继承于BaseAdapter),然后创建一个集合(ArrayList(Joke) list01,集合内容为空,集合本身不为空),创建自定义适配器对象(adapter),给ListView设置上空的适配器(通过setAdapter方法,适配在后面会更新数据),然后通过异步任务开启下载并解析后利用接口回调的方法把下载解析得到的ArrayList(Joke) list02传回到MainActivity,在MainActivity中把得到的list02都加进list01中(通过list01.addAll()方法),添加完后通知适配器更新数据(adapter.notifyDataSetChanged()

//2.具体框架构建好以后,就剩下需要实现的具体步骤,异步任务开启下载与下载后的JSON解析(具体操作请浏览http://blog.csdn.net/asswc2004/article/details/51406670、

http://blog.csdn.net/asswc2004/article/details/51407079),把解析得到的数据作为属性传入Joke中,再把得到的每一个Joke对象放进一个集合当中通过结接口回调返回到MainActivity中去,在其中的匿名内部类把此集合都加入到主函数定义已经给适配器设置好的集合中去,然后通知适配更新。

//3.在编写自定义适配器的时候需要注意优化,优化分三步,第一步是把ListView的宽高设置为固定的,这样安卓系统就不会在数据变化的时候都要去测量从而反复调用getView方法;第二步利用convertView 利用回收机制中的废弃对象(即已经被拖拉出屏幕范围的视图,都会被convertView接收),当convertView为空的时候,把布局加载器加载成的对象赋值给convertView,然后把convertView找的空间都保存在ViewHoder中(自定义一个保存控件的类)后通过setTag()放到convertView中,需要用时同getTag()获得ViewHoder对象进行设置;第三步是防止图片错位,在开启异步任务下载图片的时候,需要给图片控件imageView附带上其URL传到异步任务中去(setTag(URL)),在异步任务结束时的onpost方法中通过对比传进来的下载的URL和getTag()中的URL来防止图片的错位,当两者相同时,下载并给控件设置上图片,否则View,GONE


示例代码:

mian:

String URL = "http://api.1-blog.com/biz/bizserver/xiaohua/list.do";
private ListView listView;
private List<Joke> list = new ArrayList<Joke>();
private MyBaseAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

listView = (ListView) findViewById(R.id.list_view);
adapter = new MyBaseAdapter(list, this);
listView.setAdapter(adapter);
MyAsyncTask myAsyncTask = new MyAsyncTask(listView,this);//下载并解析内容,开启异步任务
myAsyncTask.SetOnTaskListener(new MyAsyncTask.OnTaskListener(){

@Override
public void getList(List<Joke> JokeList) {
list.addAll(JokeList);
adapter.notifyDataSetChanged();
}
});
myAsyncTask.execute(URL);
//给listView设置监听器
listView.setOnItemClickListener(new OnItemClickListener() {


@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("joke", list.get(position));
startActivity(intent);
}
});
}


AsyncTask

private ListView listView;
private Context context;
private OnTaskListener listener;


public interface OnTaskListener{
void getList(List<Joke> JokeList);
}

public void SetOnTaskListener(OnTaskListener listener){
this.listener = listener;
}
public MyAsyncTask(ListView listView, Context mainActivity) {
this.listView = listView;
this.context = mainActivity;
}


@Override
protected List<Joke> doInBackground(String... params) {
//在这里进行下载解析
String jsonString = HttpUtil.downloadJsonString(params[0]);//下载json数据
return JsonUtil.JsonPull(jsonString);//进行json解析并返回Joke集合
}
@Override
protected void onPostExecute(List<Joke> result) {
if (result != null) {
//开始给ListView设置视图,需要自定义适配器用于设计其视图。
listener.getList(result);
}
}


BaseAdapter

private List<Joke> list;
private Context context;
private ViewHoder viewHoder;
private Joke joke;
public MyBaseAdapter(List<Joke> result, Context context) {
this.list = result;
this.context = context;
}


//因为需要返回数据长度,所以要把集合数据传进来,可以通过构造方法实现传递
@Override
public int getCount() {
return list.size();//返回集合长度,如果没数据则不会给设置视图
}


@Override
public Object getItem(int position) {
return list.get(position);//返回position位置的对象
}


@Override
public long getItemId(int position) {
return position;//返回position位置对象的id,通常以positon作为id(因为每个position都不相同)
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
//在这个方法进行设置,优化第一步把listView的长宽都铺满父容器,第二部重复利用convertView,利用viewHoder防止过多的产生view
if(convertView == null){
//这里因为第一个参数需要上下文对象,所以还是通过构造把参数传进来,第二个参数是资源文件,第三个参数是父容器通常为Null
convertView = View.inflate(context,R.layout.my_baseadapter_layout, null);
TextView authorText = (TextView) convertView.findViewById(R.id.text_author);
TextView contentText = (TextView) convertView.findViewById(R.id.text_content);
final ImageView picUrlView = (ImageView) convertView.findViewById(R.id.image_picUrl);
viewHoder = new ViewHoder();
viewHoder.authorText1 = authorText;
viewHoder.contentText = contentText;
viewHoder.picUrlView = picUrlView;
convertView.setTag(viewHoder);

}else{
viewHoder = (ViewHoder) convertView.getTag();
}
joke = list.get(position);
viewHoder.authorText1.setText(joke.getAuthor());
viewHoder.contentText.setText(joke.getContent());
if(!joke.getPicUrl().equals("")){
//如果图片链接不为空,开启异步任务下载好图片并设置上去
//改当前图片设置应该显示的图片url
viewHoder.picUrlView.setTag(joke.getPicUrl());
viewHoder.picUrlView.setVisibility(View.VISIBLE);
MyImageTask mi = new MyImageTask(viewHoder.picUrlView);
mi.execute(joke.getPicUrl());
}else {
viewHoder.picUrlView.setVisibility(View.GONE);
}

return convertView;
}

class ViewHoder{
TextView authorText1,contentText;
ImageView picUrlView;
}


MyImageTask//下载图片的异步

private ImageView imageView;
private String urlString;
public MyImageTask(ImageView picUrlView) {
this.imageView = picUrlView;
}




@Override
protected Bitmap doInBackground(String... params) {
urlString = params[0];
Bitmap bm = HttpUtil.downloadPic(urlString);
PictureBean.map.put(params[0], bm);//把下载好的图片存放好
return bm;
}
@Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
if (urlString.equals(imageView.getTag())) {
imageView.setImageBitmap(result);
}else {
imageView.setVisibility(View.GONE);
}
}
}

0 0