>  기사  >  Java  >  Android Talk--ListView에서 BaseAdapter 사용

Android Talk--ListView에서 BaseAdapter 사용

高洛峰
高洛峰원래의
2016-12-13 16:41:251311검색

다양한 어댑터를 개발하고 사용해본 결과, 제가 가장 편하게 사용하는 것은 BaseAdapter입니다. 다른 어댑터에 비해 사용하기가 조금 더 번거롭기는 하지만 이를 사용하면 ListView, GridView, 갤러리, Spinner 등 이는 인터페이스 클래스 Adapter에서 직접 상속됩니다. BaseAdapter를 사용하는 경우 많은 메서드를 다시 작성해야 하며, 그 중 가장 중요한 것은 ListView 최적화와 같은 문제가 포함되기 때문입니다. 다른 메서드에 대해서는 링크된 기사를 참조하세요. 🎜>

BaseAdapter는 다른 어댑터와 다소 다릅니다. 다른 어댑터는

SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.list_item, new String[]{"img","title","info",newint[]{R.id.img, R.id.title, R.id.info}});
과 같이 구성 메서드에서 직접 데이터를 설정할 수 있지만 BaseAdapter에서는 BaseAdapter에서 상속된 클래스를 구현하고 다시 작성해야 합니다.

class MyAdapter extends BaseAdapter 
    { 
        private Context context; 
        public MyAdapter(Context context) 
        { 
            this.context = context; 
        } 
        @Override 
        publicint getCount() { 
            // How many items are in the data set represented by this Adapter.(在此适配器中所代表的数据集中的条目数) 
            return0; 
        } 
 
        @Override 
        public Object getItem(int position) { 
            // Get the data item associated with the specified position in the data set.(获取数据集中与指定索引对应的数据项) 
            returnnull; 
        } 
 
        @Override 
        publiclong getItemId(int position) { 
            // Get the row id associated with the specified position in the list.(取在列表中与指定索引对应的行id) 
            return0; 
        } 
 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            // Get a View that displays the data at the specified position in the data set. 
            returnnull; 
        } 
         
    }
등 많은 메소드가 있습니다. 별 어려움은 없으나, getView 메소드를 잘 처리해야 하는데 이것이 가장 번거롭습니다

첫 번째 유형: 처리 없음, 이와 같이 작성하는 것은 권장되지 않습니다. 데이터의 양이 적으면 괜찮지만, 목록 항목의 데이터의 양이 크면 매번 View가 다시 생성되고 리소스가 설정되므로 성능에 심각한 영향을 미칠 수 있으므로 하지 마십시오. 처음부터 이 방법을 사용하지 마세요.

@Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            View item = mInflater.inflate(R.layout.list_item, null); 
            ImageView img = (ImageView)item.findViewById(R.id.img)  
            TextView title = (TextView)item.findViewById(R.id.title); 
            TextView info = (TextView)item.findViewById(R.id.info); 
            img.setImageResource(R.drawable.ic_launcher); 
            title.setText("Hello"); 
            info.setText("world"); 
             
            return item; 
        }
ListView 최적화의 두 번째 유형: ConvertView를 캐시하여 캐시된 contentView를 사용하는 이 방법은 View를 생성하기 전에 해당 View가 캐시에 존재하지 않는지 확인할 수 있습니다. 이미 존재하는 경우 캐시에 있는 뷰를 사용하여 성능을 향상할 수 있습니다.

public View getView(int position, View convertView, ViewGroup parent) { 
            if(convertView == null) 
            { 
                convertView = mInflater.inflate(R.layout.list_item, null); 
            } 
             
            ImageView img = (ImageView)convertView.findViewById(R.id.img)  
            TextView title = (TextView)convertView.findViewById(R.id.title); 
            TextView info = (TextView)ConvertView.findViewById(R.id.info); 
            img.setImageResource(R.drawable.ic_launcher); 
            title.setText("Hello"); 
            info.setText("world"); 
             
            return convertView; 
        }
