編輯:關於Android編程
學過ListView的人都知道, 它在Android學習中有著舉足輕重的地位, 雖然現在有了RecyClerView來替代ListView, 但是對於我們初學者來說, 了解和使用ListView還是非常重要的!!!
我們應該知道, 顯示復雜內容的控件一般會有一個Adapter來控制它的顯示. 這其實就是我們平常所說的MVC設計模式. Adapter就扮演了Controller的角色.
在具體實現之前我們要從大方向上來了解一下ListView的實現機制.
ListView是用來顯示數據的控件, 在xml布局文件中存放(當然也可以用Java代碼實現, 就不要這麼鑽牛角尖了^v^), 所以它需要有數據源, 才能顯示數據, 但是它也需要知道我們的數據怎樣展示在手機上, 這就用到了我們的Adapter. 好,先簡單介紹到這兒, 後面會有詳細的闡述.
接下來, 我先介紹幾種實現ListView非常簡單的方式, 不過這幾種在我們後來的工作, 項目中幾乎不用, 所以我也不做過多的解釋.
簡單到沒朋友, 後期幾乎沒用
ArrayAdapteradapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, list); ListView listView = (ListView) findViewById(R.id.main_listview); listView.setAdapter(adapter);
不解釋
它雖然叫簡單Adapter, 但是還是比ArrayAdapter復雜點, 靈活性要高些,因為用到機率也不大, 所以不解釋了, 自己可以看看使用方式
//只能用id或本地 SimpleAdapter adapter = new SimpleAdapter(this, list,R.layout.item, new String[]{"title", "img"}, new int[]{R.id.item_tv, R.id.item_iv} ); adapter.setViewBinder(new SimpleAdapter.ViewBinder() { @Override//返回值: 是否綁定完成 public boolean setViewValue(View view, Object data, String textRepresentation) { switch (view.getId()){ //綁定ImageView case R.id.item_iv: ImageView imageView = (ImageView) view; String url = (String) data; new ImageLoader(imageView).execute(url); return true; } return false; } });
我們現在前面做理論說明, 整理好後代碼在最後貼出
首先我們寫個類(MyAdapter) extents BaseAdapter, 因為BaseAdapter為抽象類, 所以需要實現父類的四個方法
@Override//返回數據的數量 public int getCount() { return 0; } @Override//返回當前數據的對象, 參數: 位置 public Object getItem(int position) { return null; } @Override//返回當前數據對象的id(如果沒有可以直接返回position) //參數: 位置 public long getItemId(int position) { return 0; } /* 在這裡非常重要的方法, 每次item(數據項)顯示在手機上時都會調用一次getView, 也就是說它返回的View就是每次顯示在手機上的item */ @Override//參數: 位置, 復用的View(一邊item出去後,再次調用時會傳入該item), 父控件 public View getView(int position, View convertView, ViewGroup parent) { return null; }
1, listView布局的高度必須是定值或match_parent
先去取第1個條目的高度和第2個條目想加,...
計算自身的高度, 所以不要使用wrap_content
2, convertView的復用
3, 減少findViewById的使用次數
盡量減少自己去控制數據源!!(符合MVC設計模式)
貼出代碼, 一般一個完整的Adapter就是下面的格式
public class MyAdapter extends BaseAdapter{
private final LayoutInflater inflater;
private Context context;
private List list;
public MyAdapter(Context context, List list) {
this.context = context;
this.list = list;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override //位置 //重復利用的控件 //父控件
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.item, parent, false);
convertView.setTag(new ViewHolder(convertView));
}
ViewHolder holder = (ViewHolder) convertView.getTag();
Entry entry = list.get(position);
ImageUtil.loadImage(holder.image, "http://tnfs.tngou.net/image" + entry.getImgURL());
return convertView;
}
//批量添加
public void addAll(Collection collection){
list.addAll(collection);
notifyDataSetChanged();
}
//數據清理
public void clear() {
list.clear();
notifyDataSetChanged();
}
//就是View的持有
public static class ViewHolder {
private final TextView text;
private final ImageView image;
public ViewHolder(View itemView) {
text = ((TextView) itemView.findViewById(R.id.item_tv));
image = ((ImageView) itemView.findViewById(R.id.item_iv));
}
}
}
到目前為止我們可以解決顯示本地圖片問題, 但是我們加載網絡數據(尤其是圖片)還是有問題的
解決item顯示圖片錯位的問題和圖片緩存問題 (Lru算法緩存機制)
細心的朋友會發現, 在上面的代碼中, 有下面一句 :
ImageUtil.loadImage(holder.image, "http://tnfs.tngou.net/image" + entry.getImgURL());
裡面的代碼已經解決了這個問題, 我將會把源碼上傳到雲盤供大家下載, 我在源碼中已經加上了注釋 https://yunpan.cn/cMzI4y8SykZrR 訪問密碼 e1dc
自己封裝BaseAdapter
BaseAdapter中有很多代碼都可以復用, 所以我們寫一個通用的Adapter
package com.lulu.day26_listview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.net.IDN;
import java.util.Collection;
import java.util.List;
/**
* Created by Lulu on 2016/9/2.
*/
public abstract class CommonAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private Context context;
private int layoutId;
//數據源
private List list;
public CommonAdapter(Context context, int layoutId, List list) {
this.context = context;
this.layoutId = layoutId;
this.list = list;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public D getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
D d = list.get(position);
Class aClass = (Class) d.getClass();
Field id = null;
try {
id = aClass.getField("id");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
if (id == null) {
try {
id = aClass.getDeclaredField("id");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
if (id != null) {
try {
return (long) id.get(d);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Method getId = null;
try {
getId = aClass.getMethod("getId");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
if (getId == null) {
try {
getId = aClass.getDeclaredMethod("getId");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
if (getId != null) {
try {
return (long) getId.invoke(id);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(layoutId, parent, false);
//如何獲取Vh怎樣獲取它的子類呢?
Class type = (Class) ((ParameterizedType) getClass()
.getGenericSuperclass())
.getActualTypeArguments()[0];
try {
Constructor constructor = type.getConstructor(View.class);
Object o = constructor.newInstance(convertView);
convertView.setTag(o);
} catch (Exception e) {
e.printStackTrace();
}
}
onBindView(list.get(position), (VH) convertView.getTag());
return convertView;
}
public abstract void onBindView(D data, VH holder);
public static class ViewHolder {
private View itemView;
public ViewHolder(View itemView) {
this.itemView = itemView;
}
}
public void addAll(Collection collection) {
list.addAll(collection);
notifyDataSetChanged();
}
public void clear() {
list.clear();
notifyDataSetChanged();
}
public void add(D d) {
list.add(d);
notifyDataSetChanged();
}
public void add(int index, D d) {
list.add(index, d);
notifyDataSetChanged();
}
public void remove (D d) {
list.remove(d);
notifyDataSetInvalidated();
}
public void remove (int index) {
list.remove(index);
notifyDataSetInvalidated();
}
}
開學到現在一直都在學著去搞明白一個簡單的游戲。寫完代碼之後,發現主界面顯示的某些圖片比正常的大了許多。本來以為是代碼寫錯了,反反復復,來來回回的檢查代碼,真心沒有錯誤。。
之前的一遍學習筆記主要就Android滑動沖突中,在不同方向的滑動所造成沖突進行了了解,這種沖突很容易理解,當然也很容易解決。今天,就同方向的滑動所造成的沖突進行一下了解
Android之Http通信——1.初識Http協議Android之Http通信1初識Http協議 引言 正文 Http是什麼鬼 名詞解析 Htt
本文實例講述了Android編程之頁面切換測試。分享給大家供大家參考。具體分析如下:一、軟件平台:win7 + eclipse + sdk二、設計思路:兩個頁面:mian