編輯:關於Android編程
一談起ListView,我想大家都不陌生。而且最近該控件特別紅,像QQ,人人和新浪客戶端裡都有它的影子。
其實實現ListView非常的簡單。
我想大家都用過各種各樣的控件,比如說一個最簡單的TextView,我們都是在布局文件裡加入TextView標簽,然後在Activity裡通過findViewById(int id)方法得到該對象的引用,最後調用TextView類的setText(CharSequence s)方法設置該控件的值。
同樣,對於ListView,我們先在布局文件裡這樣添加標簽:
[html]
<?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="vertical" >
<ListView
android:id="@+id/mylist"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
有了布局文件,然後我們在Activity裡通過findViewById(int id)方法得到ListView對象的引用
[java]
ListView listView = (ListView) findViewById(R.id.mylist);
有了控件還不行,我們可以把ListView看作是一個可以伸縮的容器,我們需要往裡添加內容。作為數據傳輸的橋梁,Adapter封裝了所需的數據,通過調用ListView的方法setAdapter(Adapter a)將數據綁定到ListView中,這樣屏幕上就有數據顯示了。
Adapter是一個接口,定義了許多規范。Android提供了實現該接口的一些方便的類,如ArrayAdapter,CursorAdapter。下面以ArrayAdapter類為例講解如何創建一個Adapter。
[java]
String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
"Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
"Linux", "OS/2" };
// First paramenter - Context
// Second parameter - Layout for the row
// Third parameter - ID of the TextView to which the data is written
// Forth - the Array of data
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, values);
是不是很簡單?在上面的那個構造方法中,一共有四個參數,第一個參數很簡單,就是一個上下文對象Context,第二個參數是描述每一行的布局,這裡使用的是Android自帶的一個簡單布局,第三個參數是該View的id,最後一個是加入的數組。
上面的ArrayAdapter只能在每一行顯示一些文本信息,如果想豐富一下,比如增加圖片等,就需要繼承該類,實現自己的自定義類。
[java
public class MySimpleArrayAdapter extends ArrayAdapter<String> {
private final Context context;
private final String[] values;
public MySimpleArrayAdapter(Context context, String[] values) {
super(context, R.layout.rowlayout, values);
this.context = context;
this.values = values;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.rowlayout, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
textView.setText(values[position]);
String s = values[position];
imageView.setImageResource(R.drawable.ok);
return rowView;
}
}
繼承該類最關鍵的就是復寫getView()方法,因為ListView是通過該方法得到視圖然後顯示在屏幕上的。在本方法中,我們自定義了一個XML布局文件,裡面有TextView標簽和ImageView標簽,分別用來顯示文字和圖片信息,這裡是先得到系統服務LayoutInflater,調用該方法的inflate得到該布局的View,最後通過findViewById()方法獲取TextView和ImageView的對象引用,再給它們賦值返回就結束了。
但是本章的討論不是講解如何實現ListView,但是考慮到有些沒有接觸過ListView的同志,就大概寫了一點demo,同時以此例子為引子,指出該方法存在的一些性能問題。
由於通過調用LayoutInflater的inflate方法獲得的View,其實會產生新的對象,創建對象是很耗時和資源的(內存),另外調用getViewById()方法也會相對耗時和耗資源,雖然其強度不如前者。
所以Android決定,如果代表每一行的View不可見(向下滑動,上面的View被遮住了,即為不可見),那麼它將允許getView方法通過convertView復用該View,達到提升性能的目的。
我們先來看下ArrayAdapter是如何進行優化的。
[java]
public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mResource);
}
private View createViewFromResource(int position, View convertView, ViewGroup parent,
int resource) {
View view;
TextView text;
if (convertView == null) {
view = mInflater.inflate(resource, parent, false);
} else {
view = convertView;
}
try {
if (mFieldId == 0) {
// If no custom field is assigned, assume the whole resource is a TextView
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
text = (TextView) view.findViewById(mFieldId);
}
} catch (ClassCastException e) {
Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
throw new IllegalStateException(
"ArrayAdapter requires the resource ID to be a TextView", e);
}
T item = getItem(position);
if (item instanceof CharSequence) {
text.setText((CharSequence)item);
} else {
text.setText(item.toString());
}
return view;
}
該方法首先判斷傳給該方法的convertView是否為null,如果為null,那麼就調用耗時的inflate方法創建View對象,如果不為空(該convertView是以前inflate過的,只不過被遮住了),就復用該對象,達到了部分優化。
上面之所以說是部分優化,是因為只考慮了優化inflate帶來的負載,而忽略了getViewById()方法引起的性能問題。解決辦法是在自定義Adapter類裡引進靜態內部類ViewHolder,如其名字,該類裡存放我們需要顯示每一行的所有控件,比如TextView,ImageView等。當convertView為空時,我們創建布局文件的View,然後分別得到布局裡的各種控件,再把它們存放在ViewHolder類裡,最後再調用convertView的 setTag(Object o)方法把該類綁定到該類裡。
[java]
public class MyPerformanceArrayAdapter extends ArrayAdapter<String> {
private final Activity context;
private final String[] names;
static class ViewHolder {
public TextView text;
public ImageView image;
}
public MyPerformanceArrayAdapter(Activity context, String[] names) {
super(context, R.layout.rowlayout, names);
this.context = context;
this.names = names;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView; www.2cto.com
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
viewHolder.image = (ImageView) rowView
.findViewById(R.id.ImageView01);
rowView.setTag(viewHolder);
}
ViewHolder holder = (ViewHolder) rowView.getTag();
String s = names[position];
holder.text.setText(s);
if (s.startsWith("Windows7") || s.startsWith("iPhone")
|| s.startsWith("Solaris")) {
holder.image.setImageResource(R.drawable.no);
} else {
holder.image.setImageResource(R.drawable.ok);
}
return rowView;
}
}
根據統計信息,這樣的優化設計,比最初的方法效率上要快15%以上。
大家啊從Eclipse轉到Android Studio很不習慣吧,感覺還是用Eclipse的方法注釋模板比較方便,敲/**加回車,模板就加載出來了,而Android St
今天給大家詳解一下Android中Activity的生命周期,我希望我的講解不像網上大多數文章一樣,基本都是翻譯Android API,過於籠統,相信大家看了,會有一點點
一、Android平台濾鏡濾鏡這個功能在目前的市場上應用很廣泛,發展也非常快,總結起來,基本上有以下三種應用會包含濾鏡功能,都各有所長。 二、相機濾鏡介紹1、相
現在使用Ndk開發的場景還蠻多,游戲引擎、音視頻開發等都能涉及到,以前的工程大部分都是Eclipse的工程目錄,但是App開發現在大部分都是在AndroidStudio開