ListView 최적화의 세 번째 유형: ConvertView+ViewHolder를 통해 구현됩니다. ViewHolder는 정적 클래스입니다. 데이터를 표시하는 뷰(View)를 캐싱하여 UI의 응답속도를 빠르게 한다는 것입니다.

convertView == null 이라고 판단할 때 비어 있으면 목록의 설계된 항목 레이아웃(XML)을 기반으로 ConvertView에 값이 할당되고, viewHolder가 생성되어 ConvertView.View 컨트롤(XML 레이아웃의 컨트롤) 그런 다음 시스템이 두 번째로 ListView를 그릴 때 태그에서 제거될 수 있도록 변환 뷰의 setTag를 사용하여 viewHolder를 태그로 설정합니다. (아래 코드 참조)

convertView가 비어 있지 않은 경우, ConvertView의 getTag()를 사용하여 ViewHolder를 직접 얻습니다. 어댑터를 개선하는 두 가지 방법
//在外面先定义,ViewHolder静态类 
    staticclass ViewHolder 
    { 
        public ImageView img; 
        public TextView title; 
        public TextView info; 
    } 
//然后重写getView 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            ViewHolder holder; 
            if(convertView == null) 
            { 
                holder = new ViewHolder(); 
                convertView = mInflater.inflate(R.layout.list_item, null); 
                holder.img = (ImageView)item.findViewById(R.id.img)  
                holder.title = (TextView)item.findViewById(R.id.title); 
                holder.info = (TextView)item.findViewById(R.id.info); 
                convertView.setTag(holder); 
            }else 
            { 
                holder = (ViewHolder)convertView.getTag(); 
                holder.img.setImageResource(R.drawable.ic_launcher); 
                holder.title.setText("Hello"); 
                holder.info.setText("World"); 
            } 
             
            return convertView; 
        }

여기서 어댑터는 효율적으로 작동하기 위해 두 가지 기술을 사용합니다. - 필요하지 않을 때 View 확장을 방지하기 위해 구현된 getView()에 전달된 ConvertView를 재사용합니다

(번역: 불필요한 뷰를 채우지 않도록 getView() 메서드에 전달된 캐시 변환 뷰 재사용) - 필요하지 않은 경우 findViewById() 호출을 방지하기 위해 ViewHolder 패턴을 사용합니다

(번역: ViewHolder 패턴 사용 findViewById()에 대한 불필요한 호출을 피하기 위해: 너무 많은 findViewById도 성능에 영향을 미칩니다) ViewHolder 클래스의 역할 - ViewHolder 패턴은 getView()에 의해 반환된 뷰의 태그에 데이터 구조를 저장하는 것으로 구성됩니다. 이 데이터 구조에는 참조가 포함되어 있습니다. 데이터를 바인딩하려는 뷰에 연결하여 getView()가 호출될 때마다 findViewById()를 호출하지 않아도 됩니다

(번역: ViewHolder 모드에서 getView() 메서드에 의해 반환된 뷰의 태그 데이터 저장 이 데이터 구조에는

데이터를 바인딩하려는 뷰에 대한 참조가 포함되어 있으므로 getView()가 호출될 때마다 findViewById()를 호출하지 않아도 됩니다.

인스턴스 1: BaseAdapter를 사용하여 ListView 레이아웃

main.xml

list_item.xml

Activity

<?xmlversion="1.0"encoding="utf-8"?> 
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 
 
    <ListView 
        android:id="@+id/lv" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:fastScrollEnabled="true" 
        /> 
 
</LinearLayout>

실행 결과를 사용자 정의합니다. 다음:

<?xmlversion="1.0"encoding="utf-8"?> 
<LinearLayoutxmlns: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/img" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        /> 
    <LinearLayout  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:orientation="vertical" 
        > 
        <TextView 
            android:id="@+id/tv" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:textSize="20sp" 
        /> 
        <TextView  
            android:id="@+id/info" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:textSize="14sp" 
            /> 
    </LinearLayout> 
     
 
</LinearLayout>

package com.loulijun.demo17; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
 
import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
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; 
 
publicclass Demo17Activity extends Activity { 
    private ListView lv; 
    private List<Map<String, Object>> data; 
    @Override 
    publicvoid onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        lv = (ListView)findViewById(R.id.lv); 
        //获取将要绑定的数据设置到data中 
        data = getData(); 
        MyAdapter adapter = new MyAdapter(this); 
        lv.setAdapter(adapter); 
    } 
     
    private List<Map<String, Object>> getData() 
    { 
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 
        Map<String, Object> map; 
        for(int i=0;i<10;i++) 
        { 
            map = new HashMap<String, Object>(); 
            map.put("img", R.drawable.ic_launcher); 
            map.put("title", "跆拳道"); 
            map.put("info", "快乐源于生活..."); 
            list.add(map); 
        } 
        return list; 
    } 
     
    //ViewHolder静态类 
    staticclass ViewHolder 
    { 
        public ImageView img; 
        public TextView title; 
        public TextView info; 
    } 
     
    publicclass MyAdapter extends BaseAdapter 
    {     
        private LayoutInflater mInflater = null; 
        private MyAdapter(Context context) 
        { 
            //根据context上下文加载布局,这里的是Demo17Activity本身,即this 
            this.mInflater = LayoutInflater.from(context); 
        } 
 
        @Override 
        publicint getCount() { 
            //How many items are in the data set represented by this Adapter. 
            //在此适配器中所代表的数据集中的条目数 
            return data.size(); 
        } 
 
        @Override 
        public Object getItem(int position) { 
            // Get the data item associated with the specified position in the data set. 
            //获取数据集中与指定索引对应的数据项 
            return position; 
        } 
 
        @Override 
        publiclong getItemId(int position) { 
            //Get the row id associated with the specified position in the list. 
            //获取在列表中与指定索引对应的行id 
            return position; 
        } 
         
        //Get a View that displays the data at the specified position in the data set. 
        //获取一个在数据集中指定索引的视图来显示数据 
        @Override 
        public View getView(int position, View convertView, ViewGroup parent) { 
            ViewHolder holder = null; 
            //如果缓存convertView为空,则需要创建View 
            if(convertView == null) 
            { 
                holder = new ViewHolder(); 
                //根据自定义的Item布局加载布局 
                convertView = mInflater.inflate(R.layout.list_item, null); 
                holder.img = (ImageView)convertView.findViewById(R.id.img); 
                holder.title = (TextView)convertView.findViewById(R.id.tv); 
                holder.info = (TextView)convertView.findViewById(R.id.info); 
                //将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag 
                convertView.setTag(holder); 
            }else 
            { 
                holder = (ViewHolder)convertView.getTag(); 
            } 
            holder.img.setBackgroundResource((Integer)data.get(position).get("img")); 
            holder.title.setText((String)data.get(position).get("title")); 
            holder.info.setText((String)data.get(position).get("info")); 
             
            return convertView; 
        } 
         
    } 
}
예제 2: 갤러리에 BaseAdapter 적용

main.xml

Android Talk--ListView에서 BaseAdapter 사용

활동: 여기에는 getView가 없습니다. 부분 최적화는 오랫동안 디버깅을 한 후에도 아직 조정하지 않았습니다. 아직 가장 기본적인 방법을 사용하고 있습니다. 이미지 리소스가 많으면 메모리 부족 오류가 발생하기 때문에 갤러리의 메모리 누수에 대해 특별한 시간을 찾아 작성하겠습니다.

작동 효과: 원리는 동일하지만 레이아웃이 로드됩니다. 가끔 차이가 있을 수 있지만, 이 작은 차이도 충분히 짜증납니다

<?xmlversion="1.0"encoding="utf-8"?> 
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"> 
     
    <ImageView  
        android:id="@+id/img" 
        android:layout_width="480px" 
        android:layout_height="480px" 
        android:layout_gravity="center" 
        /> 
    <Gallery  
        android:id="@+id/gallery" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:spacing="3dp" 
        android:layout_gravity="bottom" 
        /> 
 
</LinearLayout>

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.